This commit was manufactured by cvs2svn to create branch 'vserver'.
authorPlanet-Lab Support <support@planet-lab.org>
Mon, 8 Aug 2005 21:03:49 +0000 (21:03 +0000)
committerPlanet-Lab Support <support@planet-lab.org>
Mon, 8 Aug 2005 21:03:49 +0000 (21:03 +0000)
158 files changed:
Documentation/DocBook/stylesheet.xsl [new file with mode: 0644]
Documentation/aoe/udev-install.sh [new file with mode: 0644]
Documentation/arm/Samsung-S3C24XX/H1940.txt [new file with mode: 0644]
Documentation/arm/Samsung-S3C24XX/SMDK2440.txt [new file with mode: 0644]
Documentation/dvb/README.flexcop [new file with mode: 0644]
Documentation/i2c/busses/i2c-ali1535 [new file with mode: 0644]
Documentation/i2c/busses/i2c-ali1563 [new file with mode: 0644]
Documentation/i2c/busses/i2c-ali15x3 [new file with mode: 0644]
Documentation/i2c/busses/i2c-amd756 [new file with mode: 0644]
Documentation/i2c/busses/i2c-i810 [new file with mode: 0644]
Documentation/i2c/busses/i2c-parport-light [new file with mode: 0644]
Documentation/i2c/busses/i2c-pca-isa [new file with mode: 0644]
Documentation/i2c/busses/i2c-prosavage [new file with mode: 0644]
Documentation/i2c/busses/i2c-savage4 [new file with mode: 0644]
Documentation/i2c/busses/i2c-sis5595 [new file with mode: 0644]
Documentation/i2c/busses/i2c-sis630 [new file with mode: 0644]
Documentation/i2c/busses/i2c-via [new file with mode: 0644]
Documentation/i2c/busses/i2c-voodoo3 [new file with mode: 0644]
Documentation/kref.txt [new file with mode: 0644]
Documentation/scsi/ChangeLog.lpfc [new file with mode: 0644]
Documentation/scsi/lpfc.txt [new file with mode: 0644]
Documentation/sound/alsa/VIA82xx-mixer.txt [new file with mode: 0644]
Documentation/sound/alsa/hda_codec.txt [new file with mode: 0644]
arch/arm/common/Kconfig [new file with mode: 0644]
arch/arm/common/sharpsl_param.c [new file with mode: 0644]
arch/arm/mm/abort-macro.S [new file with mode: 0644]
arch/frv/Kconfig.debug [new file with mode: 0644]
arch/i386/kernel/syscall_table.S [new file with mode: 0644]
arch/i386/kernel/vsyscall-note.S [new file with mode: 0644]
arch/i386/lib/putuser.S [new file with mode: 0644]
arch/ia64/sn/kernel/xp_main.c [new file with mode: 0644]
arch/ia64/sn/kernel/xp_nofault.S [new file with mode: 0644]
arch/ppc/configs/hdpu_defconfig [new file with mode: 0644]
arch/ppc/configs/mpc834x_sys_defconfig [new file with mode: 0644]
arch/ppc/configs/radstone_ppc7d_defconfig [new file with mode: 0644]
arch/ppc/platforms/83xx/Makefile [new file with mode: 0644]
arch/ppc/syslib/m82xx_pci.h [new file with mode: 0644]
arch/sh64/kernel/module.c [new file with mode: 0644]
arch/sparc64/lib/csum_copy.S [new file with mode: 0644]
arch/sparc64/lib/csum_copy_from_user.S [new file with mode: 0644]
arch/sparc64/lib/csum_copy_to_user.S [new file with mode: 0644]
arch/sparc64/lib/rwsem.S [new file with mode: 0644]
arch/um/drivers/slip_common.c [new file with mode: 0644]
arch/um/drivers/slip_common.h [new file with mode: 0644]
arch/um/include/sysdep-i386/faultinfo.h [new file with mode: 0644]
arch/um/include/sysdep-i386/skas_ptrace.h [new file with mode: 0644]
arch/um/include/sysdep-ia64/skas_ptrace.h [new file with mode: 0644]
arch/um/include/sysdep-ppc/skas_ptrace.h [new file with mode: 0644]
arch/um/include/sysdep-x86_64/faultinfo.h [new file with mode: 0644]
arch/um/include/sysdep-x86_64/skas_ptrace.h [new file with mode: 0644]
arch/um/kernel/initrd.c [new file with mode: 0644]
arch/um/sys-x86_64/um_module.c [new file with mode: 0644]
drivers/char/mbcs.h [new file with mode: 0644]
drivers/md/dm-bio-record.h [new file with mode: 0644]
drivers/media/dvb/b2c2/flexcop-dma.c [new file with mode: 0644]
drivers/media/dvb/b2c2/flexcop-eeprom.c [new file with mode: 0644]
drivers/media/dvb/b2c2/flexcop-hw-filter.c [new file with mode: 0644]
drivers/media/dvb/b2c2/flexcop-misc.c [new file with mode: 0644]
drivers/media/dvb/b2c2/flexcop-reg.h [new file with mode: 0644]
drivers/media/dvb/b2c2/flexcop-sram.c [new file with mode: 0644]
drivers/media/dvb/b2c2/flexcop-usb.h [new file with mode: 0644]
drivers/media/dvb/b2c2/flexcop.h [new file with mode: 0644]
drivers/media/dvb/bt8xx/dst_ca.h [new file with mode: 0644]
drivers/media/video/mt20xx.c [new file with mode: 0644]
drivers/misc/hdpuftrs/Makefile [new file with mode: 0644]
drivers/misc/hdpuftrs/hdpu_cpustate.c [new file with mode: 0644]
drivers/misc/hdpuftrs/hdpu_nexus.c [new file with mode: 0644]
drivers/net/wireless/atmel.h [new file with mode: 0644]
drivers/serial/jsm/Makefile [new file with mode: 0644]
drivers/sh/Makefile [new file with mode: 0644]
drivers/sh/superhyway/Makefile [new file with mode: 0644]
drivers/sh/superhyway/superhyway-sysfs.c [new file with mode: 0644]
drivers/sh/superhyway/superhyway.c [new file with mode: 0644]
drivers/usb/misc/sisusbvga/Kconfig [new file with mode: 0644]
drivers/usb/misc/sisusbvga/Makefile [new file with mode: 0644]
drivers/usb/mon/Kconfig [new file with mode: 0644]
drivers/usb/mon/Makefile [new file with mode: 0644]
drivers/video/geode/display_gx1.c [new file with mode: 0644]
drivers/video/geode/display_gx1.h [new file with mode: 0644]
drivers/video/geode/geodefb.h [new file with mode: 0644]
drivers/video/geode/video_cs5530.c [new file with mode: 0644]
drivers/video/geode/video_cs5530.h [new file with mode: 0644]
drivers/video/imxfb.h [new file with mode: 0644]
drivers/video/nvidia/nv_dma.h [new file with mode: 0644]
drivers/xen/Makefile [new file with mode: 0644]
drivers/xen/balloon/Makefile [new file with mode: 0644]
drivers/xen/balloon/balloon.c [new file with mode: 0644]
drivers/xen/blkback/Makefile [new file with mode: 0644]
drivers/xen/blkback/blkback.c [new file with mode: 0644]
drivers/xen/blkback/common.h [new file with mode: 0644]
drivers/xen/blkback/interface.c [new file with mode: 0644]
drivers/xen/blkback/vbd.c [new file with mode: 0644]
drivers/xen/blkfront/Kconfig [new file with mode: 0644]
drivers/xen/blkfront/Makefile [new file with mode: 0644]
drivers/xen/blkfront/blkfront.c [new file with mode: 0644]
drivers/xen/blkfront/block.h [new file with mode: 0644]
drivers/xen/blkfront/vbd.c [new file with mode: 0644]
drivers/xen/blktap/Makefile [new file with mode: 0644]
drivers/xen/blktap/blktap.c [new file with mode: 0644]
drivers/xen/console/Makefile [new file with mode: 0644]
drivers/xen/console/console.c [new file with mode: 0644]
drivers/xen/evtchn/Makefile [new file with mode: 0644]
drivers/xen/evtchn/evtchn.c [new file with mode: 0644]
drivers/xen/netback/Makefile [new file with mode: 0644]
drivers/xen/netback/common.h [new file with mode: 0644]
drivers/xen/netback/interface.c [new file with mode: 0644]
drivers/xen/netback/netback.c [new file with mode: 0644]
drivers/xen/netfront/Kconfig [new file with mode: 0644]
drivers/xen/netfront/Makefile [new file with mode: 0644]
drivers/xen/netfront/netfront.c [new file with mode: 0644]
drivers/xen/privcmd/Makefile [new file with mode: 0644]
drivers/xen/privcmd/privcmd.c [new file with mode: 0644]
include/asm-arm/arch-imx/imxfb.h [new file with mode: 0644]
include/asm-arm/arch-omap/board-voiceblue.h [new file with mode: 0644]
include/asm-arm/arch-s3c2410/otom-map.h [new file with mode: 0644]
include/asm-arm/mach/sharpsl_param.h [new file with mode: 0644]
include/asm-generic/ipc.h [new file with mode: 0644]
include/asm-i386/seccomp.h [new file with mode: 0644]
include/asm-ia64/sn/tioca.h [new file with mode: 0644]
include/asm-ia64/sn/tiocx.h [new file with mode: 0644]
include/asm-mips/vr41xx/pci.h [new file with mode: 0644]
include/asm-mips/vr41xx/siu.h [new file with mode: 0644]
include/asm-ppc/suspend.h [new file with mode: 0644]
include/asm-sh/cpu-sh4/timer.h [new file with mode: 0644]
include/asm-sparc64/rwsem-const.h [new file with mode: 0644]
include/asm-um/elf-i386.h [new file with mode: 0644]
include/asm-um/elf-x86_64.h [new file with mode: 0644]
include/asm-x86_64/seccomp.h [new file with mode: 0644]
include/linux/compiler-gcc4.h [new file with mode: 0644]
include/linux/cryptohash.h [new file with mode: 0644]
include/linux/hdpu_features.h [new file with mode: 0644]
include/linux/ip_mp_alg.h [new file with mode: 0644]
include/linux/patchkey.h [new file with mode: 0644]
include/linux/reboot_fixups.h [new file with mode: 0644]
include/linux/sort.h [new file with mode: 0644]
include/linux/superhyway.h [new file with mode: 0644]
include/linux/tc_act/tc_defact.h [new file with mode: 0644]
include/linux/tc_ematch/tc_em_cmp.h [new file with mode: 0644]
include/linux/tc_ematch/tc_em_meta.h [new file with mode: 0644]
include/linux/tc_ematch/tc_em_nbyte.h [new file with mode: 0644]
include/net/ieee80211.h [new file with mode: 0644]
kernel/seccomp.c [new file with mode: 0644]
lib/halfmd4.c [new file with mode: 0644]
net/ipv4/multipath.c [new file with mode: 0644]
scripts/kconfig/.kxgettext.o.cmd [new file with mode: 0644]
scripts/kconfig/POTFILES.in [new file with mode: 0644]
scripts/kconfig/kxgettext.c [new file with mode: 0644]
scripts/kconfig/kxgettext.o [new file with mode: 0644]
scripts/show_delta [new file with mode: 0644]
sound/core/rawmidi_compat.c [new file with mode: 0644]
sound/core/seq/seq_compat.c [new file with mode: 0644]
sound/core/timer_compat.c [new file with mode: 0644]
sound/parisc/harmony.h [new file with mode: 0644]
sound/pci/emu10k1/p16v.h [new file with mode: 0644]
sound/pci/hda/patch_cmedia.c [new file with mode: 0644]
sound/pci/ice1712/juli.c [new file with mode: 0644]
sound/pci/ice1712/juli.h [new file with mode: 0644]
sound/pci/ice1712/phase.h [new file with mode: 0644]

diff --git a/Documentation/DocBook/stylesheet.xsl b/Documentation/DocBook/stylesheet.xsl
new file mode 100644 (file)
index 0000000..e14c21d
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<stylesheet xmlns="http://www.w3.org/1999/XSL/Transform" version="1.0">
+<param name="chunk.quietly">1</param>
+<param name="funcsynopsis.style">ansi</param>
+</stylesheet>
diff --git a/Documentation/aoe/udev-install.sh b/Documentation/aoe/udev-install.sh
new file mode 100644 (file)
index 0000000..6449911
--- /dev/null
@@ -0,0 +1,30 @@
+# install the aoe-specific udev rules from udev.txt into 
+# the system's udev configuration
+# 
+
+me="`basename $0`"
+
+# find udev.conf, often /etc/udev/udev.conf
+# (or environment can specify where to find udev.conf)
+#
+if test -z "$conf"; then
+       if test -r /etc/udev/udev.conf; then
+               conf=/etc/udev/udev.conf
+       else
+               conf="`find /etc -type f -name udev.conf 2> /dev/null`"
+               if test -z "$conf" || test ! -r "$conf"; then
+                       echo "$me Error: no udev.conf found" 1>&2
+                       exit 1
+               fi
+       fi
+fi
+
+# find the directory where udev rules are stored, often
+# /etc/udev/rules.d
+#
+rules_d="`sed -n '/^udev_rules=/{ s!udev_rules=!!; s!\"!!g; p; }' $conf`"
+if test -z "$rules_d" || test ! -d "$rules_d"; then
+       echo "$me Error: cannot find udev rules directory" 1>&2
+       exit 1
+fi
+sh -xc "cp `dirname $0`/udev.txt $rules_d/60-aoe.rules"
diff --git a/Documentation/arm/Samsung-S3C24XX/H1940.txt b/Documentation/arm/Samsung-S3C24XX/H1940.txt
new file mode 100644 (file)
index 0000000..d6b1de9
--- /dev/null
@@ -0,0 +1,40 @@
+               HP IPAQ H1940
+               =============
+
+http://www.handhelds.org/projects/h1940.html
+
+Introduction
+------------
+
+  The HP H1940 is a S3C2410 based handheld device, with
+  bluetooth connectivity.
+
+
+Support
+-------
+
+  A variety of information is available
+
+  handhelds.org project page:
+
+    http://www.handhelds.org/projects/h1940.html
+
+  handhelds.org wiki page:
+
+    http://handhelds.org/moin/moin.cgi/HpIpaqH1940
+
+  Herbert Pötzl pages:
+
+    http://vserver.13thfloor.at/H1940/
+
+
+Maintainers
+-----------
+
+  This project is being maintained and developed by a variety
+  of people, including Ben Dooks, Arnaud Patard, and Herbert Pötzl.
+
+  Thanks to the many others who have also provided support.
+
+
+(c) 2005 Ben Dooks
\ No newline at end of file
diff --git a/Documentation/arm/Samsung-S3C24XX/SMDK2440.txt b/Documentation/arm/Samsung-S3C24XX/SMDK2440.txt
new file mode 100644 (file)
index 0000000..32e1eae
--- /dev/null
@@ -0,0 +1,56 @@
+               Samsung/Meritech SMDK2440
+               =========================
+
+Introduction
+------------
+
+  The SMDK2440 is a two part evaluation board for the Samsung S3C2440
+  processor. It includes support for LCD, SmartMedia, Audio, SD and
+  10MBit Ethernet, and expansion headers for various signals, including
+  the camera and unused GPIO.
+
+
+Configuration
+-------------
+
+  To set the default configuration, use `make smdk2440_defconfig` which
+  will configure the common features of this board, or use
+  `make s3c2410_config` to include support for all s3c2410/s3c2440 machines
+
+
+Support
+-------
+
+  Ben Dooks' SMDK2440 site at http://www.fluff.org/ben/smdk2440/ which
+  includes linux based USB download tools.
+
+  Some of the h1940 patches that can be found from the H1940 project
+  site at http://www.handhelds.org/projects/h1940.html can also be
+  applied to this board.
+
+
+Peripherals
+-----------
+
+  There is no current support for any of the extra peripherals on the
+  base-board itself.
+
+
+MTD
+---
+
+  The NAND flash should be supported by the in kernel MTD NAND support,
+  NOR flash will be added later.
+
+
+Maintainers
+-----------
+
+  This board is being maintained by Ben Dooks, for more info, see
+  http://www.fluff.org/ben/smdk2440/
+
+  Many thanks to Dimitry Andric of TomTom for the loan of the SMDK2440,
+  and to Simtec Electronics for allowing me time to work on this.
+
+
+(c) 2004 Ben Dooks
\ No newline at end of file
diff --git a/Documentation/dvb/README.flexcop b/Documentation/dvb/README.flexcop
new file mode 100644 (file)
index 0000000..a50c70f
--- /dev/null
@@ -0,0 +1,205 @@
+This README escorted the skystar2-driver rewriting procedure. It describes the
+state of the new flexcop-driver set and some internals are written down here
+too.
+
+This document hopefully describes things about the flexcop and its
+device-offsprings. Goal was to write an easy-to-write and easy-to-read set of
+drivers based on the skystar2.c and other information.
+
+Remark: flexcop-pci.c was a copy of skystar2.c, but every line has been
+touched and rewritten.
+
+History & News
+==============
+  2005-04-01 - correct USB ISOC transfers (thanks to Vadim Catana)
+
+
+
+
+General coding processing
+=========================
+
+We should proceed as follows (as long as no one complains):
+
+0) Think before start writing code!
+
+1) rewriting the skystar2.c with the help of the flexcop register descriptions
+and splitting up the files to a pci-bus-part and a flexcop-part.
+The new driver will be called b2c2-flexcop-pci.ko/b2c2-flexcop-usb.ko for the
+device-specific part and b2c2-flexcop.ko for the common flexcop-functions.
+
+2) Search for errors in the leftover of flexcop-pci.c (compare with pluto2.c
+and other pci drivers)
+
+3) make some beautification (see 'Improvements when rewriting (refactoring) is
+done')
+
+4) Testing the new driver and maybe substitute the skystar2.c with it, to reach
+a wider tester audience.
+
+5) creating an usb-bus-part using the already written flexcop code for the pci
+card.
+
+Idea: create a kernel-object for the flexcop and export all important
+functions. This option saves kernel-memory, but maybe a lot of functions have
+to be exported to kernel namespace.
+
+
+Current situation
+=================
+
+0) Done :)
+1) Done (some minor issues left)
+2) Done
+3) Not ready yet, more information is necessary
+4) next to be done (see the table below)
+5) USB driver is working (yes, there are some minor issues)
+
+What seems to be ready?
+-----------------------
+
+1) Rewriting
+1a) i2c is cut off from the flexcop-pci.c and seems to work
+1b) moved tuner and demod stuff from flexcop-pci.c to flexcop-tuner-fe.c
+1c) moved lnb and diseqc stuff from flexcop-pci.c to flexcop-tuner-fe.c
+1e) eeprom (reading MAC address)
+1d) sram (no dynamic sll size detection (commented out) (using default as JJ told me))
+1f) misc. register accesses for reading parameters (e.g. resetting, revision)
+1g) pid/mac filter (flexcop-hw-filter.c)
+1i) dvb-stuff initialization in flexcop.c (done)
+1h) dma stuff (now just using the size-irq, instead of all-together, to be done)
+1j) remove flexcop initialization from flexcop-pci.c completely (done)
+1l) use a well working dma IRQ method (done, see 'Known bugs and problems and TODO')
+1k) cleanup flexcop-files (remove unused EXPORT_SYMBOLs, make static from
+non-static where possible, moved code to proper places)
+
+2) Search for errors in the leftover of flexcop-pci.c (partially done)
+5a) add MAC address reading
+5c) feeding of ISOC data to the software demux (format of the isochronous data
+and speed optimization, no real error) (thanks to Vadim Catana)
+
+What to do in the near future?
+--------------------------------------
+(no special order here)
+
+5) USB driver
+5b) optimize isoc-transfer (submitting/killing isoc URBs when transfer is starting)
+
+Testing changes
+---------------
+
+O             = item is working
+P             = item is partially working
+X             = item is not working
+N             = item does not apply here
+<empty field> = item need to be examined
+
+       | PCI                               | USB
+item   | mt352 | nxt2002 | stv0299 | mt312 | mt352 | nxt2002 | stv0299 | mt312
+-------+-------+---------+---------+-------+-------+---------+---------+-------
+1a)    | O     |         |         |       | N     | N       | N       | N
+1b)    | O     |         |         |       |       |         | O       |
+1c)    | N     | N       |         |       | N     | N       | O       |
+1d)    |                 O                 |                 O
+1e)    |                 O                 |                 O
+1f)    |                                   P
+1g)    |                                   O
+1h)    |                 P                 |
+1i)    |                 O                 |                 N
+1j)    |                 O                 |                 N
+1l)    |                 O                 |                 N
+2)     |                 O                 |                 N
+5a)    |                 N                 |                 O
+5b)*   |                 N                 |
+5c)    |                 N                 |                 O
+
+* - not done yet
+
+Known bugs and problems and TODO
+--------------------------------
+
+1g/h/l) when pid filtering is enabled on the pci card
+
+DMA usage currently:
+  The DMA is splitted in 2 equal-sized subbuffers. The Flexcop writes to first
+  address and triggers an IRQ when it's full and starts writing to the second
+  address. When the second address is full, the IRQ is triggered again, and
+  the flexcop writes to first address again, and so on.
+  The buffersize of each address is currently 640*188 bytes.
+
+  Problem is, when using hw-pid-filtering and doing some low-bandwidth
+  operation (like scanning) the buffers won't be filled enough to trigger
+  the IRQ. That's why:
+
+  When PID filtering is activated, the timer IRQ is used. Every 1.97 ms the IRQ
+  is triggered.  Is the current write address of DMA1 different to the one
+  during the last IRQ, then the data is passed to the demuxer.
+
+  There is an additional DMA-IRQ-method: packet count IRQ. This isn't
+  implemented correctly yet.
+
+  The solution is to disable HW PID filtering, but I don't know how the DVB
+  API software demux behaves on slow systems with 45MBit/s TS.
+
+Solved bugs :)
+--------------
+1g) pid-filtering (somehow pid index 4 and 5 (EMM_PID and ECM_PID) aren't
+working)
+SOLUTION: also index 0 was affected, because net_translation is done for
+these indexes by default
+
+5b) isochronous transfer does only work in the first attempt (for the Sky2PC
+USB, Air2PC is working) SOLUTION: the flexcop was going asleep and never really
+woke up again (don't know if this need fixes, see
+flexcop-fe-tuner.c:flexcop_sleep)
+
+NEWS: when the driver is loaded and unloaded and loaded again (w/o doing
+anything in the while the driver is loaded the first time), no transfers take
+place anymore.
+
+Improvements when rewriting (refactoring) is done
+=================================================
+
+- split sleeping of the flexcop (misc_204.ACPI3_sig = 1;) from lnb_control
+  (enable sleeping for other demods than dvb-s)
+- add support for CableStar (stv0297 Microtune 203x/ALPS) (almost done, incompatibilities with the Nexus-CA)
+
+Debugging
+---------
+- add verbose debugging to skystar2.c (dump the reg_dw_data) and compare it
+  with this flexcop, this is important, because i2c is now using the
+  flexcop_ibi_value union from flexcop-reg.h (do you have a better idea for
+  that, please tell us so).
+
+Everything which is identical in the following table, can be put into a common
+flexcop-module.
+
+                  PCI                  USB
+-------------------------------------------------------------------------------
+Different:
+Register access:  accessing IO memory  USB control message
+I2C bus:          I2C bus of the FC    USB control message
+Data transfer:    DMA                  isochronous transfer
+EEPROM transfer:  through i2c bus      not clear yet
+
+Identical:
+Streaming:                 accessing registers
+PID Filtering:             accessing registers
+Sram destinations:         accessing registers
+Tuner/Demod:                     I2C bus
+DVB-stuff:            can be written for common use
+
+Acknowledgements (just for the rewriting part)
+================
+
+Bjarne Steinsbo thought a lot in the first place of the pci part for this code
+sharing idea.
+
+Andreas Oberritter for providing a recent PCI initialization template
+(pluto2.c).
+
+Boleslaw Ciesielski for pointing out a problem with firmware loader.
+
+Vadim Catana for correcting the USB transfer.
+
+comments, critics and ideas to linux-dvb@linuxtv.org.
diff --git a/Documentation/i2c/busses/i2c-ali1535 b/Documentation/i2c/busses/i2c-ali1535
new file mode 100644 (file)
index 0000000..0db3b4c
--- /dev/null
@@ -0,0 +1,42 @@
+Kernel driver i2c-ali1535
+
+Supported adapters:
+  * Acer Labs, Inc. ALI 1535 (south bridge)
+    Datasheet: Now under NDA
+       http://www.ali.com.tw/eng/support/datasheet_request.php
+
+Authors:
+       Frodo Looijaard <frodol@dds.nl>, 
+       Philip Edelbrock <phil@netroedge.com>,
+       Mark D. Studebaker <mdsxyz123@yahoo.com>,
+       Dan Eaton <dan.eaton@rocketlogix.com>,
+       Stephen Rousset<stephen.rousset@rocketlogix.com>
+                                                                                               
+Description
+-----------
+
+This is the driver for the SMB Host controller on Acer Labs Inc. (ALI)
+M1535 South Bridge.
+
+The M1535 is a South bridge for portable systems. It is very similar to the
+M15x3 South bridges also produced by Acer Labs Inc.  Some of the registers
+within the part have moved and some have been redefined slightly.
+Additionally, the sequencing of the SMBus transactions has been modified to
+be more consistent with the sequencing recommended by the manufacturer and
+observed through testing.  These changes are reflected in this driver and
+can be identified by comparing this driver to the i2c-ali15x3 driver. For
+an overview of these chips see http://www.acerlabs.com
+
+The SMB controller is part of the M7101 device, which is an ACPI-compliant
+Power Management Unit (PMU).
+
+The whole M7101 device has to be enabled for the SMB to work. You can't
+just enable the SMB alone. The SMB and the ACPI have separate I/O spaces.
+We make sure that the SMB is enabled. We leave the ACPI alone.
+
+
+Features
+--------
+
+This driver controls the SMB Host only. This driver does not use
+interrupts.
diff --git a/Documentation/i2c/busses/i2c-ali1563 b/Documentation/i2c/busses/i2c-ali1563
new file mode 100644 (file)
index 0000000..99ad4b9
--- /dev/null
@@ -0,0 +1,27 @@
+Kernel driver i2c-ali1563
+
+Supported adapters:
+  * Acer Labs, Inc. ALI 1563 (south bridge)
+    Datasheet: Now under NDA
+       http://www.ali.com.tw/eng/support/datasheet_request.php
+
+Author: Patrick Mochel <mochel@digitalimplant.org>
+
+Description
+-----------
+
+This is the driver for the SMB Host controller on Acer Labs Inc. (ALI)
+M1563 South Bridge.
+
+For an overview of these chips see http://www.acerlabs.com
+
+The M1563 southbridge is deceptively similar to the M1533, with a few
+notable exceptions. One of those happens to be the fact they upgraded the
+i2c core to be SMBus 2.0 compliant, and happens to be almost identical to
+the i2c controller found in the Intel 801 south bridges. 
+
+Features
+--------
+
+This driver controls the SMB Host only. This driver does not use
+interrupts.
diff --git a/Documentation/i2c/busses/i2c-ali15x3 b/Documentation/i2c/busses/i2c-ali15x3
new file mode 100644 (file)
index 0000000..ff28d38
--- /dev/null
@@ -0,0 +1,112 @@
+Kernel driver i2c-ali15x3
+
+Supported adapters:
+  * Acer Labs, Inc. ALI 1533 and 1543C (south bridge)
+    Datasheet: Now under NDA
+       http://www.ali.com.tw/eng/support/datasheet_request.php
+
+Authors:
+       Frodo Looijaard <frodol@dds.nl>, 
+       Philip Edelbrock <phil@netroedge.com>, 
+       Mark D. Studebaker <mdsxyz123@yahoo.com>
+
+Module Parameters
+-----------------
+
+* force_addr: int
+  Initialize the base address of the i2c controller
+
+
+Notes
+-----
+
+The force_addr parameter is useful for boards that don't set the address in
+the BIOS. Does not do a PCI force; the device must still be present in
+lspci. Don't use this unless the driver complains that the base address is
+not set.
+
+Example: 'modprobe i2c-ali15x3 force_addr=0xe800'
+
+SMBus periodically hangs on ASUS P5A motherboards and can only be cleared
+by a power cycle. Cause unknown (see Issues below).
+
+
+Description
+-----------
+
+This is the driver for the SMB Host controller on Acer Labs Inc. (ALI)
+M1541 and M1543C South Bridges.
+
+The M1543C is a South bridge for desktop systems.
+The M1541 is a South bridge for portable systems.
+They are part of the following ALI chipsets:
+   
+ * "Aladdin Pro 2" includes the M1621 Slot 1 North bridge with AGP and 
+               100MHz CPU Front Side bus
+ * "Aladdin V" includes the M1541 Socket 7 North bridge with AGP and 100MHz 
+               CPU Front Side bus
+   Some Aladdin V motherboards:
+       Asus P5A
+       Atrend ATC-5220
+       BCM/GVC VP1541
+       Biostar M5ALA
+       Gigabyte GA-5AX (** Generally doesn't work because the BIOS doesn't
+                            enable the 7101 device! **)
+       Iwill XA100 Plus
+       Micronics C200
+       Microstar (MSI) MS-5169
+
+  * "Aladdin IV" includes the M1541 Socket 7 North bridge
+               with host bus up to 83.3 MHz.
+
+For an overview of these chips see http://www.acerlabs.com. At this time the
+full data sheets on the web site are password protected, however if you
+contact the ALI office in San Jose they may give you the password.
+
+The M1533/M1543C devices appear as FOUR separate devices on the PCI bus. An
+output of lspci will show something similar to the following:
+
+  00:02.0 USB Controller: Acer Laboratories Inc. M5237 (rev 03)
+  00:03.0 Bridge: Acer Laboratories Inc. M7101      <= THIS IS THE ONE WE NEED
+  00:07.0 ISA bridge: Acer Laboratories Inc. M1533 (rev c3)
+  00:0f.0 IDE interface: Acer Laboratories Inc. M5229 (rev c1)
+
+** IMPORTANT **
+** If you have a M1533 or M1543C on the board and you get
+** "ali15x3: Error: Can't detect ali15x3!"
+** then run lspci.
+** If you see the 1533 and 5229 devices but NOT the 7101 device,
+** then you must enable ACPI, the PMU, SMB, or something similar
+** in the BIOS. 
+** The driver won't work if it can't find the M7101 device.
+
+The SMB controller is part of the M7101 device, which is an ACPI-compliant
+Power Management Unit (PMU).
+
+The whole M7101 device has to be enabled for the SMB to work. You can't
+just enable the SMB alone. The SMB and the ACPI have separate I/O spaces.
+We make sure that the SMB is enabled. We leave the ACPI alone.
+
+Features 
+-------- 
+
+This driver controls the SMB Host only. The SMB Slave
+controller on the M15X3 is not enabled. This driver does not use
+interrupts.
+
+
+Issues
+------
+
+This driver requests the I/O space for only the SMB
+registers. It doesn't use the ACPI region.
+
+On the ASUS P5A motherboard, there are several reports that
+the SMBus will hang and this can only be resolved by
+powering off the computer. It appears to be worse when the board
+gets hot, for example under heavy CPU load, or in the summer.
+There may be electrical problems on this board.
+On the P5A, the W83781D sensor chip is on both the ISA and
+SMBus. Therefore the SMBus hangs can generally be avoided
+by accessing the W83781D on the ISA bus only.
+
diff --git a/Documentation/i2c/busses/i2c-amd756 b/Documentation/i2c/busses/i2c-amd756
new file mode 100644 (file)
index 0000000..67f3087
--- /dev/null
@@ -0,0 +1,25 @@
+Kernel driver i2c-amd756
+
+Supported adapters:
+  * AMD 756
+  * AMD 766
+  * AMD 768
+  * AMD 8111
+    Datasheets: Publicly available on AMD website
+
+  * nVidia nForce
+    Datasheet: Unavailable
+
+Authors:
+       Frodo Looijaard <frodol@dds.nl>,
+       Philip Edelbrock <phil@netroedge.com> 
+
+Description
+-----------
+
+This driver supports the AMD 756, 766, 768 and 8111 Peripheral Bus
+Controllers, and the nVidia nForce.
+
+Note that for the 8111, there are two SMBus adapters. The SMBus 1.0 adapter
+is supported by this driver, and the SMBus 2.0 adapter is supported by the
+i2c-amd8111 driver.
diff --git a/Documentation/i2c/busses/i2c-i810 b/Documentation/i2c/busses/i2c-i810
new file mode 100644 (file)
index 0000000..0544eb3
--- /dev/null
@@ -0,0 +1,46 @@
+Kernel driver i2c-i810
+
+Supported adapters:
+  * Intel 82810, 82810-DC100, 82810E, and 82815 (GMCH)
+
+Authors: 
+       Frodo Looijaard <frodol@dds.nl>, 
+       Philip Edelbrock <phil@netroedge.com>,
+        Kyösti Mälkki <kmalkki@cc.hut.fi>,
+       Ralph Metzler <rjkm@thp.uni-koeln.de>,
+       Mark D. Studebaker <mdsxyz123@yahoo.com>
+
+Main contact: Mark Studebaker <mdsxyz123@yahoo.com>
+
+Description 
+----------- 
+
+WARNING: If you have an '810' or '815' motherboard, your standard I2C
+temperature sensors are most likely on the 801's I2C bus. You want the
+i2c-i801 driver for those, not this driver.
+
+Now for the i2c-i810...
+
+The GMCH chip contains two I2C interfaces.
+
+The first interface is used for DDC (Data Display Channel) which is a
+serial channel through the VGA monitor connector to a DDC-compliant
+monitor. This interface is defined by the Video Electronics Standards
+Association (VESA). The standards are available for purchase at
+http://www.vesa.org .
+
+The second interface is a general-purpose I2C bus. It may be connected to a
+TV-out chip such as the BT869 or possibly to a digital flat-panel display.
+
+Features
+-------- 
+
+Both busses use the i2c-algo-bit driver for 'bit banging'
+and support for specific transactions is provided by i2c-algo-bit.
+
+Issues
+------
+
+If you enable bus testing in i2c-algo-bit (insmod i2c-algo-bit bit_test=1),
+the test may fail; if so, the i2c-i810 driver won't be inserted. However,
+we think this has been fixed.
diff --git a/Documentation/i2c/busses/i2c-parport-light b/Documentation/i2c/busses/i2c-parport-light
new file mode 100644 (file)
index 0000000..2874364
--- /dev/null
@@ -0,0 +1,11 @@
+Kernel driver i2c-parport-light
+
+Author: Jean Delvare <khali@linux-fr.org> 
+
+This driver is a light version of i2c-parport. It doesn't depend        
+on the parport driver, and uses direct I/O access instead. This might be
+prefered on embedded systems where wasting memory for the clean but heavy
+parport handling is not an option. The drawback is a reduced portability
+and the impossibility to daisy-chain other parallel port devices.                 
+  
+Please see i2c-parport for documentation.
diff --git a/Documentation/i2c/busses/i2c-pca-isa b/Documentation/i2c/busses/i2c-pca-isa
new file mode 100644 (file)
index 0000000..6fc8f4c
--- /dev/null
@@ -0,0 +1,23 @@
+Kernel driver i2c-pca-isa
+
+Supported adapters:
+This driver supports ISA boards using the Philips PCA 9564 
+Parallel bus to I2C bus controller 
+
+Author: Ian Campbell <icampbell@arcom.com>, Arcom Control Systems 
+
+Module Parameters
+-----------------
+
+* base int
+ I/O base address
+* irq int
+ IRQ interrupt 
+* clock int 
+ Clock rate as described in table 1 of PCA9564 datasheet
+
+Description
+-----------
+
+This driver supports ISA boards using the Philips PCA 9564 
+Parallel bus to I2C bus controller 
diff --git a/Documentation/i2c/busses/i2c-prosavage b/Documentation/i2c/busses/i2c-prosavage
new file mode 100644 (file)
index 0000000..7036879
--- /dev/null
@@ -0,0 +1,23 @@
+Kernel driver i2c-prosavage
+
+Supported adapters:
+       
+       S3/VIA KM266/VT8375 aka ProSavage8 
+       S3/VIA KM133/VT8365 aka Savage4 
+
+Author: Henk Vergonet <henk@god.dyndns.org>
+
+Description
+-----------
+
+The Savage4 chips contain two I2C interfaces (aka a I2C 'master' or
+'host'). 
+
+The first interface is used for DDC (Data Display Channel) which is a
+serial channel through the VGA monitor connector to a DDC-compliant
+monitor. This interface is defined by the Video Electronics Standards
+Association (VESA). The standards are available for purchase at
+http://www.vesa.org . The second interface is a general-purpose I2C bus.
+
+Usefull for gaining access to the TV Encoder chips.
+
diff --git a/Documentation/i2c/busses/i2c-savage4 b/Documentation/i2c/busses/i2c-savage4
new file mode 100644 (file)
index 0000000..6ecceab
--- /dev/null
@@ -0,0 +1,26 @@
+Kernel driver i2c-savage4
+
+Supported adapters:
+  * Savage4
+  * Savage2000
+
+Authors: 
+       Alexander Wold <awold@bigfoot.com>,
+       Mark D. Studebaker <mdsxyz123@yahoo.com> 
+
+Description
+-----------
+
+The Savage4 chips contain two I2C interfaces (aka a I2C 'master'
+or 'host'). 
+
+The first interface is used for DDC (Data Display Channel) which is a
+serial channel through the VGA monitor connector to a DDC-compliant
+monitor. This interface is defined by the Video Electronics Standards
+Association (VESA). The standards are available for purchase at
+http://www.vesa.org . The DDC bus is not yet supported because its register
+is not directly memory-mapped.
+
+The second interface is a general-purpose I2C bus. This is the only
+interface supported by the driver at the moment.
+
diff --git a/Documentation/i2c/busses/i2c-sis5595 b/Documentation/i2c/busses/i2c-sis5595
new file mode 100644 (file)
index 0000000..cc47db7
--- /dev/null
@@ -0,0 +1,59 @@
+Kernel driver i2c-sis5595
+
+Authors: 
+       Frodo Looijaard <frodol@dds.nl>,
+        Mark D. Studebaker <mdsxyz123@yahoo.com>,
+       Philip Edelbrock <phil@netroedge.com> 
+
+Supported adapters:
+  * Silicon Integrated Systems Corp. SiS5595 Southbridge
+    Datasheet: Publicly available at the Silicon Integrated Systems Corp. site.
+
+Note: all have mfr. ID 0x1039. 
+
+   SUPPORTED            PCI ID           
+        5595            0008 
+   Note: these chips contain a 0008 device which is incompatible with the 
+         5595. We recognize these by the presence of the listed 
+         "blacklist" PCI ID and refuse to load. 
+   NOT SUPPORTED        PCI ID          BLACKLIST PCI ID         
+         540            0008            0540 
+         550            0008            0550 
+        5513            0008            5511 
+        5581            0008            5597 
+        5582            0008            5597 
+        5597            0008            5597 
+        5598            0008            5597/5598 
+         630            0008            0630 
+         645            0008            0645 
+         646            0008            0646 
+         648            0008            0648 
+         650            0008            0650 
+         651            0008            0651 
+         730            0008            0730 
+         735            0008            0735 
+         745            0008            0745 
+         746            0008            0746 
+
+Module Parameters
+-----------------
+
+* force_addr=0xaddr    Set the I/O base address. Useful for boards
+                       that don't set the address in the BIOS. Does not do a
+                       PCI force; the device must still be present in lspci.
+                       Don't use this unless the driver complains that the
+                       base address is not set.
+
+Description
+-----------
+
+i2c-sis5595 is a true SMBus host driver for motherboards with the SiS5595
+southbridges.
+
+WARNING: If you are trying to access the integrated sensors on the SiS5595
+chip, you want the sis5595 driver for those, not this driver. This driver
+is a BUS driver, not a CHIP driver. A BUS driver is used by other CHIP
+drivers to access chips on the bus.
+
diff --git a/Documentation/i2c/busses/i2c-sis630 b/Documentation/i2c/busses/i2c-sis630
new file mode 100644 (file)
index 0000000..9aca688
--- /dev/null
@@ -0,0 +1,49 @@
+Kernel driver i2c-sis630
+
+Supported adapters:
+  * Silicon Integrated Systems Corp (SiS)
+       630 chipset (Datasheet: available at http://amalysh.bei.t-online.de/docs/SIS/)
+       730 chipset
+  * Possible other SiS chipsets ?
+
+Author: Alexander Malysh <amalysh@web.de>
+
+Module Parameters
+-----------------
+
+* force = [1|0] Forcibly enable the SIS630. DANGEROUS!
+               This can be interesting for chipsets not named
+               above to check if it works for you chipset, but DANGEROUS!
+               
+* high_clock = [1|0] Forcibly set Host Master Clock to 56KHz (default, 
+                       what your BIOS use). DANGEROUS! This should be a bit 
+                       faster, but freeze some systems (i.e. my Laptop).
+
+
+Description
+-----------
+
+This SMBus only driver is known to work on motherboards with the above
+named chipsets.
+
+If you see something like this:
+
+00:00.0 Host bridge: Silicon Integrated Systems [SiS] 630 Host (rev 31)
+00:01.0 ISA bridge: Silicon Integrated Systems [SiS] 85C503/5513
+
+or like this:
+
+00:00.0 Host bridge: Silicon Integrated Systems [SiS] 730 Host (rev 02)
+00:01.0 ISA bridge: Silicon Integrated Systems [SiS] 85C503/5513
+
+in your 'lspci' output , then this driver is for your chipset.
+
+Thank You
+---------
+Philip Edelbrock <phil@netroedge.com>
+- testing SiS730 support
+Mark M. Hoffman <mhoffman@lightlink.com>
+- bug fixes
+To anyone else which I forgot here ;), thanks!
+
diff --git a/Documentation/i2c/busses/i2c-via b/Documentation/i2c/busses/i2c-via
new file mode 100644 (file)
index 0000000..55edfe1
--- /dev/null
@@ -0,0 +1,34 @@
+Kernel driver i2c-via
+
+Supported adapters:
+  * VIA Technologies, InC. VT82C586B
+    Datasheet: Publicly available at the VIA website
+
+Author: Kyösti Mälkki <kmalkki@cc.hut.fi>
+
+Description
+-----------
+
+i2c-via is an i2c bus driver for motherboards with VIA chipset.
+
+The following VIA pci chipsets are supported:
+ - MVP3, VP3, VP2/97, VPX/97 
+ - others with South bridge VT82C586B
+
+Your lspci listing must show this :
+
+ Bridge: VIA Technologies, Inc. VT82C586B ACPI (rev 10)
+
+    Problems?
+ Q: You have VT82C586B on the motherboard, but not in the listing. 
+ A: Go to your BIOS setup, section PCI devices or similar.
+    Turn USB support on, and try again. 
+
+ Q: No error messages, but still i2c doesn't seem to work.
+
+ A: This can happen. This driver uses the pins VIA recommends in their
+    datasheets, but there are several ways the motherboard manufacturer
+    can actually wire the lines.
+
diff --git a/Documentation/i2c/busses/i2c-voodoo3 b/Documentation/i2c/busses/i2c-voodoo3
new file mode 100644 (file)
index 0000000..62d90a4
--- /dev/null
@@ -0,0 +1,62 @@
+Kernel driver i2c-voodoo3
+
+Supported adapters:
+  * 3dfx Voodoo3 based cards
+  * Voodoo Banshee based cards
+
+Authors: 
+       Frodo Looijaard <frodol@dds.nl>, 
+       Philip Edelbrock <phil@netroedge.com>, 
+       Ralph Metzler <rjkm@thp.uni-koeln.de>,
+       Mark D. Studebaker <mdsxyz123@yahoo.com>
+
+Main contact: Philip Edelbrock <phil@netroedge.com>
+       
+The code is based upon Ralph's test code (he did the hard stuff ;')
+
+Description
+-----------
+
+The 3dfx Voodoo3 chip contains two I2C interfaces (aka a I2C 'master' or
+'host'). 
+
+The first interface is used for DDC (Data Display Channel) which is a
+serial channel through the VGA monitor connector to a DDC-compliant
+monitor. This interface is defined by the Video Electronics Standards
+Association (VESA). The standards are available for purchase at
+http://www.vesa.org .
+
+The second interface is a general-purpose I2C bus. The intent by 3dfx was
+to allow manufacturers to add extra chips to the video card such as a
+TV-out chip such as the BT869 or possibly even I2C based temperature
+sensors like the ADM1021 or LM75.
+
+Stability
+---------
+
+Seems to be stable on the test machine, but needs more testing on other
+machines. Simultaneous accesses of the DDC and I2C busses may cause errors.
+
+Supported Devices
+-----------------
+
+Specifically, this driver was written and tested on the '3dfx Voodoo3 AGP
+3000' which has a tv-out feature (s-video or composite).  According to the
+docs and discussions, this code should work for any Voodoo3 based cards as
+well as Voodoo Banshee based cards.  The DDC interface has been tested on a
+Voodoo Banshee card.
+       
+Issues
+------
+
+Probably many, but it seems to work OK on my system. :')
+
+
+External Device Connection
+--------------------------
+
+The digital video input jumpers give availability to the I2C bus. 
+Specifically, pins 13 and 25 (bottom row middle, and bottom right-end) are     
+the I2C clock and I2C data lines, respectively. +5V and GND are probably
+also easily available making the addition of extra I2C/SMBus devices easy
+to implement.
diff --git a/Documentation/kref.txt b/Documentation/kref.txt
new file mode 100644 (file)
index 0000000..42fe284
--- /dev/null
@@ -0,0 +1,216 @@
+
+krefs allow you to add reference counters to your objects.  If you
+have objects that are used in multiple places and passed around, and
+you don't have refcounts, your code is almost certainly broken.  If
+you want refcounts, krefs are the way to go.
+
+To use a kref, add one to your data structures like:
+
+struct my_data
+{
+       .
+       .
+       struct kref refcount;
+       .
+       .
+};
+
+The kref can occur anywhere within the data structure.
+
+You must initialize the kref after you allocate it.  To do this, call
+kref_init as so:
+
+     struct my_data *data;
+
+     data = kmalloc(sizeof(*data), GFP_KERNEL);
+     if (!data)
+            return -ENOMEM;
+     kref_init(&data->refcount);
+
+This sets the refcount in the kref to 1.
+
+Once you have an initialized kref, you must follow the following
+rules:
+
+1) If you make a non-temporary copy of a pointer, especially if
+   it can be passed to another thread of execution, you must
+   increment the refcount with kref_get() before passing it off:
+       kref_get(&data->refcount);
+   If you already have a valid pointer to a kref-ed structure (the
+   refcount cannot go to zero) you may do this without a lock.
+
+2) When you are done with a pointer, you must call kref_put():
+       kref_put(&data->refcount, data_release);
+   If this is the last reference to the pointer, the release
+   routine will be called.  If the code never tries to get
+   a valid pointer to a kref-ed structure without already
+   holding a valid pointer, it is safe to do this without
+   a lock.
+
+3) If the code attempts to gain a reference to a kref-ed structure
+   without already holding a valid pointer, it must serialize access
+   where a kref_put() cannot occur during the kref_get(), and the
+   structure must remain valid during the kref_get().
+
+For example, if you allocate some data and then pass it to another
+thread to process:
+
+void data_release(struct kref *ref)
+{
+       struct my_data *data = container_of(ref, struct my_data, refcount);
+       kfree(data);
+}
+
+void more_data_handling(void *cb_data)
+{
+       struct my_data *data = cb_data;
+       .
+       . do stuff with data here
+       .
+       kref_put(data, data_release);
+}
+
+int my_data_handler(void)
+{
+       int rv = 0;
+       struct my_data *data;
+       struct task_struct *task;
+       data = kmalloc(sizeof(*data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+       kref_init(&data->refcount);
+
+       kref_get(&data->refcount);
+       task = kthread_run(more_data_handling, data, "more_data_handling");
+       if (task == ERR_PTR(-ENOMEM)) {
+               rv = -ENOMEM;
+               kref_put(&data->refcount, data_release);
+               goto out;
+       }
+
+       .
+       . do stuff with data here
+       .
+ out:
+       kref_put(&data->refcount, data_release);
+       return rv;
+}
+
+This way, it doesn't matter what order the two threads handle the
+data, the kref_put() handles knowing when the data is not referenced
+any more and releasing it.  The kref_get() does not require a lock,
+since we already have a valid pointer that we own a refcount for.  The
+put needs no lock because nothing tries to get the data without
+already holding a pointer.
+
+Note that the "before" in rule 1 is very important.  You should never
+do something like:
+
+       task = kthread_run(more_data_handling, data, "more_data_handling");
+       if (task == ERR_PTR(-ENOMEM)) {
+               rv = -ENOMEM;
+               goto out;
+       } else
+               /* BAD BAD BAD - get is after the handoff */
+               kref_get(&data->refcount);
+
+Don't assume you know what you are doing and use the above construct.
+First of all, you may not know what you are doing.  Second, you may
+know what you are doing (there are some situations where locking is
+involved where the above may be legal) but someone else who doesn't
+know what they are doing may change the code or copy the code.  It's
+bad style.  Don't do it.
+
+There are some situations where you can optimize the gets and puts.
+For instance, if you are done with an object and enqueuing it for
+something else or passing it off to something else, there is no reason
+to do a get then a put:
+
+       /* Silly extra get and put */
+       kref_get(&obj->ref);
+       enqueue(obj);
+       kref_put(&obj->ref, obj_cleanup);
+
+Just do the enqueue.  A comment about this is always welcome:
+
+       enqueue(obj);
+       /* We are done with obj, so we pass our refcount off
+          to the queue.  DON'T TOUCH obj AFTER HERE! */
+
+The last rule (rule 3) is the nastiest one to handle.  Say, for
+instance, you have a list of items that are each kref-ed, and you wish
+to get the first one.  You can't just pull the first item off the list
+and kref_get() it.  That violates rule 3 because you are not already
+holding a valid pointer.  You must add locks or semaphores.  For
+instance:
+
+static DECLARE_MUTEX(sem);
+static LIST_HEAD(q);
+struct my_data
+{
+       struct kref      refcount;
+       struct list_head link;
+};
+
+static struct my_data *get_entry()
+{
+       struct my_data *entry = NULL;
+       down(&sem);
+       if (!list_empty(&q)) {
+               entry = container_of(q.next, struct my_q_entry, link);
+               kref_get(&entry->refcount);
+       }
+       up(&sem);
+       return entry;
+}
+
+static void release_entry(struct kref *ref)
+{
+       struct my_data *entry = container_of(ref, struct my_data, refcount);
+
+       list_del(&entry->link);
+       kfree(entry);
+}
+
+static void put_entry(struct my_data *entry)
+{
+       down(&sem);
+       kref_put(&entry->refcount, release_entry);
+       up(&sem);
+}
+
+The kref_put() return value is useful if you do not want to hold the
+lock during the whole release operation.  Say you didn't want to call
+kfree() with the lock held in the example above (since it is kind of
+pointless to do so).  You could use kref_put() as follows:
+
+static void release_entry(struct kref *ref)
+{
+       /* All work is done after the return from kref_put(). */
+}
+
+static void put_entry(struct my_data *entry)
+{
+       down(&sem);
+       if (kref_put(&entry->refcount, release_entry)) {
+               list_del(&entry->link);
+               up(&sem);
+               kfree(entry);
+       } else
+               up(&sem);
+}
+
+This is really more useful if you have to call other routines as part
+of the free operations that could take a long time or might claim the
+same lock.  Note that doing everything in the release routine is still
+preferred as it is a little neater.
+
+
+Corey Minyard <minyard@acm.org>
+
+A lot of this was lifted from Greg Kroah-Hartman's 2004 OLS paper and
+presentation on krefs, which can be found at:
+  http://www.kroah.com/linux/talks/ols_2004_kref_paper/Reprint-Kroah-Hartman-OLS2004.pdf
+and:
+  http://www.kroah.com/linux/talks/ols_2004_kref_talk/
+
diff --git a/Documentation/scsi/ChangeLog.lpfc b/Documentation/scsi/ChangeLog.lpfc
new file mode 100644 (file)
index 0000000..ae3f962
--- /dev/null
@@ -0,0 +1,1865 @@
+Known issues :
+       * Please read the associated RELEASE-NOTES file !!!
+       * This source release intended for upstream kernel releases only!
+
+Changes from 20050323 to 20050413
+
+       * Changed version number to 8.0.28
+       * Fixed build warning for 2.6.12-rc2 kernels: mempool_alloc now
+         requires a function which takes an unsigned int for gfp_flags.
+       * Removed pci dma sync calls to coherent/consistent pci memory.
+       * Merged patch from Christoph Hellwig <hch@lst.de>: split helpers
+         for fabric and nport logins out of lpfc_cmpl_els_flogi.
+       * Removed sysfs attributes that are used to dump the various
+         discovery lists.
+       * Fix for issue where not all luns are seen.  Search all lists
+         other than unmap list in lpfc_find_target().  Otherwise INQUIRY
+         to luns on nodes in NPR or other relevant states (PLOGI,
+         PRLI...) are errored back and scan() terminates.
+       * Removed FC_TRANSPORT_PATCHESxxx defines.  They're in 2.6.12-rc1.
+       * Compare return value of lpfc_scsi_tgt_reset against SCSI
+         midlayer codes SUCCESS/FAILED which that function returns rather
+         than SLI return code.
+       * Removed extraneous calls to lpfc_sli_next_iotag which should
+         only be called from lpfc_sli_submit_iocb.  Also make
+         lpfc_sli_next_iotag static.
+       * Added PCI ID for LP10000-S.
+       * Changes in lpfc_abort_handler(): Return SUCCESS if we did not
+         find command in both TX and TX completion queues.  Return ERROR
+         if we timed out waiting for command to complete after abort was
+         issued.
+       * Zero-out response sense length in lpfc_scsi_prep_cmnd to prevent
+         interpretation of stale sense length when the command completes
+         - was causing spurious 0710 messages.
+       * Moved clearing of host_scribble inside host_lock in IO
+         completion path.
+       * Fixed a bunch of mixed tab/space indentation.
+       * Allow hex format numbers in sysfs attribute setting.  Fix
+         application hang when invalid numbers are used in sysfs
+         settings.
+       * Removed extra iotag allocation by lpfc_abort_handler.
+       * Clear host_scribble in the scsi_cmnd structure when failing in
+         queuecommand.
+       * Changed logic at top of lpfc_abort_handler so that if the
+         command's host_scibble field is NULL, return SUCCESS because the
+         driver has already returned the command to the midlayer.
+
+Changes from 20050308 to 20050323
+
+       * Changed version number to 8.0.27
+       * Changed a few lines from patch submitted by Christoph Hellwig
+         (3/19). MAILBOX_WSIZE * (uint32_t) is replaced with an
+         equivalent MAILBOX_CMDSIZE macro.
+       * Merged patch from Christoph Hellwig (3/19): some misc patches
+         against the latest drivers:
+         - stop using volatile.  if you need special ordering use memory
+           barriers but that doesn't seem to be the case here
+         - switch lpfc_sli_pcimem_bcopy to take void * arguments.
+         - remove typecast for constants - a U postfix marks them
+           unsigned int in C
+         - add a MAILBOX_CMD_SIZE macro, as most users of
+           MAILBOX_CMD_WSIZE didn't really want the word count
+         - kill struct lpfc_scsi_dma_buf and embedded the two members
+           directly in struct lpfc_scsi_buf
+         - don't call dma_sync function on allocations from
+           pci_pool_alloc - it's only for streaming mappings (pci_map_*)
+       * Merged patch from Christoph Hellwig (3/19) - nlp_failMask isn't
+         ever used by the driver, just reported to userspace (and that in
+         a multi-value file which is against the sysfs guidelines).
+       * Change pci_module_init to pci_register_module() with appropriate
+         ifdefs.
+       * Added #include <linux/dma-mapping.h> as required by the DMA
+         32bit and 64bit defines on some archs.
+       * Merged patch from Christoph Hellwig (03/19) - fix initialization
+         order - scsi_add_host must happen last from scsi POV. Also some
+         minor style/comment fixups.
+       * Fixed use of TRANSPORT_PATCHES_V2 by changing to
+         FC_TRANSPORT_PATCHES_V2.
+
+Changes from 20050223 to 20050308
+
+       * Changed version number to 8.0.26
+       * Revise TRANSPORT_PATCHES_V2 so that lpfc_target is removed and
+         rport data is used instead. Removed device_queue_hash[].
+       * Changed RW attributes of scan_down, max_luns and fcp_bind_method
+         to R only.
+       * Fixed RSCN handling during initial link initialization.
+       * Fixed issue with receiving PLOGI handling when node is on NPR
+         list and marked for ADISC.
+       * Fixed RSCN timeout issues.
+       * Reduced severity of "SCSI layer issued abort device" message to
+         KERN_WARNING.
+       * Feedback from Christoph Hellwig (on 2/5) - In the LPFC_EVT_SCAN
+         case the caller already has the target ID handly, so pass that
+         one in evt_arg1.
+       * Fix compile warning/resultant panic in
+         lpfc_register_remote_port().
+
+Changes from 20050215 to 20050223
+
+       * Changed version number to 8.0.25
+       * Add appropriate comments to lpfc_sli.c.
+       * Use DMA_64BIT_MASK and DMA_32BIT_MASK defines instead of
+         0xffffffffffffffffULL & 0xffffffffULL respectively.  Use pci
+         equivalents instead of dma_set_mask and also modify condition
+         clause to actually exit on error condition.
+       * Restart els timeout handler only if txcmplq_cnt. On submission,
+         mod_timer the els_tmofunc.  This prevents the worker thread from
+         waking up the els_tmo handler un-necessarily.  The thread was
+         being woken up even when there were no pending els commands.
+       * Added new typedefs for abort and reset functions.
+       * Collapsed lpfc_sli_abort_iocb_xxx into a single function.
+       * Collapsed lpfc_sli_sum_iocb_xxx into a single function.
+       * Removed TXQ from all abort and reset handlers since it is never
+         used.
+       * Fixed Oops panic in 8.0.23 (reported on SourceForge).  The
+         driver was not handling LPFC_IO_POLL cases correctly in
+         fast_ring_event and was setting the tgt_reset timeout to 0 in
+         lpfc_reset_bus_handler.  This 0 timeout would not allow the FW
+         to timeout ABTS's on bad targets and allow the driver to have an
+         iocb on two lists.  Also split the lpfc_sli_ringtxcmpl_get
+         function into two routines to match the fast and slow completion
+         semantics - ELS completions worked for the wrong reasons.  Also
+         provided new log message number - had two 0326 entries.
+       * Removed unused #define LPFC_SCSI_INITIAL_BPL_SIZE.
+       * Removed unused struct lpfc_node_farp_pend definition.
+       * Removed unused #define LPFC_SLIM2_PAGE_AREA.
+       * Changed zeros used as pointers to NULL.
+       * Removed unneeded braces around single line in lpfc_do_work.
+       * Close humongous memory leak in lpfc_sli.c - driver was losing 13
+         iocbq structures per LIP.
+       * Removed last of GFP_ATOMIC allocations.
+       * Locks are not taken outside of nportdisc, hbadisc, els and most
+         of the init, sli, mbox and ct groups of functions
+       * Fix comment for lpfc_sli_iocb_cmd_type to fit within 80 columns.
+       * Replaced wait_event() with wait_event_interruptible().
+         wait_event() puts the woker thread in an UNINTERRUPTIBLE state
+         causing it to figure in load average calculations. Also add a
+         BUG_ON to the ret code of wait_event_interruptible() since the
+         premise is that the worker thread is signal-immune.
+
+Changes from 20050208 to 20050215
+
+       * Changed version number to 8.0.24
+       * Fixed a memory leak of iocbq structure.  For ELS solicited iocbs
+         sli layer now frees the response iocbs after processing it.
+       * Closed large memory leak -- we were losing 13 iocbq structures
+         per LIP.
+       * Changing EIO and ENOMEM to -EIO and -ENOMEM respectively.
+       * Cleanup of lpfc_sli_iocb_cmd_type array and typing of iocb type.
+       * Implemented Christoph Hellwig's feedback from 02/05: Remove
+         macros putLunHigh, putLunLow. Use lpfc_put_lun() inline instead.
+       * Integrated Christoph Hellwig's feedback from 02/05: Instead of
+         cpu_to_be32(), use swab16((uint16_t)lun). This is the same as
+         "swab16() on LE" and "<<16 on BE".
+       * Added updates for revised FC remote port patch (dev_loss_tmo
+         moved to rport, hostdata renamed dd_data, add fc_remote_host()
+         on shutdown).
+       * Removed unnecessary function prototype.
+       * Added code to prevent waking up worker thread after the exit of
+         worker thread.  Fixes panic seen with insmod/rmmod testing with
+         70 disks.
+       * Integrated Christoph Hellwig's patch from 1/30: Make some
+         variables/code static (namely lpfcAlpaArray and
+         process_nodev_timeout()).
+       * Integrated Christoph Hellwig's patch from 1/30: Use
+         switch...case instead of if...else if...else if while decoding
+         JDEC id.
+
+Changes from 20050201 to 20050208
+
+       * Changed version number to 8.0.23
+       * Make lpfc_work_done, lpfc_get_scsi_buf,
+         lpfc_mbx_process_link_up, lpfc_mbx_issue_link_down and
+         lpfc_sli_chipset_init static.
+       * Cleaned up references to list_head->next field in the driver.
+       * Replaced lpfc_discq_post_event with lpfc_workq_post_event.
+       * Implmented Christoph Hellwig's review from 2/5: Check for return
+         values of kmalloc.
+       * Integrated Christoph Hellwig's patch from 1/30: Protecting
+         scan_tmo and friends in !FC_TRANSPORT_PATCHES_V2 &&
+         !USE_SCAN_TARGET.
+       * Integrated Christoph Hellwig's patch from 1/30: Some fixes in
+         the evt handling area.
+       * Integrated Christoph Hellwig's patch from 1/30: Remove usage of
+         intr_inited variable. The interrupt initilization from OS side
+         now happens in lpfc_probe_one().
+       * Integrated Christoph Hellwig's patch from 1/30: remove shim
+         lpfc_alloc_transport_attr - remove shim lpfc_alloc_shost_attrs -
+         remove shim lpfc_scsi_host_init - allocate phba mem in scsi's
+         hostdata readjust code so that they are no use after free's
+         (don't use after scsi_host_put) - make lpfc_alloc_sysfs_attr
+         return errors
+       * Fixed panic in lpfc_probe_one(). Do not delete in a list
+         iterator that is not safe.
+       * Clean up fast lookup array of the fcp_ring when aborting iocbs.
+       * Following timeout handlers moved to the lpfc worker thread:
+         lpfc_disc_timeout, lpfc_els_timeout, lpfc_mbox, lpfc_fdmi_tmo,
+         lpfc_nodev_timeout, lpfc_els_retry_delay.
+       * Removed unused NLP_NS_NODE #define.
+       * Integrated Christoph Hellwig's patch from 1/30: remove unused
+         lpfc_hba_list; remove unused lpfc_rdrev_wd30; remove
+         lpfc_get_brd_no and use Linux provided IDR.
+       * Changed board reset procedure so that lpfc_sli_send_reset()
+         writes the INITFF bit and leaves lpfc_sli_brdreset() to clear
+         the bit.
+       * Removed outfcpio sysfs device attribute.
+       * VPD changes: 1) Modify driver to use the model name and
+         description from the VPD data if it exists 2) Rework use of DUMP
+         mailbox command to support HBAs with 256 bytes of SLIM.
+       * Fixed compile error for implicit definition of struct
+         scsi_target
+
+Changes from 20050124 to 20050201
+
+       * Changed version number to 8.0.22
+       * Moved discovery timeout handler to worker thread. There are
+         function calls in this function which are not safe to call from
+         HW interrupt context.
+       * Removed free_irq from the error path of HBA initialization.
+         This will fix the free of uninitialised IRQ when config_port
+         fails.
+       * Make sure function which processes unsolicited IOCBs on ELS ring
+         still is called with the lock held.
+       * Clear LA bit from work_ha when we are not supposed to handle LA.
+       * Fix double locking bug in the error handling part of
+         lpfc_mbx_cmpl_read_la.
+       * Implemented fast IOCB processing for FCP ring.
+       * Since mboxes are now unconditionally allocated outside of the
+         lock, free them in cases where they are not used.
+       * Moved out a couple of GFP_ATOMICs in lpfc_disc_timeout, to
+         before locks so that they can GFP_KERNEL instead. Also cleaned
+         up code.
+       * Collapsed interrupt handling code into one function.
+       * Removed event posting and handling of solicited and unsolicited
+         iocbs.
+       * Remove ELS ring handling leftovers from the lpfc_sli_inter().
+       * ELS ring (any slow ring) moved from the lpfc_sli_inter() into a
+         worker thread.  Link Attention, Mbox Attention, and Error
+         Attention, as well as slow rings' attention is passed to the
+         worker thread via worker thread copy of Host Attention
+         register. Corresponding events are removed from the event queue
+         handling.
+       * Add entries to hba structure to delegate some functionality from
+         the lpfc_sli_inter() to a worker thread.
+       * Reduced used of GFP_ATOMIC for memory allocations.
+       * Moved locks deeper in order to change GFP_ATOMIC to GFP_KERNEL.
+       * IOCB initialization fix for Raw IO.
+       * Removed qcmdcnt, iodonecnt, errcnt from lpfc_target and from
+         driver.
+       * Added call to lpfc_els_abort in lpfc_free_node.  Modified
+         lpfc_els_abort to reset txq and txcmplq iterator after a
+         iocb_cmpl call.
+       * Fixed a use after free issue in lpfc_init.c.
+       * Defined default mailbox completion routine and removed code in
+         the sli layer which checks the mbox_cmpl == 0 to free mail box
+         resources.
+       * In lpfc_workq_post_event, clean up comment formatting and remove
+         unneeded cast of kmalloc's return.
+       * Removed loop which calls fc_remote_port_unblock and
+         fc_remote_port_delete for every target as this same effect is
+         accomplished by the scsi_remove_host call.
+       * Minor cleanup of header files.  Stop header files including
+         other header files.  Removed sentinels which hide multiple
+         inclusions.  Removed unneeded #include directives.
+       * Fixed memory leaks in mailbox error paths.
+       * Moved lock from around of lpfc_work_done to lpfc_work_done
+         itself.
+       * Removed typedef for LPFC_WORK_EVT_t and left just struct
+         lpfc_work_evt to comply with linux_scsi review coding style.
+       * Fixed some trailing whitespaces, spaces used for indentation and
+         ill-formatting multiline comments.
+       * Bug fix for Raw IO errors.  Reuse of IOCBs now mandates setting
+         of ulpPU and fcpi_parm to avoid incorrect read check of Write IO
+         and incorrect read length.
+
+Changes from 20050110 to 20050124
+
+       * Changed version number to 8.0.21
+       * Removed unpleasant casting in the definition and use of
+         lpfc_disc_action function pointer array.
+       * Makefile cleanup.  Use ?= operator for setting default
+         KERNELVERSION and BASEINCLUDE values.  Use $(PWD) consistently.
+       * Removed call to lpfc_sli_intr from lpfc_config_port_post.  All
+         Linux systems will service hardware interrupts while bringing up
+         the driver.
+       * Christoph Hellwig change request: Reorg of contents of
+         lpfc_hbadisc.c, lpfc_scsi.h, lpfc_init.c, lpfc_sli.c,
+         lpfc_attr.c, lpfc_scsi.c.
+       * Renamed discovery thread to lpfc_worker thread.  Moved handling
+         of error attention and link attention and mbox event handler to
+         lpfc_worker thread.
+       * Removed .proc_info and .proc_name from the driver template and
+         associated code.
+       * Removed check of FC_UNLOADING flag in lpfc_queuecommand to
+         determine what result to return.
+       * Move modification of FC_UNLOADING flag under host_lock.
+       * Fix IOERR_RCV_BUFFER_WAITING handling for CT and ELS subsystem.
+       * Workaround firmware bug for IOERR_RCV_BUFFER_WAITING on ELS
+         ring.
+       * Fixed a couple lpfc_post_buffer problems in lpfc_init.c.
+       * Add missing spaces to the parameter descriptions for
+         lpfc_cr_delay, lpfc_cr_count and lpfc_discovery_threads.
+       * Lock before calling lpfc_sli_hba_down().
+       * Fix leak of "host" in the error path in the remove_one() path.
+       * Fix comment for lpfc_cr_count.  It defaults to 1.
+       * Fix issue where we are calling lpfc_disc_done() recursively from
+         lpfc_linkdown(), but list_for_each_entry_safe() is not safe for
+         such use.
+       * Bump lpfc_discovery_threads (count of outstading ELS commands in
+         discovery) to 32
+       * If the SCSI midlayer tries to recover from an error on a lun
+         while the corresponding target is in the NPR state, lpfc driver
+         will reject all the resets. This will cause the target to be
+         moved to offline state and block all the I/Os. The fix for this
+         is to delay the lun reset to a target which is not in MAPPED
+         state until the target is rediscovered or nodev timeout is
+         fired.
+
+Changes from 20041229 to 20050110
+
+       * Changed version number to 8.0.20
+       * rport fix: use new fc_remote_port_rolechg() function instead of
+         direct structure change
+       * rport fix: last null pointer check
+       * Phase II of GFP_ATOMIC effort.  Replaced iocb_mem_pool and
+         scsibuf_mem_pool with kmalloc and linked list.  Inserted list
+         operations for mempool_alloc calls.  General code cleanup.  All
+         abort and reset routines converted.  Handle_ring_event
+         converted.
+       * If the mbox_cmpl == lpfc_sli_wake_mbox_wait in
+         lpfc_sli_handle_mb_event, pmb->context1 points to a waitq. Do
+         not free the structure.
+       * rport fixes: fix for rmmod crash
+       * rport fixes: when receiving PRLI's, set node/rport role values
+       * rport fixes: fix for unload and for fabric port deletes
+       * VPD info bug fix.
+       * lpfc_linkdown() should be able to process all outstanding events
+         by calling lpfc_disc_done() even if it is called from
+         lpfc_disc_done() Moving all events from phba->dpc_disc to local
+         local_dpc_disc prevents those events from being processed.
+         Removing that queue. From now on we should not see "Illegal
+         State Transition" messages.
+       * Release host lock and enable interrupts when calling
+         del_timer_sync()
+       * All related to rports: Clean up issues with rport deletion
+         Convert to using block/unblock on list remove (was del/add)
+         Moved rport delete to freenode - so rport tracks node.
+       * rport fixes: for fport, get maxframe and class support
+         information
+       * Added use of wait_event to work with kthread interface.
+       * Ensure that scsi_transport_fc.h is always pulled in by
+         lpfc_scsiport.c
+       * In remote port changes: no longer nulling target->pnode when
+         removing from mapped list. Pnode get nulled when the node is
+         freed (after nodev tmo). This bug was causing i/o recieved in
+         the small window while the device was blocked to be errored w/
+         did_no_connect. With the fix, it returns host_busy
+         (per the pre-remote port changes).
+       * Merge in support for fc transport remote port use. This removes
+         any consistent bindings within the driver. All scanning is now
+         on a per-target basis driven by the discovery engine.
+
+Changes from 20041220 to 20041229
+
+       * Changed version number to 8.0.19
+       * Fixed bug for handling RSCN type 3.  Terminate RSCN mode
+         properly after ADISC handling completes.
+       * Add list_remove_head macro.  Macro cleans up memory allocation
+         list handling.  Also clean up lpfc_reset_bus_handler - routine
+         does not need to allocate its own scsi_cmnd and scsi_device
+         structures.
+       * Fixed potential discovery bug, nlp list corrutpion fix potential
+         memory leak
+       * Part 1 of the memory allocation rework request by linux-scsi.
+         This effort fixes the number of bdes per scsi_buf to 64, makes
+         the scatter-gather count a module parameter, builds a linked
+         list of scsi_bufs, and removes all dependencies on lpfc_mem.h.
+       * Reverted lpfc_do_dpc, probe_one, remove_one to original
+         implementation.  Too many problems (driver not completing
+         initial discovery, and IO not starting to disks).  Backs out
+         kthread patch.
+       * Fix race condition in lpfc_do_dpc.  If wake_up interrupt occurs
+         while lpfc_do_dpc is running disc_done and the dpc list is
+         empty, the latest insertion is missed and the schedule_timeout
+         does not wakeup.  The sleep interval is MAX_SCHEDULE_TIMEOUT
+         defined as ~0UL >> 1, a very large number.  Hacked it to 5*HZ
+         for now.
+       * Fixed bug introduced when discovery thread implementation was
+         moved to kthread. kthread_stop() is not able to wake up thread
+         waiting on a semaphore and "modprobe -r lpfc" is not always
+         (most of the times) able to complete. Fix is in not using
+         semaphore for the interruptable sleep.
+       * Small Makefile cleanup - Remove remnants of 2.4 vs. 2.6
+         determination.
+
+Changes from 20041213 to 20041220
+
+       * Changed version number to 8.0.18
+       * Janitorial cleanup after removal of sliinit and ringinit[] ring
+         statistic is owned by the ring and SLI stats are in sli
+         structure.
+       * Integrated patch from Christoph Hellwig <hch@lst.de> Kill
+         compile warnings on 64 bit platforms: %variables for %llx format
+         specifiers must be caste to long long because %(u)int64_t can
+         just be long on 64bit platforms.
+       * Integrated patch from Christoph Hellwig <hch@lst.de> Removes
+         dead code.
+       * Integrated patch from Christoph Hellwig <hch@lst.de>: use
+         kthread interface.
+       * Print LPFC_MODULE_DESC banner in module init routine.
+       * Removed sliinit structure and ringinit[] array.
+       * Changed log message number from 324 to 326 in lpfc_sli.c.
+       * Wait longer for commands to complete in lpfc_reset_bus_handler
+         and lpfc_reset_bus_handler.  Also use schedule_timeout() instead
+         of msleep() and add error message in lpfc_abort_handler()
+       * When setting lpfc_nodev_tmo, from dev_loss set routine, make 1
+         sec minimum value.
+       * Functions which assume lock being held were called without lock
+         and kernel complained about unlocking lock which is not locked.
+       * Added code in linkdown to unreg if we know login session will be
+         terminated.
+       * Removed automap config parameter and fixed up use_adisc logic to
+         include FCP2 devices.
+
+Changes from 20041207 to 20041213
+
+       * Changed version number to 8.0.17
+       * Fix sparse warnings by adding __iomem markers to lpfc_compat.h.
+       * Fix some sparse warnings -- 0 used as NULL pointer.
+       * Make sure there's a space between every if and it's (.
+       * Fix some overly long lines and make sure hard tabs are used for
+         indentation.
+       * Remove all trailing whitespace.
+       * Integrate Christoph Hellwig's patch for 8.0.14: if
+         pci_module_init fails we need to release the transport template.
+         (also don't print the driver name at startup, linux drivers can
+         be loaded without hardware present, and noise in the log for
+         that case is considered unpolite, better print messages only for
+         hardware actually found).
+       * Integrate Christoph Hellwig's patch for 8.0.14: Add missing
+         __iomem annotations, remove broken casts, mark functions static.
+         Only major changes is chaning of some offsets from word-based to
+         byte-based so we cans simply do void pointer arithmetics (gcc
+         extension) instead of casting to uint32_t.
+       * Integrate Christoph Hellwig's patch for 8.0.14: flag is always
+         LPFC_SLI_ABORT_IMED, aka 0 - remove dead code.
+       * Modified preprocessor #ifdef, #if, #ifndef to reflect upstream
+         kernel submission.  Clean build with make clean;make and make
+         clean;make ADVANCED=1 on SMP x86, 2.6.10-rc2 on RHEL 4 Beta
+         1. IO with a few lips and a long cable pull behaved accordingly.
+       * Implement full VPD support.
+       * Abort handler will try to wait for abort completion before
+         returning.  Fixes some panics in iocb completion code path.
+
+Changes from 20041130 to 20041207
+       
+       * Changed version number to 8.0.16
+       * Hung dt session fix.  When the midlayer calls to abort a scsi
+         command, make sure the driver does not complete post-abort
+         handler.  Just NULL the iocb_cmpl callback handler and let SLI
+         take over.
+       * Add Read check that uses SLI option to validate all READ data
+         actually received.
+
+
+Changes from 20041123 to 20041130
+
+       * Changed version number to 8.0.15
+       * Ifdef'd unused "binary" attributes by DFC_DEBUG for clean
+         compiles
+       * Stop DID_ERROR from showing up along with QUEUE_FULL set by the
+         Clarion array (SCSI error ret. val.  0x70028) There is no need
+         for driver to hard fail command which was failed by the target
+         device.
+       * Fix for Scsi device scan bug reported on SourceForge.  Driver
+         was returning a DID_ERROR in lpfc_handle_fcp_error causing
+         midlayer to mark report luns as failing even though it
+         succeeded.
+       * Don't ignore SCSI status on underrun conditions for inquiries,
+         test unit ready's, etc.  This was causing us to lose
+         reservation conflicts, etc
+
+Changes from 20041018 to 20041123
+       
+       * Changed version number to 8.0.14
+       * Added new function "iterator" lpfc_sli_next_iocb_slot() which
+         returns pointer to iocb entry at cmdidx if queue is not full.
+         It also updates next_cmdidx, and local_getidx (but not cmdidx)
+       * lpfc_sli_submit_iocb() copies next_cmdidx into cmdidx. Now it is
+         the only place were we are updating cmdidx.
+       * lpfc_sli_update_ring() is split in to two --
+         lpfc_sli_update_ring() and lpfc_sli_update_full_ring().
+       * lpfc_sli_update_ring() don't to read back correct value of
+         cmdidx.
+       * Simplified lpfc_sli_resume_iocb() and its use.
+       * New static function lpfc_sli_next_iocb(phba, pring, &piocb) to
+         iterate through commands in the TX queue and new command (at the
+         end).
+       * Reduced max_lun to 256 (due to issues reported to some arrays).
+         Fixed comment, and macro values so def=256, min=1, max=32768.
+       * Fix an obvious typo/bug: kfree was used to free lpfc_scsi_buf
+         instead of mempool_free in lpfc_scsiport.c.
+       * Suppress nodev_tmo message for FABRIC nodes.
+       * Fixed some usage of plain integer as NULL pointer.
+       * Bug fix for FLOGI cmpl, lpfc_els_chk_latt error path code
+         cleanup.
+       * Fixup lpfc_els_chk_latt() to have Fabric NPorts go thru
+         discovery state machine as well.
+       * Fixes to lpfc_els_chk_latt().
+       * Use DID not SCSI target id as a port_id and add some missing
+         locks in lpfc_fcp.c.
+       * Changed eh_abort_handler to return FAILED if command is not
+         found in driver.
+       * Fix crash: paging request at virtual address 0000000000100108 -
+         a result of removing from the txcmpl list item which was already
+         removed (100100 is a LIST_POISON1 value from the next pointer
+         and 8 is an offset of the "prev") Driver runs out of iotags and
+         does not handle that case well. The root of the proble is in the
+         initialization code in lpfc_sli.c
+       * Changes to work with proposed linux kernel patch to support
+         hotplug.
+       * Zero out seg_cnt in prep_io failure path to prevent double sg
+         unmap calls.
+       * Fix setting of upper 32 bits for Host Group Ring Pointers if in
+         SLIM. Old code was inappropriately masking off low order bits.
+       * Use scsi_[activate|deactivate]_tcq calls provided in scsi_tcq.h.
+       * Integrated patch from Christoph Hellwig (hch@lst.de): don't call
+         pci_dma_sync_* on coherent memory. pci_dma_sync_* is need and
+         must be used only with streaming dma mappings pci_map_*, not
+         coherent mappings.  Note: There are more consistent mappings
+         that are using pci_dma_sync calls. Probably these should be
+         removed as well.
+       * Modified lpfc_free_scsi_buf to accomodate all three scsi_buf
+         free types to alleviate miscellaneous panics with cable pull
+         testing.
+       * Set hotplug to default 0 and lpfc_target_remove to not remove
+         devices unless hotplug is enabled.
+       * Fixed discovery bug: plogi cmpl uses ndlp after its freed.
+       * Fixed discovery bug: rnid acc cmpl, can potentially use ndlp
+         after its freed.
+       * Modularize code path in lpfc_target_remove().
+       * Changes to support SCSI hotplug (ifdef'ed out because they need
+         kernel support USE_SCAN_TARGET requires kernel support to export
+         the interface to scsi_scan_target and to move the SCAN_WILD_CARD
+         define to a general scsi header file.  USE_RESCAN_HOST requires
+         kernel support to export an interface to scan_scsi_host() with
+         the rescan flag turned on).
+       * Removed redundant variable declaration of lpfc_linkdown_tmo.
+       * Fix for large port count remove test.
+       * Added check to see if BAR1 register is valid before using BAR1
+         register for programming config_port mail box command.
+       * Added lpfc_scsi_hotplug to enable/disable driver support of SCSI
+         hotplug.
+       * Changed lpfc_disc_neverdev() to lpfc_disc_illegal() and changed
+         lpfc_disc_nodev() to lpfc_disc_noop().  Adjusted appropriate
+         events to use these routines.
+       * Add support for SCSI device hotplug.
+       * Take dummy lpfc_target's into account for lpfc_slave_destroy().
+       * Bug fix to store WWPN / WWNN in NameServer / FDMI lpfc_nodelist
+         entries.
+       * Added slavecnt in lpfc_target for diagnostic purposes.
+       * Added lpfc_hba load/unload flags to take care of special cases
+         for add/remove device.
+       * Have target add/remove delay before scanning.
+       * Have rmmod path cleanup blocked devices before scsi_remove_host.
+       * Added a #define for msleep for 2.6.5 kernels.
+       * In reset bus handler if memory allocation fails, return FAILED
+         and not SUCCESS.
+       * Have lpfc eh handlers, bus_reset and lun_reset, wait for all
+         associated I/Os to complete before returning.
+       * Fix memset byte count in lpfc_hba_init so that
+         LP1050 would initialize correctly.
+       * Backround nodev_timeout processing to DPC This enables us to
+         unblock (stop dev_loss_tmo) when appopriate.
+       * Fix array discovery with multiple luns.  The max_luns was 0 at
+         the time the host structure was intialized.  lpfc_cfg_params
+         then set the max_luns to the correct value afterwards.
+       * Remove unused define LPFC_MAX_LUN and set the default value of
+         lpfc_max_lun parameter to 512.
+       * Reduced stack usage of lpfc_hba_init.
+       * Cleaned up the following warning generated by
+         scripts/checkincludes.pl lpfc_fcp.c: scsi/scsi_cmnd.h is
+         included more than once.
+       * Replaced "set_current_state(TASK_UNINTERRUPTIBLE);
+         schedule_timeout(timeout)" with "msleep(timeout)".
+       * Fixnode was loosing starget when rediscovered. We saw messages
+         like: lpfc 0000:04:02.0: 0:0263 Cannot block scsi target as a
+         result.  Moved starget field into struct lpfc_target which is
+         referenced from the node.
+       * Add additional SLI layer logging in lpfc_sli.c.
+       * Ignore more unexpected completions in lpfc_nportdisc.c.
+       * Can not call lpfc_target_unblock from the soft interrupt
+         context.  It seems to be not nessasery to unblock target from
+         nodev timeout.
+       * Introduce and use less lethal event handler for unexpected
+         events in lpfc_nportdisc.c.
+       * Can not call fc_target_(un)block() functions with interrupts
+         disabled in lpfc_scsiport.c.
+       * Added new configuration parameter, lpfc_max_luns range 1-32768,
+         default 32768.
+       * Allow lpfc_fcp.c to call lpfc_get_hba_sym_node_name().
+       * Increase nodev timeout from 20 seconds to 30 seconds.
+       * Replace some kfree((void*)ptr) with kfree(ptr).
+       * Make 3 functions static: lpfc_get_hba_sym_node_name,
+         lpfc_intr_prep and lpfc_setup_slim_access.  Move lpfc_intr_prep
+         and lpfc_setup_slim_access so they're defined before being used.
+       * Remove an unecessary list_del() in lpfc_hbadisc.c.
+       * Set nlp_state before calling lpfc_nlp_list() since this will
+         potentially call fc_target_unblock which may cause a race in
+         queuecommand by releasing host_lock.
+       * Since lpfc_nodev_tmo < dev_loss_tmo remove queuecommand
+         DID_BAD_TARGET return for now.
+       * Fix a problem with rcv logo.
+       * Remove unused portstatistics_t structure.
+       * Remove #if 0 and unnecessary checks in lpfc_fcp.c.
+       * Simplify lpfc_issue_lip: Extra layer of protection removed.
+       * Grab lock before calling lpfc_sli_issue_mbox(phba, pmb,
+         MBX_NOWAIT) in lpfc_sli_issue_mbox_wait().
+
+Changes from 20040920 to 20041018
+
+       * Changed version number to 8.0.13
+       * Hide some attributes using #ifndef DFC_DEBUG ... #endif.
+       * Modify Makefile to (1) make BUILD_NO_DEBUG=1 will hide some
+         (binary) attributes (2) make BUILD_FC_TRANS=0 will build driver
+         for 2.6.5 kernel with block/unblock patch.
+       * Modified #ifdef names.
+       * Added support for proposed FC transport host attributes (which
+         replaces some of the attributes we had local to the driver).
+         Removed the binary statistics sysfs attribute.
+       * Added extra ELS verbose logging for ELS responses.
+       * Added recognition for BUILD_FC_TRANS=2 to Makefile to define
+         FC_TRANS_VER2.
+       * Add a pointer for link stats allocation.
+       * Exported lpfc_get_hba_sym_node_name for use by FC_TRANS_VER2
+         sysfs routines.
+       * Fix discovery problem in lip testing: if device sends an ELS cmd
+         (i.e. LOGO) before our FLOGI completes it should be LS_RJT'ed.
+       * Moved #defines around to provide target_add/remove for upstream
+         kernel deliverables only not SLES9.  Provided ifdefs to #include
+         target_block/unblock only if FC_TRANS_VER1.
+       * Add sanity check in lpfc_nlp_list move setting nlp_Target
+         outside #ifdef.
+       * Added a blocked member to the lpfc_target structure for
+         block/unblock.  This member allows the driver to know when to
+         unblock for pci_remove_one or pci_add_one.  #ifdef'd some more
+         block/unblock stuff and removed some defensive checks from
+         target_block/unblock.
+       * Moved + 5 second window to dev_loss_tmo setting and updated
+         comments.
+       * Removed NULL target check from target_block/unblock and fixed up
+         a few comments.
+       * Enable sysfs attributes on 2.6.5 kernels and remove extra
+         compatibility code.
+       * Remove any and all trailing whitespace.
+       * Added message 0718 and return error when dma_map_single fails.
+       * Changed the fcpCntl2 commands to include an FCP_ prefix to get
+         rid of build warnings on later 2.6.9-rc kernels.  Build
+         conflicts with scsi/scsi.h.  Remove inclusions of scsi/scsi.h
+         from hbadisc.c, sli.c, and fcp.c since these modules had no
+         dependencies on scsi.h.
+       * Fixed a bug with RSCN handling. A RSCN received on one device,
+         shouldn't affect other devices not referenced by the RSCN.
+       * Moved #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,6) to include
+         lpfc_jedec_to_ascii to prevent warning in SLES 9.
+       * Update Makefile to account for SLES 9 and scsi-target upstream
+         kernel.
+       * This checkin provides block/unblock hooks for the upstream scsi
+         target kernel and 2.6.5 on SLES9 SP1 with the block/unblock
+         patch.
+       * Discovery changes regarding setting targetp->pnode and
+         ndlp->nlp_Target Ensure fc_target_* routines are called properly
+         from discovery.  Remove list_del's from lpfc_cleanup().  Ensure
+         all the lpfc_consistent_bind_* routines don't set any driver
+         structure objects.
+       * Fix for timeout of READ_LA or READ_SPARAM mailbox command
+         causing panic.
+       * Cleanup list_del()'s for Discovery ndlp lists.
+       * Bug fixes for some insmod/rmmod crashes, link down crashes and
+         device loss crashes.
+       * Removed NLP_SEARCH_DEQUE.
+       * Call lpfc_target_unblock only if the targetp is nonNull and with
+         the host_lock held.
+       * Added qcmdcnt back along with misc bug fixes to discovery.
+       * Changed tgt_io to outfcpio lpfc_fcp.c.
+       * Fixed errors caused by LIP and cable pulls both with and without
+         block/unblock patch.
+       * For now we have to call fc_target_unblock and fc_target_block
+         with interrupts enabled.
+       * Save seg_cnt from dma_map_sg.  Save scatter-gather start address
+         and pass back to dma_unmap_sg in error with seg_cnt.
+       * Incorporating block/unblock calls into driver with ifdefs.  This
+         change is supported by scsi-target-2.6 kernel and forward only.
+       * Merged in some discovery bug fixes and added tgt io counters.
+       * Added sysfs attributes/interfaces: read only attribute
+         "management_version" and write only attribute "issue_lip".
+       * Fix build on big endian machines: while #if was OK with
+         __BIG_ENDIAN which defined as 4321, __BIG_ENDIAN_BITFIELD has to
+         be tested with #ifdef because it does not have any value, it is
+         either defined or not.
+       * Add fabric_name and port_type attributes.
+       * Change mdelay to msleep.  mdelay works, but wastefully uses cpu
+         resources without a lock held. Revert to msleep.  Tested with
+         sg_reset for bus and three attached targets.
+       * Added the customary #ifndef...#define...#endif to
+         lpfc_version.h.
+       * Integrate patches from Christoph Hellwig: two new helpers common
+         to lpfc_sli_resume_iocb and lpfc_sli_issue_iocb - singificant
+         cleanup of those two functions - the unused SLI_IOCB_USE_TXQ is
+         gone - lpfc_sli_issue_iocb_wait loses it's flags argument
+         totally.
+       * Fix in lpfc_sli.c: we can not store a 5 bit value in a 4-bit
+         field.
+       * Moved some routines out of lpfc_fcp.c into more appropriate
+         files.
+       * Whitespace cleanup: remove all trailing whitespace.
+       * Make lpfc_disc_ndlp_show static to lpfc_fcp.c.
+       * Remove leftover printk and replace some with
+         printk(KERN_WARNING)
+       * Trivial: fix a few long lines and a soft tab.
+       * Remove warnings generated by Sparse against driver (make
+         C=1). Mostly these are "using integer as pointer warnings"
+         i.e. use NULL instead of 0.
+       * Integrated patch from Christoph Hellwig: Quite a lot of changes
+         here, the most notable is that the phba->slim2p lpfc_dmabuf goes
+         away in favour of a typede pointer and a dma_addr_t.  Due to the
+         typed pointer lots of the cast mess can go away, and while at it
+         I also replaced the messy SLI2_SLIM_t with a simple struct
+         lpfc2_sli2_slim that only contains the part of the union we care
+         about while using SLI2_SLIM_SIZE for all size calculations
+         directly.
+       * Integrated patch from Christoph Hellwig: This streamlines the
+         I/O completion path a little more, especially taking care of
+         fast-pathing the non-error case.  Also removes tons of dead
+         members and defines from lpfc_scsi.h - e.g. lpfc_target is down
+         to nothing more then the lpfc_nodelist pointer.
+       * Added binary sysfs file to issue mbox commands
+       * Replaced #if __BIG_ENDIAN with #if __BIG_ENDIAN_BITFIELD for
+         compatibility with the user space applications.
+       * Decrease the amount of data in proc_info.
+       * Condense nodelist flag members.
+       * Expand INFO for discovery sysfs shost entries.
+       * Notify user if information exceeds 4k sysfs limit.
+       * Removed a bunch of unused #defines.
+       * Added initial sysfs discovery shost attributes.
+       * Remove unused #defines lpfc_disc.h.
+       * Fixed failMask nodelist settings.
+       * Cleanup some old comments / unused variables.
+       * Add LP101 to list of recognized adapters.
+
+Changes from 20040908 to 20040920
+
+       * Changed version number to 8.0.12
+       * Removed used #defines: DEFAULT_PCI_LATENCY_CLOCKS and
+         PCI_LATENCY_VALUE from lpfc_hw.h.
+       * Changes to accomodate rnid.
+       * Fix RSCN handling so RSCN NS queries only effect NPorts found in
+         RSCN data.
+       * If we rcv a plogi on a NPort queued up for discovery, clear the
+         NLP_NPR_2B_DISC bit since rcv plogi logic will force NPort thru
+         discovery.
+       * Ensure lpfc_target is also cleaned up in lpfc_cleanup().
+       * Preliminary changes for block/unblock kernel API extensions in
+         progress with linux-scsi list.  These are name changes and
+         prototype changes only.
+       * Added send_abts flag to lpfc_els_abort. For rcv LOGO when ADISC
+         sent, the XRI of the LOGO rcv'ed is the same as the ADISC
+         sent. Thus we cannot ABTS the ADISC before sending the LOGO ACC.
+       * Weed out some unused fc_flags.  Add FC_DISC_TMO.
+       * board_online sysfs attribute added to support libdfc functions
+         InitDiagEnv and SetBrdEnv.
+       * Streamline code in lpfc_els_retry fixup abort case in
+         lpfc_els_timeout_handler().
+       * Flush discovery/ELS events when we bring SLI layer down.
+       * ctlreg and slimem binary attributes added to support libdfc
+         read/write mem/ctl functions.
+       * Integrated Christoph Hellwig's patch: Cleanup
+         lpfc_sli_ringpostbuf_get.
+       * Modified lpfc_slave_alloc and lpfc_slave_destroy to allocate and
+         free a dummy target pointer.  This allows queuecommand to skip
+         the NULL target pointer check and avoid the console spam when
+         slave_alloc fails.
+       * Fix cfg_scan_down logic, it was reversed.
+       * Init list head ctrspbuflist.
+       * Change name of lpfc_driver_abort to lpfc_els_abort since it is
+         only valid for ELS ring.
+       * Remove unused third argument for lpfc_consistent_bind_get().
+       * Fix up iotag fields in lpfc_prep_els_iocb().
+       * Remove log message on code path triggered by lpfc_els_abort().
+       * Set host->unique_id in lpfc_fcp.c.
+       * Removed deadwood: lpfc_target.pHba not necessary anymore.
+       * Integrated patch from Christoph Hellwig: remove dead
+         SLI_IOCB_POLL handling.
+       * Integrated patch from Christoph Hellwig: Streamline I/O
+         submission and completion path a little.
+       * Remove unnecessary lpfc_brd_no.  Ensure brd_no assignment is
+         unique.
+       * Removed unused MAX_FCP_LUN.
+       * Use mod_timer instead of add_timer for fdmi in lpfc_ct.c.
+       * Fixed misc discovery problems.
+       * Move stopping timers till just before lpfc_mem_free() call.
+       * Fix up NameServer reglogin error path.
+       * Cleanup possible outstanding discovery timers on rmmod.
+       * Fix discovery NPort to NPort pt2pt problem.
+       * Get rid of ip_tmofunc / scsi_tmofunc.
+       * Integrated patch from Christoph Hellwig:
+         lpfc_disc_done/lpfc_do_dpc cleanup - lpfc_disc_done can return
+         void - move lpfc_do_dpc and lpfc_disc_done to lpfc_hbadisc.c -
+         remove checking of list emptiness before calling lpfc_disc_done,
+         it handles the emtpy list case just fine and the additional
+         instructions cost less then the bustlocked spinlock operations.
+       * Integrated patch from Christoph Hellwig: This adds a new 64bit
+         counter instead, brd_no isn't reused anymore.  Also some tiny
+         whitespace cleanups in surrounding code.
+       * Reorder functions in lpfc_els.c to remove need for prototypes.
+       * Removed unsed prototypes from lpfc_crtn.h -
+         lpfc_ip_timeout_handler, lpfc_read_pci and lpfc_revoke.
+       * Removed some unused prototypes from lpfc_crtn.h -
+         lpfc_scsi_hba_reset, lpfc_scsi_issue_inqsn,
+         lpfc_scsi_issue_inqp0, lpfc_scsi_timeout_handler.
+       * Integrated patch from Christoph Hellwig: remove TRUE/FALSE
+         usage.
+       * Integrated patch from Christoph Hellwig: Remove unused function
+         prototypes lpfc_set_pkt_len and lpfc_get_pkt_data from
+         lpfc_crtn.h - fixes build warnings.
+       * Removed unused struct lpfc_dmabufip definition from lpfc_mem.h.
+       * Removed pre-2.6.5 MODULE_VERSION macro from lpfc_compat.h.
+       * Fixing missing static and removing dead code.
+       * Adding nodewwn, portwwn and portfcid shost attributes.
+       * Initial support for CT via sysfs. request payloads of size less
+         than PAGE_SIZE and rsp payloads of size PAGE_SIZE are supported.
+         Driver maintains a list of rsp's and passes back rsp's
+         corresponding to the pid of the calling process.
+       * Support for RefreshInformation, GetAdapterAttributes,
+         GetPortStatistics.
+       * Make nodev-tmo default to 20 seconds.
+       * Fix up some DSM error cases, unreg_login rpi where needed.
+       * Fix up comments for fc_target_block / fc_target_unblock.
+       * Fix up code for scsi_block_requests / scsi_unblock_requests.
+       * Add NLP_FCP_TARGET for nodeinfo support.
+       * Move suspend/resume in lpfc_nlp_list under appropriate case -
+         Used host_lock for DPC to avoid race (remove dpc_lock)
+       * Fix some corner cases for PLOGI receive - simplify error case
+         for cmpl_reglogin_reglogin_issue.
+       * Bug fix for ppc64 EEH MMIO panic - always do readl after
+         writel's of HBA registers to force flush.
+       * Get rid of initial static routine declarations in lpfc_hbadisc.c
+         and lpfc_els.c.
+       * Updates to discovery processing.
+
+Changes from 20040823 to 20040908
+
+       * Changed version number to 8.0.11
+       * Removed persistent binding code.
+       * Display both ASC and ASCQ info.
+       * Fixed link down->up transitions when linkdown tmo expires. Fix
+         was in the defensive error checking at the start of
+         queuecommand.
+       * Removed lpfc_scsi_timeout_handler as this timer is no longer
+         required.  The midlayer will exhaust retries and then call
+         lpfc_abort_handler, lpfc_reset_lun_handler, and
+         lpfc_reset_target_handler.
+       * Minimal support for SCSI flat space addressing/volume set
+         addressing.  Use 16 bits of LUN address so that flat
+         addressing/VSA will work.
+       * Changed 2 occurences of if( 1 != f(x)) to if(f(x) != 1)
+       * Drop include of lpfc_cfgparm.h.
+       * Reduce stack usage of lpfc_fdmi_cmd in lpfc_ct.c.
+       * Add minimum range checking property to /sys write/store
+         functions.
+       * Fix display of node_name and port_name via fc transport
+         attr.
+       * Removed biosparam code.
+       * Removed range checking. phba->config[] array elements are now
+         embedded into the hba struct. lpfc_config_setup() has been
+         removed.
+       * Collapsed lpfc_scsi_cmd_start into lpfc_queuecommand and cleaned
+         up combined routines.
+       * Removed unused prototypes myprint and
+         lpfc_sched_service_high_priority_queue.
+       * Removed unused function lpfc_nodev.
+       * Removed scsi_cmnd->timeout_per_command cancelation. SCSI midlayer
+         now times out all commands - FW is instructed to not timeout.
+       * Removed polling code from lpfc_scsi_cmd_start. Reorganized
+         queuecommand and cmd_start some.
+
+Changes from 20040810 to 20040823
+
+       * Changed version number to 8.0.10
+       * Additional timer changes as per Arjan / Christoph's comments.
+       * Used mod_timer() instead of del_timer_sync() where appropriate.
+       * Fixed a use after free case (panic on 2.6.8.1 with
+         CONFIG_DEBUG_SLAB set).
+       * Fix compile warning in lpfc_fcp.c.
+       * Minor fix for log message, that prints unassigned brdno which is
+         zero.
+       * Move scsi_host_alloc() to the beginning of probe_one(). This
+         ensures that host_lock is available at later stages and also
+         avoids tons of unnecessary initializing if host_alloc()
+         fails.
+       * Removed else clause from lpfc_slave_configure that set
+         sdev->queue_depth.  The driver informs the midlayer of its
+         setting in the template and only overrides if queue tagging is
+         enabled.
+       * Added PCI_DEVICE_ID_ZEPHYR and PCI_DEVICE_ID_ZFLY (Junior
+         Zephyr) support
+
+Changes from 20040730 to 20040810
+       
+       * Changed version number to 8.0.9
+       * Removed per HBA driver lock.  Driver now uses the host->host_lock
+       * Restored support for the 2.6.5 kernel for those linux distributions
+         shipped with the 2.6.5 kernel.
+       * Applied patch from Christoph Hellwig (hch@infradead.org) as follows
+         "[PATCH] use scsi host private data in ->proc_info.  
+       * Applied patch from Christoph Hellwig (hch@infradead.org) as follows
+         "Re: [Emulex] Ready for next round.  This patch cleans up the memory 
+         allocation routines a little and fixes a missing mempool_destroy and
+         some missing error handling."
+       * Changed pointers assignments from 0 to NULL.
+       * Added fixes to the lpfc_reset_lun_handler and lpfc_reset_bus_handler
+         entry points that caused kernel to Oops or hang.
+       * Added fixes to targetless hosts that caused modprobe and insmod to hang.
+       * Ongoing cleanup to many files
+         
+Changes from 20040723 to 20040730
+
+       * Changed version number to 8.0.8
+       * Removed unused LPFN_DRIVER_VERSION #define.
+       * Folded lpfc_findnode_scsiid into lpfc_find_target, its only
+         caller.
+       * Removed 2 unneeded arguments to lpfc_find_target (lun and
+         create_flag).
+       * Make lpfc_sli_reset_on_init = 1
+       * Minor cleanup to quieten sparse.
+       * Removed missing function = 0 in tmo routine in lpfc_els.c.
+       * Moved additional binding parameters into lpfc_defaults.c:
+         lpfc_automap / lpfc_fcp_bind_method
+       * Use msecs_to_jiffies() where applicable.
+       * Only use queue depth attribute only after SLI HBA setup was
+         completed.
+       * Put in memory barriers for PPC
+       * Added PCI_DEVICE_ID_HELIOS and PCI_DEVICE_ID_JFLY (Junior
+         Helios) support
+       * Added 4&10 gigabit choices in user option link_speed
+       * Updated timer logic: Set timer data after init_timer use
+         timer_pending() instead of expires.
+       * Removed some remnants of IP over FC support from Kconfig and
+         Makefile.
+       * Remove redundant prototypes for lpfc_handle_eratt,
+         lpfc_handle_latt and lpfc_read_pci.
+       * Ongoing cleanup of lpfc_init.c.
+       * Changed LPFC_CFG_DFT_HBA_Q_DEPTH -> LPFC_CFG_HBA_Q_DEPTH.
+       * Another cleanup stab at lpfc_ct.c. Remove castings, structure
+         code sanely, remove redundant code, reorganize code so that
+         functions are invoked after definition.
+
+Changes from 20040716 to 20040723
+
+       * Changed version number to 8.0.7
+       * Cleanup of lpfc_ct.c. Removed number of casts, removed tons of
+         dead/redundant code, cleaned up badly and poorly written code,
+         cleaned up return values.
+       * Fixed Persistent binding implementation
+       * Removed all references to lpfc_scsi_req_tmo
+       * Removed last references to lun_skip config parameter.
+       * Removed LPFC_DEV_RPTLUN node failure bit because we don't issue
+         REPORT_LUNS from the driver anymore.
+       * Removed LUN-tracking in driver.  Removed lpfc_lun struct and
+         moved any functionality we still need to lpfc_target.
+       * Added new lpfc_jedec_to_ascii() call and replace two instances
+         of duplicate code with calls to this function.
+       * Removed Volume Set Addressing handling on LUN IDs.
+       * Applied patch from Christoph Hellwig (hch@infradead.org) that
+         removes dead code belonging to lpfc_build_scsi_cmnd() and its
+         call path. This is related to the recently removed report_lun
+         code.
+
+Changes from 20040709 to 20040716
+
+       * Changed version number to 8.0.6
+       * Removed internal report LUNs usage.  Removed functions:
+         lpfc_disc_issue_rptlun, lpfc_disc_cmpl_rptlun,
+         lpfc_disc_retry_rptlun and their use.
+       * Removed usused scheduler prototypes in lpfc_crtn.h
+       * Replace lpfc_geportname() with generic memcmp().
+       * Rearrange code in lpfc_rcv_plogi_plogi_issue() to make it a
+         little more readable.
+       * Remove redundant port_cmp != 2 check in if
+         (!port_cmp) { .... if (port_cmp != 2).... }
+       * Clock changes: removed struct clk_data and timerList.
+       * Clock changes: seperate nodev_tmo and els_retry_delay into 2
+         seperate timers and convert to 1 argument changed
+         LPFC_NODE_FARP_PEND_t to struct lpfc_node_farp_pend convert
+         ipfarp_tmo to 1 argument convert target struct tmofunc and
+         rtplunfunc to 1 argument * cr_count, cr_delay and
+         discovery_threads are only needed to be module_params and not
+         visible via sysfs.
+
+Changes from 20040614 to 20040709
+
+       * Changed version number to 8.0.5
+       * Make lpfc_info static.
+       * Make lpfc_get_scsi_buf static.
+       * Print a warning if pci_set_mwi returns an error.
+       * Changed SERV_PARM to struct serv_parm.
+       * Changed LS_RJT to struct ls_rjt.
+       * Changed CSP to struct csp.
+       * Changed CLASS_PARMS to struct class_parms.
+       * Some cosmetic coding style cleanups to lpfc_fcp.c.
+       * Providing a sysfs interface that dumps the last 32
+         LINK_[UP|DOWN] and RSCN events.
+       * Get rid of delay_iodone timer.
+       * Remove qfull timers and qfull logic.
+       * Convert mbox_tmo, nlp_xri_tmo to 1 argment clock handler
+       * Removed duplicate extern defs of the bind variables.
+       * Streamline usage of the defines CLASS2 and CLASS3, removing
+         un-necessary checks on config[LPFC_CFG_FCP_CLASS].
+       * Moving the persistent binding variables to new file
+         lpfc_defaults.c
+       * Changed LPFC_SCSI_BUF_t to struct lpfc_scsi_buf.
+       * Moved config specific code from probe_one() into
+         config_setup(). Removing a redundant check on scandown value
+         from bind_setup() as this is already done in config_setup().
+       * Changed LPFC_SLI_t to struct lpfc_sli.
+       * Changed FCP_CMND to struct fcp_cmnd.
+       * Changed FCP_RSP to struct fcp_rsp.
+       * Remove the need for buf_tmo.
+       * Changed ULP_BDE64 to struct ulp_bde64.
+       * Changed ULP_BDE to struct ulp_bde.
+       * Cleanup lpfc_os_return_scsi_cmd() and it's call path.
+       * Removed lpfc_no_device_delay.
+       * Consolidating lpfc_hba_put_event() into lpfc_put_event().
+       * Removed following attributes and their functionality:
+         lpfc_extra_io_tmo, lpfc_nodev_holdio, lpfc_delay_rsp_err,
+         lpfc_tgt_queue_depth and lpfc_check_cond_err.
+       * Clock changes consolidating timers, just in the struct lpfc_hba,
+         to get rid of clkData and pass only one argument to timeout
+         routine. Also, removing need for outstanding clock linked list
+         to stop these timers at rmmod.
+       * Move lpfc.conf contents into lpfc_fcp.c. Removing per adapter
+         attributes in favor of global attributes.
+       * Fix a potential null pointer reference of pmbuf in lpfc_ct.c.
+       * On reset_lun, issue LUN_RESET as opposed to ABORT_TASK_SET.
+       * Removed SCSI_REQ_TMO related code.
+       * Introducing two new defines LPFC_ATTR_R and LPFC_ATTR_RW that do
+         a module_param, MODULE_PARM_DESC, lpfc_param_show,
+         [lpfc_param_store] and CLASS_DEVICE_ATTRIBUTE.
+       * Properly clean up when allocation of a linked BDE fails in the
+         SCSI queuecommand path.
+       * Fail SCSI command if dma_map_sg call fails.
+       * Remove unused macros SWAP_ALWAYS and SWAP_ALWAYS16.
+       * Reset context2 to 0 on exit in
+         lpfc_sli_issue_iocb_wait_high_priority() and
+         lpfc_sli_issue_iocb_wait().
+       * Arranging lpfc_scsiport.c to follow style of use after
+         definition. This removes the need for the cruft of forward
+         declarations. Also removing a redundant #define ScsiResult as it
+         already available elsewhere.
+       * Applying "Streamline lpfc error handling" patch from Christoph
+         Hellwig (hch@infradead.org) with following modifications: fix
+         mem leaks, remove some misplaced code that need not be there,
+         print a message on exit (old code prints two (entry/exit)), make
+         ret values consistent (either 1/0 or SUCCESS/FAILURE), keep all
+         eh routines in a single file (lpfc_scsiport.c).
+       * Move contents of lpfc_module_param.h into lpfc_fcp.c.
+       * Changed sysfs attributes to CLASS_DEVICE_ATTRIBUTES (previously
+         DEVICE_ATTRIBUTES). They now appear in
+         /sys/class/scsi_host/hostx (previously in
+         /sys/bus/pci/drivers/lpfc/devx).
+       * Removed lpfc_syfs.h and lpfc_sysfs.c.
+       * Cleanup of config params.  Throttle params have been removed.
+         max_lun has been removed. max_target is replaced with a #define,
+         lun_skip is removed.  Remove ipfc config params and related
+         code.
+       * Changed DMABUF_t usage to struct lpfc_dmabuf.
+       * Downsizing iCfgParam structure to include a_string, a_low, a_hi
+         and a_default values only.
+       * Free SCSI buf safety memory pool on shutdown to eliminate memory
+         leak.
+       * Change lpfc_printf_log to a #define. Also include phba->brd_no
+         and newline in the print string rather than in the #define.
+       * Remove code that optionally locates Host Group Pointers in host
+         memory SLIM since this is no longer needed for PPC64, once
+         CONFIG_PORT uses HBA's view of its BAR0.
+       * Removed the forward declarations of the sli functions and
+         rearranging the code in lpfc_sli.c.
+       * Removed the preamble functionality from logging.
+       * Make lpfc_sli_hba_setup() return negative error codes on error
+         and correct the comment left over in lpfc_fcp.c
+       * Removed the lpfc_loadtime variable.
+       * Put a space between all ifs and their open parens '('.
+       * Change Studly_Caps LPFC_SCSI_BUF_t to struct lpfc_scsi_buf.
+       * Fixed insmod hang after hardware error.
+       * Relocated scsi_host alloc to before we enable the interrupt
+         handler
+       * Add .tmp_versions directory to Makefile clean target.  This
+         directory is created in the 2.6.5+ build process (with Red Hat
+         kernels at least).
+       * Changing phba->config to kmalloc lpfc_icfgparam and not
+         *phba->config. This is manifesting itself as a panic in
+         pci_release_region().
+       * Fix for firmware download / board reset problem.
+       * Integrated patch from Christoph Hellwig (hch@infradead.org) to
+         reorganize and cleanup lpfc_fcp.c
+       * Don't abort commands immediately when there is an RSCN event to
+         give driver time to rediscover targets before the midlayer
+         retries the SCSI commands.
+
+Changes from 20040604 to 20040614
+
+       * Changed version number to 8.0.4
+       * Removed lpfc_valid_lun function.
+       * Added scsi_buf safety pool to address scsi_buf failures in
+         queuecommand under low memory conditions.  Allocations now come
+         from kmalloc initially, but if kmalloc fails, the allocation
+         comes from the safety pool.
+       * Modified lpfc_slave_alloc to only set the scsi_device->hostdata
+         pointer if the driver has discovered the target.  This routine
+         always returns success now as well since no error ever occurs in
+         the alloc routine.
+       * Mask only info and warning messages.  Print all error messages
+         irrespective of mask.
+       * Removing lpfc_log_chk_msg_disabled()
+       * Changed lpfc_printf_log to take struct lpfc_hba * directly
+         instead of a "board number".
+       * Convert dma_sync_single to pci_dma_sync_single_for_{device/cpu}.
+       * Implemented new style log messages. The message strings are now
+         embedded in the call to lpfc_printf_log.
+       * Decreased FLOGI discovery timeout to 20 seconds.
+       * On error in lpfc_pci_probe_one() return -1 and not 1.
+       * Allow for board numbers that are not sequential, paving the way
+         for hotplug support.
+       * scsi_add_host() can fail, so wrap it around in an if(). Also
+         initiate scsi_scan_host() after attaching the sysfs attributes.
+       * lpfc_release_version is used only in lpfc_ct.c, so move it there
+         and mark it as static.
+       * Removed lpfc_sleep_ms and replaced with mdelay or schedule calls
+         directly
+       * Removed all (struct list_head *) casts from clkData-related list
+         handling in list_add, list_del macros.
+       * Removed EXPORT_SYMBOLs.
+       * Removed LPFC_MIN_QFULL and lpfc_qthrottle_up.
+       * Replace LPFCSCSITARGET_t with struct lpfc_target.
+       * Replace LPFCSCSILUN_t with struct lpfc_lun.
+       * Remove unused struct declarations (fcPathId and fcRouteId) from
+         lpfc_scsi.h.
+       * Rewrite use of FC transport attributes.
+       * Fix crash when link is lost.  This was due to lpfc_delay_iodone
+         calling list_del on an object that was never put on a list.
+       * Remove trailing spaces at the end of all lines.
+       * Set MAX_FCP_TARGET to 256 from 0xff.  Set MAX_FCP_LUN and
+         MAX_FCP_CMDS to their decimal equivalents and updated
+         documentation.
+
+Changes from 20040526 to 20040604
+
+       * Changed version number to 8.0.3
+       * Completed sysfs FC transport support.
+       * Removed unused fields in SCSI LUN and SCSI Target structures:
+         void *pTargetProto; void *pTargetOSEnv; void *pLunOSEnv;
+       * Modified list_for_each to list_for_each_entry. Modified
+         list_for_each_safe to list_for_each_entry_safe.
+       * Remove lpfc_dfc.h file.
+       * Changed pHba->phba, pCommand->pcmd
+       * Changed plogi_ndlp -> plogindlp, pos_tmp->postmp, pRsp->prsp,
+         pCmd->pcmd
+       * Changed pText -> ptext
+       * Changed p_tmp_buff -> ptmpbuff
+       * Changed pBufList -> pbuflist, pRsp -> prsp, pCmd -> pcmd
+       * Changed *pos_tmp -> *postmp, *p_mbuf -> *pmbuf
+       * Following changes are made to the SCSI fast path: Added
+         DMA_BUF_t member to the lpfc_scsi_buf_t.  This will reduce a
+         memory allocation in the scsi fast path.  Added check for
+         targetp == NULL in the scsi fast path.  Increased number of
+         scatter gather entries in lpfc_scsi_dma_ext to 4 from 3 and
+         changed the size of lpfc_scsi_dma_ext to 264
+       * Fixing some missing static lpfc_nportdisc.c.
+       * Reordered #include lines so that lpfc.h doesn't have to #include
+         other header files.
+       * Remove lpfc_get_hba_sym_node_name() as a global EXPORT and make
+         it static.
+       * Move struct clk_data definition from lpfc_hw.h to lpfc_sli.h.
+       * Changed LPFC_IOCBQ_t to struct lpfc_iocbq.
+       * Changed LPFC_SLI_RING_t to struct lpfc_sli_ring.
+       * Changed LPFC_NODELIST_t to struct lpfc_nodelist.
+       * Rearranged lpfc_nportdisc.c by moving state machine array
+         (lpfc_disc_action) and the one function that uses it,
+         lpfc_disc_state_machine, to the end of the file, removing the
+         need for the raft of prototypes at the top.
+       * Changed LPFC_BINDLIST_t to struct lpfc_bindlist.
+       * Removed lpfc_issue_ct_rsp(), lpfc_sleep(), lpfc_add_bind(),
+         lpfc_del_bind(), lpfc_sli_wake_mbox_wait() and
+         lpfc_sli_issue_mbox_wait().
+       * Fixed a large number of overly-long lines.
+       * Fixed some discovery problems: Introduced deferred ndlp removal
+         when in DSM to avoid panic when in nested DMSs Fix NportId
+         fffc01 handling to not relogin after LOGO fixed handling of LOGO
+         on PLOGI issue.
+       * Changed SLI_CT_REQUEST to lpfc_sli_ct_request.
+       * Changed NAME_TYPE to struct lpfc_name.
+       * Changed lpfcCfgParam_t to struct lpfc_cfgparam.
+       * Changed LPFC_STAT_t to struct lpfc_stats.
+       * Changed HBAEVT_t to struct lpfc_hba_event.
+       * Changed Studly_Caps lpfcHBA_t to struct lpfc_hba.
+       * Removed no longer used tasklet_running flag.
+       * Removing *PSOME_VAR typedefs and using SOME_VAR* directly.
+       * Changing .use_clustering to ENABLE_CLUSTERING.
+       * Modify lpfc_queuecommand to return SCSI_MLQUEUE_HOST_BUSY when
+         it can't queue a SCSI command.  Also, remove cmnds_in_flight
+         member of struct lpfcHBA for 2.6 kernels as it was only needed
+         to determine what to return from queuecommand.
+       * Change return type of lpfc_evt_iocb_free to void as it doesn't
+         return anything.
+       * Remove unused cmnd_retry_list and in_retry members in struct
+         lpfcHBA.
+       * Remove some instances of unneeded casting of kmalloc's return in
+         lpfc_scsiport.c
+       * Remove lpfc_linux_attach() and lpfc_linux_detach(). Integrate
+         them into lpfc_probe_one() and lpfc_release_one() respectively.
+       * Remove lpfc_num_iocbs, lpfc_num_bufs module parameters
+       * Remove #defines for NUM_NODES, NUM_BUFS and NUM_IOCBS
+
+Changes from 20040515 to 20040526
+
+       * Changing version number to 8.0.2.
+       * Including dma-mapping.h as one of the include headers.  Also
+         rearrange the #include order.
+       * Make functions static as appropriate.
+       * queuecommand() will now return SCSI_MLQUEUE_HOST_BUSY instead of
+         1 to backpressure midlayer.
+       * Removed function prototypes for lpfc_start_timer() and
+         lpfc_stop_timer()
+       * Changed timer support to be inline.  Clk_data is now declared
+         right next to the corresponding timer_list entry so we don't
+         have to allocate these clk_data dynamically.
+       * Add readls after writels to PCI space to flush the writes.
+       * Fix misspelled word "safety" in function names.
+       * Fix up comments in lpfc.conf for per HBA parameters to reflect
+         new implementation.
+       * Change lpfc_proc_info handler to get the Nodename from
+         fc_nodename and not fc_portname.
+       * Fix up some comments and whitespace in lpfc_fcp.c.
+       * Formatting changes: get rid of leading spaces in code
+       * Move discovery processing from tasklet to a kernel thread.
+       * Move ndlp node from unmap list to map list if ADISC completed
+         successfully.
+       * Flush all the ELS IOCBs when there is a link event.
+       * LP9802 qdepth is twice the LP9802DC qdepth.  Delay
+         elx_sched_init after READ_CONFIG to get max_xri from the
+         firmware.  Reset ELX_CFG_DFT_HBA_Q_DEPTH to max_xri after
+         READ_CONFIG
+       * Fix fc_get_cfg_parm() to be more robust and support embedded hex
+         values.  The lpfc_param's are now defined as:
+         lpfc_log_verbose="lpfc:0,lpfc0:0x10,lpfc1:4,lpfc100:0xffff" The
+         "," delimter does not matter. It can be anything or not exist at
+         all. ie param = "lpfc:0lpfc0:0x10.lpfc1:4txtlpfc100:0xffff" will
+         also work.  Additionally the string is treated as case
+         insensitive.
+       * Changed all usage of lpfc_find_lun_device() to lpfc_find_lun().
+       * Removed unnecessary wrappers lpfc_find_lun_device() and
+         lpfc_tran_find_lun().
+       * Switch from using internal bus/id/lun to similar data from
+         scsi_device structure.
+       * Eliminate one-line function lpfc_find_target()
+       * Added slave_alloc, slave_destory
+       * lpfc_scsi_cmd_start can now acquire lun pointer from
+         scsi_device->hostdata, which is setup in slave_alloc.
+       * Eliminate unnecessary checking on every cmd just to see if we
+         are accessing the device the first time.
+       * Remove assumption in lpfc_reset_lun_handler that a valid
+         lpfc_scsi_buf is hung off of linux's scsi_cmnd->host_scribble
+         when our reset is called.
+
+Changes from 20040507 to 20040515
+
+       * Changed version to 8.0.1
+       * Fixed crash on driver rmmod after error injection tests and
+         lpfc_tasklet deadlock.
+       * Modified lpfc.conf to remove limit on number of support hosts
+       * Removed HBAAPI 
+       * Removed duplication of SCSI opcodes from lpfc_fcp.h that are
+         available in scsi/scsi.h
+       * Rework module_param usage
+       * Added MODULE_PARAM_DESC for various module_params
+       * Removed #define EXPORT_SYMTAB
+       * Removed #includes of if_arp.h and rtnetlink.h
+       * Removed string "Open Source" from MODULE_DESC
+       * Cleanup duplicated string definitions used by MODULE_DESC
+       * Renamed lpfc_pci_[detect|release] to lpfc_pci_[probe|remove]_one
+       * Fix formatting of lpfc_driver
+       * Remove unnecessary memset to 0 of lpfcDRVR
+       * Attach driver attributes always unless pci_module_init failed
+       * Remove all one-line wrappers from lpfc_mem.
+       * Remove lpfc_sysfs_set_[show|store] as it is no longer needed
+       * Redo lpfc_sysfs_params_[show|store] to one value per attribute rule
+       * Breakdown lpfc_sysfs_info_show into smaller one value per attribute
+       * Use device attributes instead of driver attributes where appropriate
+       * Remove no longer needed EXPORT_SYMBOLs
+       * Remove some unused code (1600 msg's related)
+
+Changes from 20040429 to 20040507
+
+       * Change version to 8.0.0
+       * Fix the number of cmd / rsp ring entries in lpfc_fcp.c to match
+         the divisions setup in lpfc_hw.h.
+       * Remove phba->iflag reference.
+       * Several locking improvements.
+       * Remove functions lpfc_drvr_init_lock, lpfc_drvr_lock,
+         lpfc_drvr_unlock and lpfc_hipri_*.
+       * Remove LPFC_DRVR_LOCK and LPFC_DRVR_UNLOCK macros.
+       * Make lpfc_info() use lpfc_get_hba_model_desc() instead of
+         rewriting almost identical code.
+       * Fix 1 overly long line in each of lpfc_cfgparm.h, lpfc_ftp.c and
+         lpfc_sli.c.
+       * Fix build for Red Hat 2.6.3 kernel by #defining MODULE_VERSION
+         only if it isn't already defined.
+       * Change elx_sli_issue_mbox_wait to return correct error code to
+         the caller.
+       * In some of the els completion routines, after calling
+         lpfc_elx_chk_latt, driver ignores the return code of the
+         lpfc_elx_chk_latt. This will prevent the discovery state machine
+         restarting correctly when there are link events in the middle of
+         discovery state machine running. Fix this by exiting discovery
+         state machine if lpfc_els_chk_latt returns a non zero value.
+       * Removed MAX_LPFC_BRDS from lpfc_diag.h
+       * Removed unused first_check.
+       * Remove some unused fields and defines.
+       * Change lpfc-param names to lpfc_param.
+       * Add use of MODULE_VERSION macro for 2.6 kernels.
+       * Shorten length of some of the comment lines to make them more
+         readable.
+       * Move FCP_* definitions to their own header file, lpfc_fcp.h.
+       * Remove unused prototypes from lpfc_crtn.h: fcptst, iptst,
+         lpfc_DELAYMS.
+       * Remove duplicated prototypes from lpfc_crtn.h:
+         lpfc_config_port_prep, lpfc_config_port_post,
+         lpfc_hba_down_prep.
+       * Removed some unused export_symbols.
+       * Install driver files into */drivers/scsi/lpfc instead of
+         */drivers/scsi.
+
+Changes from 20040426 to 20040429
+
+       * Declared export symbol lpfc_page_alloc and lpfc_page_free
+       * Changed lpfc version number to 6.98.3
+       * Move the definition of MAX_LPFC_BRDS to the only header file
+         that uses it (lpfc_diag.h).
+       * Change lpfc_sli_wake_iocb_wait to do a regular wake_up since
+         lpfc_sli_issue_iocb_wait now sleeps uninterruptible.
+       * Replace list_for_each() with list_for_each_safe() when a list
+         element could be deleted.
+       * Fix IOCB memory leak
+
+Changes from 20040416 to 20040426
+
+       * Change lpfc_config_port_prep() to interpret word 4 of the DUMP
+         mbox response as a byte-count
+       * Add info attribute to sysfs
+       * Minor formatting (spaces to tabs) cleanup in lpfc_sched.h
+       * Remove unused log message number 732
+       * Completing MODULE_PARM -> module_param changes
+       * Removed unused targetenable module parameter
+       * Removed locks from lpfc_sli_issue_mbox_wait routine
+       * Removed code that retry 29,00 check condition
+       * Removed code that manipulates rspSnsLen.
+       * Fix use of lun-q-depth config param
+       * Fix severity inconsistency with log message 249
+       * Removed lpfc_max_target from lpfc_linux_attach
+       * Replace references to lpfcDRVR.pHba[] with lpfc_get_phba_by_inst()
+       * Change lpfc_param to lpfc-param
+       * Partially removed 32 HBA restriction within driver.  Incorported
+         lpfc_instcnt, lpfc_instance[], and pHba[] into lpfcDRVR
+         structure Added routines lpfc_get_phba_by_inst()
+         lpfc_get_inst_by_phba() lpfc_check_valid_phba()
+       * Turn on attributes "set" & "params" by default.
+       * Further formatting/whitespace/line length cleanup on: lpfc_ct.c
+         lpfc_els.c lpfc_fcp.c lpfc_hbadisc.c lpfc_init.c lpfc_ipport.c
+         lpfc_mbox.c lpfc_nportdisc.c lpfc_sched.c lpfc_sched.h
+         lpfc_scsi.h lpfc_scsiport.c lpfc_sli.c and lpfc_sli.h
+       * Add log message 249 to log any unsupported device addressing
+         modes encountered.
+       * Add support for 256 targets and 256 LUNs
+       * Fixed panic in lpfc_linkdown.
+       * Removed (struct list_head*) casting in several calls to list_del
+       * Free irq reservation and kill running timers when insmod or
+         modprobe are killed via ctrl-c
+       * Remove drivers/scsi from include path
+       * Wrap use of log message 311 in macro
+       * Detect failure return from pci_map_sg call in lpfc_os_prep_io
+       * Fix use-after-free of IOCB in lpfc_sli_process_sol_iocb which
+         was causing an Oops on 2.6.5 kernel.
+       * Cleanup use of several gotos not used for error exit.
+       * Replace memcpy_toio() and memcpy_toio() with endian-dependent
+         lpfc_memcpy_to_slim() and lpfc_memcpy_from_slim() so that for
+         big endian hosts like PPC64, the SLIM is accessed 4 bytes at a
+         time instead of as a byte-stream.
+
+Changes from 20040409 to 20040416
+
+       * The scsi_register and scsi_alloc_host OS calls can fail and
+         return a zero-valued host pointer.  A ctrl-C on 2.6 kernels
+         during driver load will cause this and the driver to panic.
+         Fixed this bug.  Also found a bug in the error_x handling with
+         lpfc_sli_hba_down - it was in the wrong place and the driver
+         lock was not held, but needed to be (in lpfc_linux_attach) Fixed
+         both.  Did some minor comment clean up.
+       * Removed unwanted (void *) castings.
+       * Replace define of INVALID_PHYS, with kernel 2.6.5's
+         dma_mapping_error() and add a inline function for earlier
+         kernels.  Remove lpfc_bad_scatterlist().
+       * Clean up formatting in hbaapi.h, lpfc.h, lpfc_cfgparm.h,
+         lpfc_crtn.h, lpfc_ct.c, lpfc_diag.h, lpfc_disc.h, lpfc_els.c,
+         lpfc_fcp.c, lpfc_hbadisc.c, lpfc_hw.h, lpfc_init.c,
+         lpfc_ipport.c, lpfc_logmsg.c, lpfc_logmsg.h and lpfc_scsiport.c
+         - mostly replacing groups of 8 spaces with hard tabs and keeping
+         lines to 80 column max..
+       * Removed LPFC_DRVR_LOCK call from lpfc_unblock_requests for 2.4
+         kernels.  The lpfc_scsi_done routine already unlocks the driver
+         lock since it expects this lock to be held.
+       * Removed global lock capabilities from driver lock routines
+       * Remove SA_INTERRUPT flag from request_irq
+       * Move dma_addr_t cast inside of getPaddr macro as everywhere
+         getPaddr is used, the return is cast to dma_addr_t.
+       * Clean up formatting in lpfc_sli.c and lpfc_sysfs.c - mostly
+          replacing groups of 8 spaces with hard tabs and keeping lines
+          to 80 column max.
+       * Fix build for RHEL 2.1 BOOT kernels by always #including
+         interrupt.h in lpfc.h.
+       * Fix RHEL 3 build by #defining EXPORT_SYMTAB.
+       * Replace sprintf with snprintf in lpfc_proc_info.
+       * Fix build warnings on 2.6 kernels - remove no longer used calls
+         to  character device initialization.
+       * Initial support code for discovery in tasklet conversion.
+       * Removing char interface and ioctl code.
+       * Change all elx prefixes to lpfc
+       * Replace lpfc_write_slim() & lpfc_read_slim() with memcpy_toio(),
+         memcpy_fromio(), writel() & readl().
+
+Changes from 20040402 to 20040409
+
+       * Replaced lpfc_read_hbaregs_plus_offset and
+         lpfc_write_hbaregs_plus_offset functions with readl and writel.
+       * Get rid of long mdelay's in insmod path
+       * Changed the way our pci_device_id structures are initialized
+       * Replace lpfc_read/write_CA/HA/HC/HS with calls to readl() &
+         writel() directly.
+       * Increase SLI2_SLIM to 16K Increase cmd / rsp IOCBs accordingly
+       * Removed lpfc_els_chk_latt from the lpfc_config_post function.
+         lpfc_els_chk_latt will enable the link event interrupts when
+         flogi is pending which causes two discovery state machines
+         running parallely.
+       * Add pci_disable_device to unload path.
+       * Move lpfc_sleep_event from lpfc_fcp.c to lpfc_util_ioctl.c
+       * Call dma_map_single() & pci_map_single() directly instead of via
+         macro lpfc_pci_map().  Allow address 0 for PPC64.
+       * Change sleep to uninterruptible in lpfc_sli_issue_icob_wait
+         because this function doesn't handle signals.
+       * Move lpfc_wakeup_event from lpfc_fcp.c to lpfc_ioctl.c
+       * Remove unneeded #include <linux/netdevice.h>
+       * Remove unused clock variables lpfc_clkCnt and lpfc_sec_clk.
+       * Get rid of capitalization of function names.
+       * Removed lpfc_addr_sprintf.
+       * Implemented gotos in lpfc_linux_attach for error cases.
+       * Replace mlist->dma.list = dmp->dma.list; to mlist = dmp.
+       * Remove functions lpfc_get_OsNameVersion and elx_wakeup. Change
+         elx_wakeup to wake_up_interruptible
+       * Add function lpfc_get_os_nameversion and change
+         lpfc_get_OsNameVersion to lpfc_get_os_nameversion.
+       * Remove lpfc_get_OsNameVersion
+       * Change driver name to a consistent lpfc in every visible place.
+       * Fix build warning: removed unused variable ret in lpfc_fdmi_tmo.
+       * Remove lpfc_utsname_nodename_check function
+       * Remove functions lpfc_register_intr and lpfc_unregister_intr
+       * Fill in owner field in lpfc_ops file_operations struct and
+         remove now unnecessary open and close entry points.
+       * Change function name prefixes from elx_ to lpfc_
+       * Remove special case check for TUR in elx_os_prep_io()
+       * Renamed elx_scsi.h to lpfc_scsi.h
+       * Renamed elx_sched.h to lpfc_sched.h
+       * Renamed elx_mem.h to lpfc_mem.h
+       * Renamed elx_sli.h to lpfc_sli.h
+       * Renamed elx_logmsg.h to lpfc_logmsg.h
+       * Renamed elx.h to lpfc.h
+       * Renamed elx_sli.c to lpfc_sli.c
+       * Renamed elx_sched.c to lpfc_sched.c
+       * Renamed elx_mem.c to lpfc_mem.c
+       * Renamed elx_logmsg.c to lpfc_logmsg.c
+       * Renamed lpfcLINUXfcp.c lpfc_fcp.c
+       * Renamed elx_clock.c to lpfc_clock.c
+       * Reduce stack usage in lpfc_info().
+       * Move lpip_stats structure from lpfc_hba.h to lpfc_ip.h.
+       * Move lpfc_stats and HBAEVT_t structures from lpfc_hba.h to
+         lpfc.h
+       * Remove lpfc_hba.h
+       * Remove duplicate rc definitions from 
+       * Removed code which used next pointer to store mbox structure.
+       * Cleaned up list iterations.
+       * Removed non list manipulation of the next pointers.
+       * Change list_del()/INIT_LIST_HEAD sequences to list_del_init()
+       * In ELX_IOCBQ_t: Moved hipri_trigger field to iocb_flag. Combined
+         hipri_wait_queue and rsp_iocb in union
+       * Replaced casting from list_head with list_entry macro.
+       * Added ct_ndlp_context field to the ELX_IOCBQ_t.
+       * Do not use DMABUf_t list to store ndlp context
+       * Return 0 from lpfc_process_iotcl_util() when ELX_INITBRDS
+         succeeds.
+       * remove elx_os_scsiport.h
+       * Do not use DMABUf_t list to hold rpi context
+       * Replace elx_cfg_* names with lpfc_cfg-*
+       * Moved FCP activity to ring 0.  Moved ELS/CT activity to ring 2.
+       * Clean up formatting of elx_sli.h (tabs for indents, 80 column
+         lines).
+       * Remove unused elxclock declaration in elx_sli.h.
+       * Since everywhere IOCB_ENTRY is used, the return value is cast,
+         move the cast into the macro.
+       * Split ioctls out into seperate files
+
+Changes from 20040326 to 20040402
+
+       * Updated ChangeLog for 20040402 SourceForge drop.
+       * Use safe list iterator for ndlp list
+       * Added code to return NLP_STE_FREED_NODE from the discovery
+         state machine functions if the node is freed from the
+         function.
+       * Fixes to DMABUF_t handling
+       * Fix for load error in discovery
+       * Remove loop_cnt variable from lpfc_rcv_plogi_unused_node.
+       * Remove nle. reference.
+        * Remove support for building 2.4 drivers
+       * Remove elx_util.h and replace elx_disc.h with lpfc_disc.h
+       * Implemented the Linux list macros in the discovery code.
+         Also moved elx_disc.h contents into lpfc_disc.h
+       * Unused variable cleanup
+       * Use Linux list macros for DMABUF_t
+       * Break up ioctls into 3 sections, dfc, util, hbaapi
+         rearranged code so this could be easily seperated into a
+         differnet module later All 3 are currently turned on by
+         defines in lpfc_ioctl.c LPFC_DFC_IOCTL, LPFC_UTIL_IOCTL,
+         LPFC_HBAAPI_IOCTL
+       * Misc cleanup: some goto's; add comments; clarify function
+         args
+       * Added code to use list macro for ELXSCSITARGET_t.
+       * New list implementation for ELX_MBOXQ_t
+       * Cleaned up some list_head casting.
+       * Put IPFC ifdef around two members of struct lpfc_nodelist.
+       * Cleaned up iocb list using list macros and list_head data
+         structure.
+       * lpfc_online() was missing some timer routines that were
+         started by lpfc_linux_attach().  These routines are now also
+         started by lpfc_online().  lpfc_offline() only stopped
+         els_timeout routine.  It now stops all timeout routines
+         associated with that hba.
+       * Replace seperate next and prev pointers in struct
+         lpfc_bindlist with list_head type.  In elxHBA_t, replace
+         fc_nlpbind_start and _end with fc_nlpbind_list and use
+         list_head macros to access it.
+       * Fix ulpStatus for aborting I/Os overlaps with newer firmware
+         ulpStatus values
+       * Rework params_show/store to be consistent as the other
+         routines.  Remove generic'ness and rely on set attribute.
+       * Remove unused log message.
+       * Collapse elx_crtn.h and prod_crtn.h into lpfc_crtn.h
+       * Ifdef Scheduler specific routines
+       * Removed following ununsed ioclt's: ELX_READ_IOCB
+         ELX_READ_MEMSEG ELX_READ_BINFO ELX_READ_EINVAL ELX_READ_LHBA
+         ELX_READ_LXHBA ELX_SET ELX_DBG LPFC_TRACE 
+       * Removed variable fc_dbg_flg
+       * Fixed a bug where HBA_Q_DEPTH was set incorrectly for
+         3-digit HBAs.  Also changed can_queue so midlayer will only
+         send (HBA_Q_DEPTH - 10) cmds.
+       * Clean up code in the error path, check condition.  Remove
+         ununsed sense-related fields in lun structure.
+       * Added code for safety pools for following objects: mbuf/bpl,
+         mbox, iocb, ndlp, bind
+       * Wrapped '#include <elx_sched.h>' in '#ifdef USE_SCHEDULER'.
+       * Fixed 'make clean' target.
+        * Build now ignores elx_sched.o, and includes lpfc_sysfs.o.
+       * Wrapped lpfndd.o target in BUILD_IPFC ifdef.
+       * Removed elx_os.h inclusion in implementation files.
+       * Removed ELX_OS_IO_t data structure and put data direction
+         and non scatter/gather physical address into the scsi buffer
+         structure directly.  Moved DRVR_LOCK, putPaddr, getPaddr
+         macros and some defines into elx.h since they are required
+         by the whole driver.
+       * Migrated following ioctls (debug) ELX_DISPLAY_PCI_ALL
+         ELX_DEVP ELX_READ_BPLIST ELX_RESET_QDEPTH ELX_STAT.
+       * Step 1 of attempt to move all Debug ioctls to sysfs.
+         Implemented the following IOCTLs in sysfs: ELX_WRITE_HC
+         ELX_WRITE_HS ELX_WRITE_HA ELX_WRITE_CA ELX_READ_HC
+         ELX_READ_HS ELX_READ_HA ELX_READ_CA ELX_READ_MB ELX_RESET
+         ELX_READ_HBA ELX_INSTANCE ELX_LIP.  Also introduced
+         attribute "set" to be used in conjuction with the above
+         attributes.
+       * Removed DLINK, enque and deque declarations now that clock
+         doesn't use them anymore
+       * Separated install rule so that BUILD_IPFC has to be set when
+         make is called in order for the install rule to attempt to
+         copy the lpfndd.o driver.  This change fixes a bug that
+         occurs because the install rule by default attempted to
+         install lpfndd.o, whereas the default make rule did not by
+         default build lpfndd.o.
+       * Keep track if hbaapi index numbers need to be refreshed.
+       * Removed prod_os.h from include list.
+       * Removed LPFC_LOCK and LPFC_UNLOCK macros.  Added OS calls
+         into elx_os_scsiport.c.  This file is now empty.
+       * Added spin_lock_irqsave and spin_unlock_irqrestore calls
+         into code directly and removed LPFC_LOCK_ and _UNLOCK_
+         macros
+       * Remove references to "elx_clock.h"
+       * Added utsname.h to include list.  The previous checkin to
+         elx_os.h removed its inclusion of utsname.h since there is
+         precious little in the file.  However, lpfcLINUXfcp.c needs
+         it and now has it.
+       * Removed some commented-out code
+       * Removed elx_lck_t data structure, stray elxDRVR_t type, and
+         include from file.  No longer used.
+       * Removed two PCI Sync defines.  Removed includes - not
+         needed.  Cleaned up macro lines.
+       * Added two functions from elxLINUXfcp.c.  These functions
+         were IPFC specific.
+       * Removed hipri lock abstractions and added OS call into code.
+         Removed elx_lck_t and added spinlock_t directly. Moved two
+         IPFC functions into lpfc_ipport.c
+       * Moved IP specific structures to lpfc_ip.h file.
+       * lpfc_ipfarp_timeout() uses system timer.  Remove all usages
+         of old internal clock support.
+       * Made changes to compile without IPFC support for the default
+         build.  Added ifdef IPFC for all lpfc_ip.h includes.
+       * Patched elx_free_scsi_buf
+       * Removed elx_sched.o from 2.6 dependencies
+       * Reworked lpfc_pcimap.
+       * Use Linux swap macros to replace ELX swapping macros
+         (SWAP_SHORT, SWAP_LONG, SWAP_DATA, SWAP_DATA16,
+         PCIMEM_SHORT, PCIMEM_LONG, PCIMEM_DATA).
+       * move in_interrupt() check inside of elx_sleep_ms()
+       * Moved location of pci.h include.
+       * Restored elx_lck_t types in elxHBA_t.
+       * Removed elx_pci_dma_sync call.  Also removed some PCI
+         defines from elx_hw.h and removed the spinlock_t locks that
+         are no longer used in elx.h
+       * elx_iodone() now uses system timer.
+       * elx_qfull_retry() now uses system timer.
+       * lpfc_put_buf(), lpfc_ip_xri_timeout() and
+         lpfc_ip_timeout_handler() now use system timer.
+       * lpfc_fdmi_tmo() and lpfc_qthrottle_up() now use system
+          timer.
+       * Removed num_bufs and num_iocbs configuration parameters.
+       * Fixed a memory corruption bug. This was caused by a memory
+         write to ndlp structure from lpfc_cmpl_els_acc function.
+         This ndlp structure was freed from lpfc_els_unsol_event.
+       * lpfc_disc_timeout() and lpfc_establish_link_tmo() now use
+         system timer.  Also update lpfc_els_retry_delay() to do a
+         single lock release at the end.
+       * Remove use of PAN (pseudo adapter number).
+       * Reintroduced usage of the cross compiler for building on
+         ppc64 to remove build errors that were cropping up when
+         using the standard gcc compiler.
+       * Fix no-unlock-before return in lpfc_els_retry_delay which was
+         causing  a deadlock on insmod in some environments.
+       * Minor format changes fix up comments
+       * Create utility clock function elx_start_timer() and
+         elx_stop_timer().  All timeout routines now use these common
+         routines.
+       * Minor formating changes fix up comments
+       * Minor formatting changes get rid of failover defines for
+         syntax checking
+       * Minor formatting changes remove ISCSI defines.
+       * Fix typo in install target for 2.4 kernels.
+       * Removed unused elx_scsi_add_timer extern function
+         declaration.
+       * Cleanup casting around DMA masks.
+       * Comment out lpfndd.o modules_install section as lpfndd.o is
+         not generated if CONFIG_NET_LPFC is not set. Also refer to
+         BASEINCLUDE only in out of kernel source module builds as it
+         will not exist otherwise.
+       * Removed unused malloc counters from lpfcLINUXfcp.c.
+       * Remove some unnecessary #includes in lpfcLINUXfcp.c
+       * Remove unncessary #includes in elxLINUXfcp.c
+       * Minor formatting cleanups in Makefile to avoid some
+          linewrapping.
+       * Removed unused elx_mem_pool data structure.
+       * Remove several unnecessary #includes.
+       * Moving fix for memory leak in ioctl lip area to sysfs's lip.
+       * Removed unused elx_dma_handle_t elx_acc_handle_t
+         FC_MAX_SEGSZ and FC_MAX_POOL.
+       * Rewrite of Makefile. Fixes breakages with make -j4 during
+         kernel compile. Does not recompile all files on every
+         build. Uses the kernel build's definitions of CFLAGS,
+         MODFLAGS etc. Removed "make rpm" option.
+       * Removed unused #defines CLOSED, DEAD, OPENED, NORMAL_OPEN
+         and unneeded #include of elx_sched.h in elx.h.
+       * Several log message updates
+       * Add PCI_DEVICE_ID_FIREFLY for LP6000
+       * Fixed known issues in 20040326: driver crashes on rmmod in
+         both 2.4 and 2.6 kernels
+       
+
+Changes from 20040319 to 20040326
+
+       * Updated ChangeLog for 20040326 SourceForge drop.
+       * remove lpfc_isr / lpfc_tmr logic fixed up 8 spaces from
+         previous checkins with tabs
+       * replace elx_in_intr() with in_interrupt()
+       * Remove unused messages 1602 and 1603.
+       * Fix the following issues with log messages: Remove unused
+         messages 406, 407, 409, 927, 928, 1201, 1202, 1204, 1205, 1206
+         and 1207.  Create a new message 738 to fix duplicate instances
+         of 736.
+       * Removed remaining pci interface abstractions from elxLINUXfcp.c.
+         Implemented OS calls directly in all remaining files and cleaned
+         up modules.  Removed prototypes as well.
+       * Removed following functions/structures elx_mem_dmapool
+         elx_idx_dmapool elx_size_dmapool elx_kmem_lock dfc_data_alloc
+         dfc_data_free dfc_mem struct mbuf_info elx_acc_handle_t
+         data_handle elx_dma_handle_t dma_handle struct elx_memseg
+         MEMSEG_t
+       * lpfc_els_timeout_handler() now uses system timer.
+       * Further cleanup of #ifdef powerpc
+       * lpfc_scsi_timeout_handler() now uses system timer.
+       * Replace common driver's own defines for endianess w/ Linux's
+         __BIG_ENDIAN etc.
+       * Added #ifdef IPFC for all IPFC specific code.
+       * lpfc_disc_retry_rptlun() now uses system timer.
+       * lpfc_npr_timeout() now uses system timer.
+       * Modified detect code, on insmod, to only wait a max of 2 secs if
+         link comes up and there are no devices.
+       * Move remaining message logging functions into
+         elx_logmsg.c/elx_logmsg.h.
+       * Added code to clear link attention bit when there is a pending
+         link event and the memory allocation for read_la mail box
+         command fails.
+       * Removed function calls for mapping bar registers and allocating
+         kernel virtual memory mappings to the mapped bars Removed
+         prototypes, lpfc_driver_cache_line, and pci_bar1_map rename to
+         pci_bar2_map.
+       * Allocate mbox only if the hba_state is in ready state.
+       * Complete lip support via sysfs. To lip, echo brdnum >
+         /sys/bus/pci/drivers/lpfc/lip.
+       * moving sysfs show/store implementations to lpfc_sysfs.c. Also add
+         support for lip.
+       * Add files: lpfc_sysfs.c, lpfc_sysfs.h
+       * move LPFC_DRIVER_NAME and LPFC_MODULE_DESC out of lpfcLINUXfcp.c
+         to lpfc_version.h, since it is now needed in lpfc_sysfs.c
+       * elx_mbox_timeout now uses system timer
+       * Changed lpfc_nodev_timeout, lpfc_els_retry_delay and
+         lpfc_linkdown_timeout to use the system timer instead of
+         internal clock support.
+       * Move remaining message logging functions in elx_util.c to
+         elx_logmsg.c.
+       * Remove some unnecessary typecasting.
+       * Remove log message that is no longer used (was used by
+         elx_str_atox).
+       * Replaced DLINK_t and SLINK_t by standard Linux list_head
+       * Removed deque macro
+       * Replaced ELX_DLINK_t ans ELX_SLINK_t by Linux struct list_head
+         (except for clock)
+       * Removed following functions from code: linux_kmalloc linux_kfree
+         elx_alloc_bigbuf elx_free_bigbuf
+       * Removed following abstract functions from the code.  elx_malloc
+         elx_free elx_ip_get_rcv_buf elx_ip_free_rcv_buf
+         elx_mem_alloc_dmabuf elx_mem_alloc_dmabufext elx_mem_alloc_dma
+         elx_mem_alloc_buf lpfc_bufmap
+       * Removed custom PCI configuration #defines and replaced with
+         OS-provided #defines. Also added linux/pci.h to *.c files.
+       * Remove elx_str_ctox.  Replace elx_str_atox with sscanf.
+       * Many indentation/whitespace fixes.
+       * Replace elx_str_ctox with isxdigit where it was only used to
+         check the value of a character.
+       * Removed following functions from the code.  elx_kmem_free
+         elx_kmem_alloc elx_kmem_zalloc
+       * Change use of 2.4 SCSI typedef Scsi_Host_Template to  struct
+         scsi_host_template for 2.6 kernels.
+       * Change use of 2.4 SCSI typedefs (Scsi_Device, Scsi_Cmnd,
+         Scsi_Request) the their real struct names.
+       * Move 2.6 compatibility irqreturn definitions to lpfc_compat.h.
+         Protect these definitions from conflicting with similar ones in
+         later 2.4 kernels.
+       * Remove unused definitions: LINUX_TGT_t, LINUX_LUN_t,
+         LINUX_BUF_t, elx_lun_t, SET_ADAPTER_STATUS.
+       * Convert pci_ calls to linux 2.6 dma_ equivalents.
+       * Removed unused types: struct buf, struct sc_buf, T_SCSIBUF
+         typedef.
+       * Fix Makefile so that 2.4 drivers don't always rebuild all files.
+       * Remove unused _static_ and fc_lun_t definitions.
+       * Cleaned up some memory pool implementation code.
+       * Fix panic with char dev changes. Turns out that 2.6.4 code does
+         the same in kernel space with the 2.4 interface style
+         definitions. So remove the new char dev code altogether.
+       * Remove typecasting from fc_get_cfg_param and consolidate
+         multiple instances of the parameter switch into a single
+         instance.
+       * Use lpfc_is_LC_HBA() macro that tests pcidev->device directly
+         instead of saving a private copy that undergoes varied shifting
+         & casting.
+       * Removed usage of all memory pools.
+
+Changes from 20040312 to 20040319
+       
+       * Use dev_warn instead of printk for 2.6 kernels
+       * Correct Iocbq completion routine for 2.6 kernel case
+       * Change void *pOSCmd to Scsi_Smnd *pCmd
+       * Change void *pOScmd to struct sk_buff *pCmd
+       * Remove data directon code.
+       * Removed memory pool for buf/bpl buffers and use kmalloc/kfree
+         pci_pool_alloc/free directly.
+       * Move PPC check for DMA address 0 in scatter-gather list, into
+         lpfc_compat.h
+       * Always use pci_unmap_single() instead of pci_unmap_page()
+       * Clean up the 2.6 vs 2.4 #if blocks.
+       * Conditionalize Scheduler
+       * Add a comment to explain a little what the first Makefile
+         section does.
+       * Removed lpfc_intr_post
+       * Sysfs new display format. Also added write functionality. You
+         can [ echo "0 log_verbose 3" >
+         /sys/bus/pci/drivers/lpfc/params]. Hex support yet to be added.
+       * Removed several #ifdef powerpc, including for a discovery issue
+         in lpfc_ValidLun()
+       * Change elx_printf_log to use vsprintf.
+       * Added lpfc_compat.h provides macros to aid compilation in the
+         Linux 2.4 kernel over various platform architectures.  Initially
+         support mapping to a DMA address.
+       * Removed memory pool for nlp/bind buffers and use kmalloc/kfree
+         directly.
+       * Removed memory pool for iocb buffers and use kmalloc/kfree
+         directly.
+       * Removed memory pool for mailbox buffers and use kmalloc/kfree
+         directly.
+       * Cleaned up back and forth casts
+       * Initial support for sysfs for 2.6 kernel.
+       * Changed elx_dma_addr_t to dma_addr_t
+       * Fix a 2.6 kernel check to be >= 2.6.0 instead of > (was missing
+         2.6.0).
+       * Remove elx_printf and elx_str_sprintf. Replace elx_print with
+         printk.
+       * Replace elx_printf with printk.
+       * Replace elx_str_sprintf with sprintf.
+       * Removed the mem_lock, its prototype, function, macro, and
+         iflags.
+       * Use kmalloc/kfree for ELX_SCSI_BUF_t
+       * Use linux pci_pools for SCSI_DMA_EXT
+       * Use linux pci_pools for BPLs.
+       * Minor cleanup of DFC args for PPC64.
+       * Several small indentation cleanups.
+       * New Linux 2.6 style of char device registration.
+       * Migrated members of LPFCHBA_t and LINUX_HBA_t into elxHBA_t
+       * Use strcpy, strncmp, isdigit, strlen instead of abstractions
+       * Cleanup of driver_template.
+       * Facilitate compile time turn on/off of lpfc_network_on.
+       * Split large source files into smaller, better named ones.
+
+Changes from 2.10a to 20040312
+
+       * Fix build for 2.4 kernels
+       * Move driver version macros into lpfc_version.h file.
+       * Fixed data miscompare with LIP.
+       * Removed elx_sli, elx_ioc, elx_disc, elx_sch routines,
+         prototypes, and reference points.
+       * Correct the space insertions with hardtabs
+       * Remove routine call pointers in ELX_SLI_INIT_t struct.
+       * Removed module locks except for drvr, mem, and clock.
+       * Removed unused module locks from sourcebase. Kept drvr_lock,
+         mem_lock, and clock_lock.
+       * Change NULL to 0
diff --git a/Documentation/scsi/lpfc.txt b/Documentation/scsi/lpfc.txt
new file mode 100644 (file)
index 0000000..4dbe413
--- /dev/null
@@ -0,0 +1,83 @@
+
+LPFC Driver Release Notes:
+
+=============================================================================
+
+
+                               IMPORTANT:
+
+  Starting in the 8.0.17 release, the driver began to be targeted strictly
+  toward the upstream kernel. As such, we removed #ifdefs for older kernels
+  (pre 2.6.10). The 8.0.16 release should be used if the driver is to be
+  run on one of the older kernels.
+
+  The proposed modifications to the transport layer for FC remote ports
+  and extended attribute support is now part of the upstream kernel
+  as of 2.6.12. We no longer need to provide patches for this support,
+  nor a *full* version which has old an new kernel support.
+  
+  The driver now requires a 2.6.12 (if pre-release, 2.6.12-rc1) or later
+  kernel.
+  
+  Please heed these dependencies....
+
+
+   ********************************************************************
+
+
+The following information is provided for additional background on the
+history of the driver as we push for upstream acceptance.
+
+Cable pull and temporary device Loss:
+
+  In older revisions of the lpfc driver, the driver internally queued i/o 
+  received from the midlayer. In the cases where a cable was pulled, link
+  jitter, or a device temporarily loses connectivity (due to its cable
+  being removed, a switch rebooting, or a device reboot), the driver could
+  hide the disappearance of the device from the midlayer. I/O's issued to
+  the LLDD would simply be queued for a short duration, allowing the device
+  to reappear or link come back alive, with no inadvertant side effects
+  to the system. If the driver did not hide these conditions, i/o would be
+  errored by the driver, the mid-layer would exhaust its retries, and the
+  device would be taken offline. Manual intervention would be required to
+  re-enable the device.
+
+  The community supporting kernel.org has driven an effort to remove
+  internal queuing from all LLDDs. The philosophy is that internal
+  queuing is unnecessary as the block layer already performs the 
+  queuing. Removing the queues from the LLDD makes a more predictable
+  and more simple LLDD.
+
+  As a potential new addition to kernel.org, the 8.x driver was asked to
+  have all internal queuing removed. Emulex complied with this request.
+  In explaining the impacts of this change, Emulex has worked with the
+  community in modifying the behavior of the SCSI midlayer so that SCSI
+  devices can be temporarily suspended while transport events (such as
+  those described) can occur.  
+
+  The proposed patch was posted to the linux-scsi mailing list. The patch
+  is contained in the 2.6.10-rc2 (and later) patch kits. As such, this
+  patch is part of the standard 2.6.10 kernel.
+
+  By default, the driver expects the patches for block/unblock interfaces
+  to be present in the kernel. No #define needs to be set to enable support.
+
+
+Kernel Support
+
+  This source package is targeted for the upstream kernel only. (See notes
+  at the top of this file). It relies on interfaces that are slowing
+  migrating into the kernel.org kernel.
+
+  At this time, the driver requires the 2.6.12 (if pre-release, 2.6.12-rc1)
+  kernel.
+
+  If a driver is needed for older kernels please utilize the 8.0.16
+  driver sources.
+
+
+Patches
+
+  Thankfully, at this time, patches are not needed.
+
+
diff --git a/Documentation/sound/alsa/VIA82xx-mixer.txt b/Documentation/sound/alsa/VIA82xx-mixer.txt
new file mode 100644 (file)
index 0000000..1b0ac06
--- /dev/null
@@ -0,0 +1,8 @@
+
+                               VIA82xx mixer
+                               =============
+
+On many VIA82xx boards, the 'Input Source Select' mixer control does not work.
+Setting it to 'Input2' on such boards will cause recording to hang, or fail
+with EIO (input/output error) via OSS emulation.  This control should be left
+at 'Input1' for such cards.
diff --git a/Documentation/sound/alsa/hda_codec.txt b/Documentation/sound/alsa/hda_codec.txt
new file mode 100644 (file)
index 0000000..e9d07b8
--- /dev/null
@@ -0,0 +1,299 @@
+Notes on Universal Interface for Intel High Definition Audio Codec
+------------------------------------------------------------------
+
+Takashi Iwai <tiwai@suse.de>
+
+
+[Still a draft version]
+
+
+General
+=======
+
+The snd-hda-codec module supports the generic access function for the
+High Definition (HD) audio codecs.  It's designed to be independent
+from the controller code like ac97 codec module.  The real accessors
+from/to the controller must be implemented in the lowlevel driver.
+
+The structure of this module is similar with ac97_codec module.
+Each codec chip belongs to a bus class which communicates with the
+controller.
+
+
+Initialization of Bus Instance
+==============================
+
+The card driver has to create struct hda_bus at first.  The template
+struct should be filled and passed to the constructor:
+
+struct hda_bus_template {
+       void *private_data;
+       struct pci_dev *pci;
+       const char *modelname;
+       struct hda_bus_ops ops;
+};
+
+The card driver can set and use the private_data field to retrieve its
+own data in callback functions.  The pci field is used when the patch
+needs to check the PCI subsystem IDs, so on.  For non-PCI system, it
+doesn't have to be set, of course.
+The modelname field specifies the board's specific configuration.  The
+string is passed to the codec parser, and it depends on the parser how
+the string is used.
+These fields, private_data, pci and modelname are all optional.
+
+The ops field contains the callback functions as the following:
+
+struct hda_bus_ops {
+       int (*command)(struct hda_codec *codec, hda_nid_t nid, int direct,
+                      unsigned int verb, unsigned int parm);
+       unsigned int (*get_response)(struct hda_codec *codec);
+       void (*private_free)(struct hda_bus *);
+};
+
+The command callback is called when the codec module needs to send a
+VERB to the controller.  It's always a single command.
+The get_response callback is called when the codec requires the answer
+for the last command.  These two callbacks are mandatory and have to
+be given.
+The last, private_free callback, is optional.  It's called in the
+destructor to release any necessary data in the lowlevel driver.
+
+The bus instance is created via snd_hda_bus_new().  You need to pass
+the card instance, the template, and the pointer to store the
+resultant bus instance.
+
+int snd_hda_bus_new(snd_card_t *card, const struct hda_bus_template *temp,
+                   struct hda_bus **busp);
+
+It returns zero if successful.  A negative return value means any
+error during creation.
+
+
+Creation of Codec Instance
+==========================
+
+Each codec chip on the board is then created on the BUS instance.
+To create a codec instance, call snd_hda_codec_new().
+
+int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
+                     struct hda_codec **codecp);
+
+The first argument is the BUS instance, the second argument is the
+address of the codec, and the last one is the pointer to store the
+resultant codec instance (can be NULL if not needed).
+
+The codec is stored in a linked list of bus instance.  You can follow
+the codec list like:
+
+       struct list_head *p;
+       struct hda_codec *codec;
+       list_for_each(p, &bus->codec_list) {
+               codec = list_entry(p, struct hda_codec, list);
+               ...
+       }
+
+The codec isn't initialized at this stage properly.  The
+initialization sequence is called when the controls are built later.
+
+
+Codec Access
+============
+
+To access codec, use snd_codec_read() and snd_codec_write().
+snd_hda_param_read() is for reading parameters.
+For writing a sequence of verbs, use snd_hda_sequence_write().
+
+To retrieve the number of sub nodes connected to the given node, use
+snd_hda_get_sub_nodes().  The connection list can be obtained via
+snd_hda_get_connections() call.
+
+When an unsolicited event happens, pass the event via
+snd_hda_queue_unsol_event() so that the codec routines will process it
+later.
+
+
+(Mixer) Controls
+================
+
+To create mixer controls of all codecs, call
+snd_hda_build_controls().  It then builds the mixers and does
+initialization stuff on each codec.
+
+
+PCM Stuff
+=========
+
+snd_hda_build_pcms() gives the necessary information to create PCM
+streams.  When it's called, each codec belonging to the bus stores 
+codec->num_pcms and codec->pcm_info fields.  The num_pcms indicates
+the number of elements in pcm_info array.  The card driver is supposed
+to traverse the codec linked list, read the pcm information in
+pcm_info array, and build pcm instances according to them. 
+
+The pcm_info array contains the following record:
+
+/* PCM information for each substream */
+struct hda_pcm_stream {
+       unsigned int substreams;        /* number of substreams, 0 = not exist */
+       unsigned int channels_min;      /* min. number of channels */
+       unsigned int channels_max;      /* max. number of channels */
+       hda_nid_t nid;  /* default NID to query rates/formats/bps, or set up */
+       u32 rates;      /* supported rates */
+       u64 formats;    /* supported formats (SNDRV_PCM_FMTBIT_) */
+       unsigned int maxbps;    /* supported max. bit per sample */
+       struct hda_pcm_ops ops;
+};
+
+/* for PCM creation */
+struct hda_pcm {
+       char *name;
+       struct hda_pcm_stream stream[2];
+};
+
+The name can be passed to snd_pcm_new().  The stream field contains
+the information  for playback (SNDRV_PCM_STREAM_PLAYBACK = 0) and
+capture (SNDRV_PCM_STREAM_CAPTURE = 1) directions.  The card driver
+should pass substreams to snd_pcm_new() for the number of substreams
+to create.
+
+The channels_min, channels_max, rates and formats should be copied to
+runtime->hw record.  They and maxbps fields are used also to compute
+the format value for the HDA codec and controller.  Call
+snd_hda_calc_stream_format() to get the format value.
+
+The ops field contains the following callback functions:
+
+struct hda_pcm_ops {
+       int (*open)(struct hda_pcm_stream *info, struct hda_codec *codec,
+                   snd_pcm_substream_t *substream);
+       int (*close)(struct hda_pcm_stream *info, struct hda_codec *codec,
+                    snd_pcm_substream_t *substream);
+       int (*prepare)(struct hda_pcm_stream *info, struct hda_codec *codec,
+                      unsigned int stream_tag, unsigned int format,
+                      snd_pcm_substream_t *substream);
+       int (*cleanup)(struct hda_pcm_stream *info, struct hda_codec *codec,
+                      snd_pcm_substream_t *substream);
+};
+
+All are non-NULL, so you can call them safely without NULL check.
+
+The open callback should be called in PCM open after runtime->hw is
+set up.  It may override some setting and constraints additionally.
+Similarly, the close callback should be called in the PCM close.
+
+The prepare callback should be called in PCM prepare.  This will set
+up the codec chip properly for the operation.  The cleanup should be
+called in hw_free to clean up the configuration.
+
+The caller should check the return value, at least for open and
+prepare callbacks.  When a negative value is returned, some error
+occurred.
+
+
+Proc Files
+==========
+
+Each codec dumps the widget node information in
+/proc/asound/card*/codec#* file.  This information would be really
+helpful for debugging.  Please provide its contents together with the
+bug report.
+
+
+Power Management
+================
+
+It's simple:
+Call snd_hda_suspend() in the PM suspend callback.
+Call snd_hda_resume() in the PM resume callback.
+
+
+Codec Preset (Patch)
+====================
+
+To set up and handle the codec functionality fully, each codec may
+have a codec preset (patch).  It's defined in struct hda_codec_preset:
+
+       struct hda_codec_preset {
+               unsigned int id;
+               unsigned int mask;
+               unsigned int subs;
+               unsigned int subs_mask;
+               unsigned int rev;
+               const char *name;
+               int (*patch)(struct hda_codec *codec);
+       };
+
+When the codec id and codec subsystem id match with the given id and
+subs fields bitwise (with bitmask mask and subs_mask), the callback
+patch is called.  The patch callback should initialize the codec and
+set the codec->patch_ops field.  This is defined as below:
+
+       struct hda_codec_ops {
+               int (*build_controls)(struct hda_codec *codec);
+               int (*build_pcms)(struct hda_codec *codec);
+               int (*init)(struct hda_codec *codec);
+               void (*free)(struct hda_codec *codec);
+               void (*unsol_event)(struct hda_codec *codec, unsigned int res);
+       #ifdef CONFIG_PM
+               int (*suspend)(struct hda_codec *codec, pm_message_t state);
+               int (*resume)(struct hda_codec *codec);
+       #endif
+       };
+
+The build_controls callback is called from snd_hda_build_controls().
+Similarly, the build_pcms callback is called from
+snd_hda_build_pcms().  The init callback is called after
+build_controls to initialize the hardware.
+The free callback is called as a destructor.
+
+The unsol_event callback is called when an unsolicited event is
+received.
+
+The suspend and resume callbacks are for power management.
+
+Each entry can be NULL if not necessary to be called.
+
+
+Generic Parser
+==============
+
+When the device doesn't match with any given presets, the widgets are
+parsed via th generic parser (hda_generic.c).  Its support is
+limited: no multi-channel support, for example.
+
+
+Digital I/O
+===========
+
+Call snd_hda_create_spdif_out_ctls() from the patch to create controls
+related with SPDIF out.  In the patch resume callback, call
+snd_hda_resume_spdif().
+
+
+Helper Functions
+================
+
+snd_hda_get_codec_name() stores the codec name on the given string.
+
+snd_hda_check_board_config() can be used to obtain the configuration
+information matching with the device.  Define the table with struct
+hda_board_config entries (zero-terminated), and pass it to the
+function.  The function checks the modelname given as a module
+parameter, and PCI subsystem IDs.  If the matching entry is found, it
+returns the config field value.
+
+snd_hda_add_new_ctls() can be used to create and add control entries.
+Pass the zero-terminated array of snd_kcontrol_new_t.  The same array
+can be passed to snd_hda_resume_ctls() for resume.
+Note that this will call control->put callback of these entries.  So,
+put callback should check codec->in_resume and force to restore the
+given value if it's non-zero even if the value is identical with the
+cached value.
+
+Macros HDA_CODEC_VOLUME(), HDA_CODEC_MUTE() and their variables can be
+used for the entry of snd_kcontrol_new_t.
+
+The input MUX helper callbacks for such a control are provided, too:
+snd_hda_input_mux_info() and snd_hda_input_mux_put().  See
+patch_realtek.c for example.
diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig
new file mode 100644 (file)
index 0000000..692af6b
--- /dev/null
@@ -0,0 +1,24 @@
+config ICST525
+       bool
+
+config ICST307
+       bool
+
+config SA1111
+       bool
+       select DMABOUNCE
+
+config DMABOUNCE
+       bool
+
+config TIMER_ACORN
+       bool
+
+config SHARP_LOCOMO
+       bool
+
+config SHARP_PARAM
+       bool
+
+config SHARP_SCOOP
+       bool
diff --git a/arch/arm/common/sharpsl_param.c b/arch/arm/common/sharpsl_param.c
new file mode 100644 (file)
index 0000000..c2c557a
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Hardware parameter area specific to Sharp SL series devices
+ *
+ * Copyright (c) 2005 Richard Purdie
+ *
+ * Based on Sharp's 2.4 kernel patches
+ *
+ * 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
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <asm/mach/sharpsl_param.h>
+
+/*
+ * Certain hardware parameters determined at the time of device manufacture,
+ * typically including LCD parameters are loaded by the bootloader at the
+ * address PARAM_BASE. As the kernel will overwrite them, we need to store
+ * them early in the boot process, then pass them to the appropriate drivers.
+ * Not all devices use all paramaters but the format is common to all.
+ */
+#ifdef ARCH_SA1100
+#define PARAM_BASE     0xe8ffc000
+#else
+#define PARAM_BASE     0xa0000a00
+#endif
+#define MAGIC_CHG(a,b,c,d) ( ( d << 24 ) | ( c << 16 )  | ( b << 8 ) | a )
+
+#define COMADJ_MAGIC   MAGIC_CHG('C','M','A','D')
+#define UUID_MAGIC     MAGIC_CHG('U','U','I','D')
+#define TOUCH_MAGIC    MAGIC_CHG('T','U','C','H')
+#define AD_MAGIC       MAGIC_CHG('B','V','A','D')
+#define PHAD_MAGIC     MAGIC_CHG('P','H','A','D')
+
+struct sharpsl_param_info sharpsl_param;
+
+void sharpsl_save_param(void)
+{
+       memcpy(&sharpsl_param, (void *)PARAM_BASE, sizeof(struct sharpsl_param_info));
+
+       if (sharpsl_param.comadj_keyword != COMADJ_MAGIC)
+               sharpsl_param.comadj=-1;
+
+       if (sharpsl_param.phad_keyword != PHAD_MAGIC)
+               sharpsl_param.phadadj=-1;
+
+       if (sharpsl_param.uuid_keyword != UUID_MAGIC)
+               sharpsl_param.uuid[0]=-1;
+
+       if (sharpsl_param.touch_keyword != TOUCH_MAGIC)
+               sharpsl_param.touch_xp=-1;
+
+       if (sharpsl_param.adadj_keyword != AD_MAGIC)
+               sharpsl_param.adadj=-1;
+}
+
+
diff --git a/arch/arm/mm/abort-macro.S b/arch/arm/mm/abort-macro.S
new file mode 100644 (file)
index 0000000..d7cb1bf
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * The ARM LDRD and Thumb LDRSB instructions use bit 20/11 (ARM/Thumb)
+ * differently than every other instruction, so it is set to 0 (write)
+ * even though the instructions are read instructions. This means that
+ * during an abort the instructions will be treated as a write and the
+ * handler will raise a signal from unwriteable locations if they
+ * fault. We have to specifically check for these instructions
+ * from the abort handlers to treat them properly.
+ *
+ */
+
+       .macro  do_thumb_abort
+       tst     r3, #PSR_T_BIT
+       beq     not_thumb
+       ldrh    r3, [r2]                        @ Read aborted Thumb instruction
+       and     r3, r3, # 0xfe00                @ Mask opcode field
+       cmp     r3, # 0x5600                    @ Is it ldrsb?
+       orreq   r3, r3, #1 << 11                @ Set L-bit if yes
+       tst     r3, #1 << 11                    @ L = 0 -> write
+       orreq   r1, r1, #1 << 11                @ yes.
+       mov     pc, lr
+not_thumb:
+       .endm
+
+/*
+ * We check for the following insturction encoding for LDRD.
+ *
+ * [27:25] == 0
+ *   [7:4] == 1101
+ *    [20] == 0
+ */
+       .macro  do_ldrd_abort
+       tst     r3, #0x0e000000                 @ [27:25] == 0
+       bne     not_ldrd
+       and     r2, r3, #0x000000f0             @ [7:4] == 1101
+       cmp     r2, #0x000000d0
+       bne     not_ldrd
+       tst     r3, #1 << 20                    @ [20] == 0
+       moveq   pc, lr
+not_ldrd:
+       .endm
+
diff --git a/arch/frv/Kconfig.debug b/arch/frv/Kconfig.debug
new file mode 100644 (file)
index 0000000..0034b65
--- /dev/null
@@ -0,0 +1,74 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+config EARLY_PRINTK
+       bool "Early printk"
+       depends on EMBEDDED && DEBUG_KERNEL
+       default n
+       help
+         Write kernel log output directly into the VGA buffer or to a serial
+         port.
+
+         This is useful for kernel debugging when your machine crashes very
+         early before the console code is initialized. For normal operation
+         it is not recommended because it looks ugly and doesn't cooperate
+         with klogd/syslogd or the X server. You should normally N here,
+         unless you want to debug such a crash.
+
+config DEBUG_STACKOVERFLOW
+       bool "Check for stack overflows"
+       depends on DEBUG_KERNEL
+
+config DEBUG_PAGEALLOC
+       bool "Page alloc debugging"
+       depends on DEBUG_KERNEL
+       help
+         Unmap pages from the kernel linear mapping after free_pages().
+         This results in a large slowdown, but helps to find certain types
+         of memory corruptions.
+
+config GDBSTUB
+       bool "Remote GDB kernel debugging"
+       depends on DEBUG_KERNEL
+       select DEBUG_INFO
+       select FRAME_POINTER
+       help
+         If you say Y here, it will be possible to remotely debug the kernel
+         using gdb. This enlarges your kernel ELF image disk size by several
+         megabytes and requires a machine with more than 16 MB, better 32 MB
+         RAM to avoid excessive linking time. This is only useful for kernel
+         hackers. If unsure, say N.
+
+choice
+       prompt "GDB stub port"
+       default GDBSTUB_UART1
+       depends on GDBSTUB
+       help
+         Select the on-CPU port used for GDB-stub
+
+config GDBSTUB_UART0
+       bool "/dev/ttyS0"
+
+config GDBSTUB_UART1
+       bool "/dev/ttyS1"
+
+endchoice
+
+config GDBSTUB_IMMEDIATE
+       bool "Break into GDB stub immediately"
+       depends on GDBSTUB
+       help
+         If you say Y here, GDB stub will break into the program as soon as
+         possible, leaving the program counter at the beginning of
+         start_kernel() in init/main.c.
+
+config GDB_CONSOLE
+       bool "Console output to GDB"
+       depends on GDBSTUB
+       help
+         If you are using GDB for remote debugging over a serial port and
+         would like kernel messages to be formatted into GDB $O packets so
+         that GDB prints them as program output, say 'Y'.
+
+endmenu
diff --git a/arch/i386/kernel/syscall_table.S b/arch/i386/kernel/syscall_table.S
new file mode 100644 (file)
index 0000000..9e77d13
--- /dev/null
@@ -0,0 +1,299 @@
+.data
+ENTRY(sys_call_table)
+       .long sys_restart_syscall       /* 0 - old "setup()" system call, used for restarting */
+       .long sys_exit
+       .long sys_fork
+       .long sys_read
+       .long sys_write
+       .long sys_open          /* 5 */
+       .long sys_close
+       .long sys_waitpid
+       .long sys_creat
+       .long sys_link
+       .long sys_unlink        /* 10 */
+       .long sys_execve
+       .long sys_chdir
+       .long sys_time
+       .long sys_mknod
+       .long sys_chmod         /* 15 */
+       .long sys_lchown16
+       .long sys_ni_syscall    /* old break syscall holder */
+       .long sys_stat
+       .long sys_lseek
+       .long sys_getpid        /* 20 */
+       .long sys_mount
+       .long sys_oldumount
+       .long sys_setuid16
+       .long sys_getuid16
+       .long sys_stime         /* 25 */
+       .long sys_ptrace
+       .long sys_alarm
+       .long sys_fstat
+       .long sys_pause
+       .long sys_utime         /* 30 */
+       .long sys_ni_syscall    /* old stty syscall holder */
+       .long sys_ni_syscall    /* old gtty syscall holder */
+       .long sys_access
+       .long sys_nice
+       .long sys_ni_syscall    /* 35 - old ftime syscall holder */
+       .long sys_sync
+       .long sys_kill
+       .long sys_rename
+       .long sys_mkdir
+       .long sys_rmdir         /* 40 */
+       .long sys_dup
+       .long sys_pipe
+       .long sys_times
+       .long sys_ni_syscall    /* old prof syscall holder */
+       .long sys_brk           /* 45 */
+       .long sys_setgid16
+       .long sys_getgid16
+       .long sys_signal
+       .long sys_geteuid16
+       .long sys_getegid16     /* 50 */
+       .long sys_acct
+       .long sys_umount        /* recycled never used phys() */
+       .long sys_ni_syscall    /* old lock syscall holder */
+       .long sys_ioctl
+       .long sys_fcntl         /* 55 */
+       .long sys_ni_syscall    /* old mpx syscall holder */
+       .long sys_setpgid
+       .long sys_ni_syscall    /* old ulimit syscall holder */
+       .long sys_olduname
+       .long sys_umask         /* 60 */
+       .long sys_chroot
+       .long sys_ustat
+       .long sys_dup2
+       .long sys_getppid
+       .long sys_getpgrp       /* 65 */
+       .long sys_setsid
+       .long sys_sigaction
+       .long sys_sgetmask
+       .long sys_ssetmask
+       .long sys_setreuid16    /* 70 */
+       .long sys_setregid16
+       .long sys_sigsuspend
+       .long sys_sigpending
+       .long sys_sethostname
+       .long sys_setrlimit     /* 75 */
+       .long sys_old_getrlimit
+       .long sys_getrusage
+       .long sys_gettimeofday
+       .long sys_settimeofday
+       .long sys_getgroups16   /* 80 */
+       .long sys_setgroups16
+       .long old_select
+       .long sys_symlink
+       .long sys_lstat
+       .long sys_readlink      /* 85 */
+       .long sys_uselib
+       .long sys_swapon
+       .long sys_reboot
+       .long old_readdir
+       .long old_mmap          /* 90 */
+       .long sys_munmap
+       .long sys_truncate
+       .long sys_ftruncate
+       .long sys_fchmod
+       .long sys_fchown16      /* 95 */
+       .long sys_getpriority
+       .long sys_setpriority
+       .long sys_ni_syscall    /* old profil syscall holder */
+       .long sys_statfs
+       .long sys_fstatfs       /* 100 */
+       .long sys_ioperm
+       .long sys_socketcall
+       .long sys_syslog
+       .long sys_setitimer
+       .long sys_getitimer     /* 105 */
+       .long sys_newstat
+       .long sys_newlstat
+       .long sys_newfstat
+       .long sys_uname
+       .long sys_iopl          /* 110 */
+       .long sys_vhangup
+       .long sys_ni_syscall    /* old "idle" system call */
+       .long sys_vm86old
+       .long sys_wait4
+       .long sys_swapoff       /* 115 */
+       .long sys_sysinfo
+       .long sys_ipc
+       .long sys_fsync
+       .long sys_sigreturn
+       .long sys_clone         /* 120 */
+       .long sys_setdomainname
+       .long sys_newuname
+       .long sys_modify_ldt
+       .long sys_adjtimex
+       .long sys_mprotect      /* 125 */
+       .long sys_sigprocmask
+       .long sys_ni_syscall    /* old "create_module" */
+       .long sys_init_module
+       .long sys_delete_module
+       .long sys_ni_syscall    /* 130: old "get_kernel_syms" */
+       .long sys_quotactl
+       .long sys_getpgid
+       .long sys_fchdir
+       .long sys_bdflush
+       .long sys_sysfs         /* 135 */
+       .long sys_personality
+       .long sys_ni_syscall    /* reserved for afs_syscall */
+       .long sys_setfsuid16
+       .long sys_setfsgid16
+       .long sys_llseek        /* 140 */
+       .long sys_getdents
+       .long sys_select
+       .long sys_flock
+       .long sys_msync
+       .long sys_readv         /* 145 */
+       .long sys_writev
+       .long sys_getsid
+       .long sys_fdatasync
+       .long sys_sysctl
+       .long sys_mlock         /* 150 */
+       .long sys_munlock
+       .long sys_mlockall
+       .long sys_munlockall
+       .long sys_sched_setparam
+       .long sys_sched_getparam   /* 155 */
+       .long sys_sched_setscheduler
+       .long sys_sched_getscheduler
+       .long sys_sched_yield
+       .long sys_sched_get_priority_max
+       .long sys_sched_get_priority_min  /* 160 */
+       .long sys_sched_rr_get_interval
+       .long sys_nanosleep
+       .long sys_mremap
+       .long sys_setresuid16
+       .long sys_getresuid16   /* 165 */
+       .long sys_vm86
+       .long sys_ni_syscall    /* Old sys_query_module */
+       .long sys_poll
+       .long sys_nfsservctl
+       .long sys_setresgid16   /* 170 */
+       .long sys_getresgid16
+       .long sys_prctl
+       .long sys_rt_sigreturn
+       .long sys_rt_sigaction
+       .long sys_rt_sigprocmask        /* 175 */
+       .long sys_rt_sigpending
+       .long sys_rt_sigtimedwait
+       .long sys_rt_sigqueueinfo
+       .long sys_rt_sigsuspend
+       .long sys_pread64       /* 180 */
+       .long sys_pwrite64
+       .long sys_chown16
+       .long sys_getcwd
+       .long sys_capget
+       .long sys_capset        /* 185 */
+       .long sys_sigaltstack
+       .long sys_sendfile
+       .long sys_ni_syscall    /* reserved for streams1 */
+       .long sys_ni_syscall    /* reserved for streams2 */
+       .long sys_vfork         /* 190 */
+       .long sys_getrlimit
+       .long sys_mmap2
+       .long sys_truncate64
+       .long sys_ftruncate64
+       .long sys_stat64        /* 195 */
+       .long sys_lstat64
+       .long sys_fstat64
+       .long sys_lchown
+       .long sys_getuid
+       .long sys_getgid        /* 200 */
+       .long sys_geteuid
+       .long sys_getegid
+       .long sys_setreuid
+       .long sys_setregid
+       .long sys_getgroups     /* 205 */
+       .long sys_setgroups
+       .long sys_fchown
+       .long sys_setresuid
+       .long sys_getresuid
+       .long sys_setresgid     /* 210 */
+       .long sys_getresgid
+       .long sys_chown
+       .long sys_setuid
+       .long sys_setgid
+       .long sys_setfsuid      /* 215 */
+       .long sys_setfsgid
+       .long sys_pivot_root
+       .long sys_mincore
+       .long sys_madvise
+       .long sys_getdents64    /* 220 */
+       .long sys_fcntl64
+#ifdef CONFIG_TUX
+       .long __sys_tux
+#else
+# ifdef CONFIG_TUX_MODULE
+       .long sys_tux
+# else
+       .long sys_ni_syscall
+# endif
+#endif
+       .long sys_ni_syscall
+       .long sys_gettid
+       .long sys_readahead     /* 225 */
+       .long sys_setxattr
+       .long sys_lsetxattr
+       .long sys_fsetxattr
+       .long sys_getxattr
+       .long sys_lgetxattr     /* 230 */
+       .long sys_fgetxattr
+       .long sys_listxattr
+       .long sys_llistxattr
+       .long sys_flistxattr
+       .long sys_removexattr   /* 235 */
+       .long sys_lremovexattr
+       .long sys_fremovexattr
+       .long sys_tkill
+       .long sys_sendfile64
+       .long sys_futex         /* 240 */
+       .long sys_sched_setaffinity
+       .long sys_sched_getaffinity
+       .long sys_set_thread_area
+       .long sys_get_thread_area
+       .long sys_io_setup      /* 245 */
+       .long sys_io_destroy
+       .long sys_io_getevents
+       .long sys_io_submit
+       .long sys_io_cancel
+       .long sys_fadvise64     /* 250 */
+       .long sys_ni_syscall
+       .long sys_exit_group
+       .long sys_lookup_dcookie
+       .long sys_epoll_create
+       .long sys_epoll_ctl     /* 255 */
+       .long sys_epoll_wait
+       .long sys_remap_file_pages
+       .long sys_set_tid_address
+       .long sys_timer_create
+       .long sys_timer_settime         /* 260 */
+       .long sys_timer_gettime
+       .long sys_timer_getoverrun
+       .long sys_timer_delete
+       .long sys_clock_settime
+       .long sys_clock_gettime         /* 265 */
+       .long sys_clock_getres
+       .long sys_clock_nanosleep
+       .long sys_statfs64
+       .long sys_fstatfs64
+       .long sys_tgkill        /* 270 */
+       .long sys_utimes
+       .long sys_fadvise64_64
+       .long sys_ni_syscall    /* sys_vserver */
+       .long sys_mbind
+       .long sys_get_mempolicy
+       .long sys_set_mempolicy
+       .long sys_mq_open
+       .long sys_mq_unlink
+       .long sys_mq_timedsend
+       .long sys_mq_timedreceive       /* 280 */
+       .long sys_mq_notify
+       .long sys_mq_getsetattr
+       .long sys_ni_syscall            /* reserved for kexec */
+       .long sys_waitid
+       .long sys_ni_syscall            /* 285 */ /* available */
+       .long sys_add_key
+       .long sys_request_key
+       .long sys_keyctl
diff --git a/arch/i386/kernel/vsyscall-note.S b/arch/i386/kernel/vsyscall-note.S
new file mode 100644 (file)
index 0000000..d4b5be4
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * This supplies .note.* sections to go into the PT_NOTE inside the vDSO text.
+ * Here we can supply some information useful to userland.
+ */
+
+#include <linux/uts.h>
+#include <linux/version.h>
+
+#define ASM_ELF_NOTE_BEGIN(name, flags, vendor, type)                        \
+       .section name, flags;                                                 \
+       .balign 4;                                                            \
+       .long 1f - 0f;          /* name length */                             \
+       .long 3f - 2f;          /* data length */                             \
+       .long type;             /* note type */                               \
+0:     .asciz vendor;          /* vendor name */                             \
+1:     .balign 4;                                                            \
+2:
+
+#define ASM_ELF_NOTE_END                                                     \
+3:     .balign 4;              /* pad out section */                         \
+       .previous
+
+       ASM_ELF_NOTE_BEGIN(".note.kernel-version", "a", UTS_SYSNAME, 0)
+       .long LINUX_VERSION_CODE
+       ASM_ELF_NOTE_END
diff --git a/arch/i386/lib/putuser.S b/arch/i386/lib/putuser.S
new file mode 100644 (file)
index 0000000..a32d9f5
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * __put_user functions.
+ *
+ * (C) Copyright 2005 Linus Torvalds
+ *
+ * These functions have a non-standard call interface
+ * to make them more efficient, especially as they
+ * return an error value in addition to the "real"
+ * return value.
+ */
+#include <asm/thread_info.h>
+
+
+/*
+ * __put_user_X
+ *
+ * Inputs:     %eax[:%edx] contains the data
+ *             %ecx contains the address
+ *
+ * Outputs:    %eax is error code (0 or -EFAULT)
+ *
+ * These functions should not modify any other registers,
+ * as they get called from within inline assembly.
+ */
+
+#define ENTER  pushl %ebx ; GET_THREAD_INFO(%ebx)
+#define EXIT   popl %ebx ; ret
+
+.text
+.align 4
+.globl __put_user_1
+__put_user_1:
+       ENTER
+       cmpl TI_addr_limit(%ebx),%ecx
+       jae bad_put_user
+1:     movb %al,(%ecx)
+       xorl %eax,%eax
+       EXIT
+
+.align 4
+.globl __put_user_2
+__put_user_2:
+       ENTER
+       movl TI_addr_limit(%ebx),%ebx
+       subl $1,%ebx
+       cmpl %ebx,%ecx
+       jae bad_put_user
+2:     movw %ax,(%ecx)
+       xorl %eax,%eax
+       EXIT
+
+.align 4
+.globl __put_user_4
+__put_user_4:
+       ENTER
+       movl TI_addr_limit(%ebx),%ebx
+       subl $3,%ebx
+       cmpl %ebx,%ecx
+       jae bad_put_user
+3:     movl %eax,(%ecx)
+       xorl %eax,%eax
+       EXIT
+
+.align 4
+.globl __put_user_8
+__put_user_8:
+       ENTER
+       movl TI_addr_limit(%ebx),%ebx
+       subl $7,%ebx
+       cmpl %ebx,%ecx
+       jae bad_put_user
+4:     movl %eax,(%ecx)
+5:     movl %edx,4(%ecx)
+       xorl %eax,%eax
+       EXIT
+
+bad_put_user:
+       movl $-14,%eax
+       EXIT
+
+.section __ex_table,"a"
+       .long 1b,bad_put_user
+       .long 2b,bad_put_user
+       .long 3b,bad_put_user
+       .long 4b,bad_put_user
+       .long 5b,bad_put_user
+.previous
diff --git a/arch/ia64/sn/kernel/xp_main.c b/arch/ia64/sn/kernel/xp_main.c
new file mode 100644 (file)
index 0000000..3be52a3
--- /dev/null
@@ -0,0 +1,289 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 2004-2005 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+
+/*
+ * Cross Partition (XP) base.
+ *
+ *     XP provides a base from which its users can interact
+ *     with XPC, yet not be dependent on XPC.
+ *
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <asm/sn/intr.h>
+#include <asm/sn/sn_sal.h>
+#include <asm/sn/xp.h>
+
+
+/*
+ * Target of nofault PIO read.
+ */
+u64 xp_nofault_PIOR_target;
+
+
+/*
+ * xpc_registrations[] keeps track of xpc_connect()'s done by the kernel-level
+ * users of XPC.
+ */
+struct xpc_registration xpc_registrations[XPC_NCHANNELS];
+
+
+/*
+ * Initialize the XPC interface to indicate that XPC isn't loaded.
+ */
+static enum xpc_retval xpc_notloaded(void) { return xpcNotLoaded; }
+
+struct xpc_interface xpc_interface = {
+       (void (*)(int)) xpc_notloaded,
+       (void (*)(int)) xpc_notloaded,
+       (enum xpc_retval (*)(partid_t, int, u32, void **)) xpc_notloaded,
+       (enum xpc_retval (*)(partid_t, int, void *)) xpc_notloaded,
+       (enum xpc_retval (*)(partid_t, int, void *, xpc_notify_func, void *))
+                                                       xpc_notloaded,
+       (void (*)(partid_t, int, void *)) xpc_notloaded,
+       (enum xpc_retval (*)(partid_t, void *)) xpc_notloaded
+};
+
+
+/*
+ * XPC calls this when it (the XPC module) has been loaded.
+ */
+void
+xpc_set_interface(void (*connect)(int),
+               void (*disconnect)(int),
+               enum xpc_retval (*allocate)(partid_t, int, u32, void **),
+               enum xpc_retval (*send)(partid_t, int, void *),
+               enum xpc_retval (*send_notify)(partid_t, int, void *,
+                                               xpc_notify_func, void *),
+               void (*received)(partid_t, int, void *),
+               enum xpc_retval (*partid_to_nasids)(partid_t, void *))
+{
+       xpc_interface.connect = connect;
+       xpc_interface.disconnect = disconnect;
+       xpc_interface.allocate = allocate;
+       xpc_interface.send = send;
+       xpc_interface.send_notify = send_notify;
+       xpc_interface.received = received;
+       xpc_interface.partid_to_nasids = partid_to_nasids;
+}
+
+
+/*
+ * XPC calls this when it (the XPC module) is being unloaded.
+ */
+void
+xpc_clear_interface(void)
+{
+       xpc_interface.connect = (void (*)(int)) xpc_notloaded;
+       xpc_interface.disconnect = (void (*)(int)) xpc_notloaded;
+       xpc_interface.allocate = (enum xpc_retval (*)(partid_t, int, u32,
+                                       void **)) xpc_notloaded;
+       xpc_interface.send = (enum xpc_retval (*)(partid_t, int, void *))
+                                       xpc_notloaded;
+       xpc_interface.send_notify = (enum xpc_retval (*)(partid_t, int, void *,
+                                   xpc_notify_func, void *)) xpc_notloaded;
+       xpc_interface.received = (void (*)(partid_t, int, void *))
+                                       xpc_notloaded;
+       xpc_interface.partid_to_nasids = (enum xpc_retval (*)(partid_t, void *))
+                                       xpc_notloaded;
+}
+
+
+/*
+ * Register for automatic establishment of a channel connection whenever
+ * a partition comes up.
+ *
+ * Arguments:
+ *
+ *     ch_number - channel # to register for connection.
+ *     func - function to call for asynchronous notification of channel
+ *            state changes (i.e., connection, disconnection, error) and
+ *            the arrival of incoming messages.
+ *      key - pointer to optional user-defined value that gets passed back
+ *           to the user on any callouts made to func.
+ *     payload_size - size in bytes of the XPC message's payload area which
+ *                    contains a user-defined message. The user should make
+ *                    this large enough to hold their largest message.
+ *     nentries - max #of XPC message entries a message queue can contain.
+ *                The actual number, which is determined when a connection
+ *                is established and may be less then requested, will be
+ *                passed to the user via the xpcConnected callout.
+ *     assigned_limit - max number of kthreads allowed to be processing
+ *                      messages (per connection) at any given instant.
+ *     idle_limit - max number of kthreads allowed to be idle at any given
+ *                  instant.
+ */
+enum xpc_retval
+xpc_connect(int ch_number, xpc_channel_func func, void *key, u16 payload_size,
+               u16 nentries, u32 assigned_limit, u32 idle_limit)
+{
+       struct xpc_registration *registration;
+
+
+       DBUG_ON(ch_number < 0 || ch_number >= XPC_NCHANNELS);
+       DBUG_ON(payload_size == 0 || nentries == 0);
+       DBUG_ON(func == NULL);
+       DBUG_ON(assigned_limit == 0 || idle_limit > assigned_limit);
+
+       registration = &xpc_registrations[ch_number];
+
+       if (down_interruptible(&registration->sema) != 0) {
+               return xpcInterrupted;
+       }
+
+       /* if XPC_CHANNEL_REGISTERED(ch_number) */
+       if (registration->func != NULL) {
+               up(&registration->sema);
+               return xpcAlreadyRegistered;
+       }
+
+       /* register the channel for connection */
+       registration->msg_size = XPC_MSG_SIZE(payload_size);
+       registration->nentries = nentries;
+       registration->assigned_limit = assigned_limit;
+       registration->idle_limit = idle_limit;
+       registration->key = key;
+       registration->func = func;
+
+       up(&registration->sema);
+
+       xpc_interface.connect(ch_number);
+
+       return xpcSuccess;
+}
+
+
+/*
+ * Remove the registration for automatic connection of the specified channel
+ * when a partition comes up.
+ *
+ * Before returning this xpc_disconnect() will wait for all connections on the
+ * specified channel have been closed/torndown. So the caller can be assured
+ * that they will not be receiving any more callouts from XPC to their
+ * function registered via xpc_connect().
+ *
+ * Arguments:
+ *
+ *     ch_number - channel # to unregister.
+ */
+void
+xpc_disconnect(int ch_number)
+{
+       struct xpc_registration *registration;
+
+
+       DBUG_ON(ch_number < 0 || ch_number >= XPC_NCHANNELS);
+
+       registration = &xpc_registrations[ch_number];
+
+       /*
+        * We've decided not to make this a down_interruptible(), since we
+        * figured XPC's users will just turn around and call xpc_disconnect()
+        * again anyways, so we might as well wait, if need be.
+        */
+       down(&registration->sema);
+
+       /* if !XPC_CHANNEL_REGISTERED(ch_number) */
+       if (registration->func == NULL) {
+               up(&registration->sema);
+               return;
+       }
+
+       /* remove the connection registration for the specified channel */
+       registration->func = NULL;
+       registration->key = NULL;
+       registration->nentries = 0;
+       registration->msg_size = 0;
+       registration->assigned_limit = 0;
+       registration->idle_limit = 0;
+
+       xpc_interface.disconnect(ch_number);
+
+       up(&registration->sema);
+
+       return;
+}
+
+
+int __init
+xp_init(void)
+{
+       int ret, ch_number;
+       u64 func_addr = *(u64 *) xp_nofault_PIOR;
+       u64 err_func_addr = *(u64 *) xp_error_PIOR;
+
+
+       if (!ia64_platform_is("sn2")) {
+               return -ENODEV;
+       }
+
+       /*
+        * Register a nofault code region which performs a cross-partition
+        * PIO read. If the PIO read times out, the MCA handler will consume
+        * the error and return to a kernel-provided instruction to indicate
+        * an error. This PIO read exists because it is guaranteed to timeout
+        * if the destination is down (AMO operations do not timeout on at
+        * least some CPUs on Shubs <= v1.2, which unfortunately we have to
+        * work around).
+        */
+       if ((ret = sn_register_nofault_code(func_addr, err_func_addr,
+                                               err_func_addr, 1, 1)) != 0) {
+               printk(KERN_ERR "XP: can't register nofault code, error=%d\n",
+                       ret);
+       }
+       /*
+        * Setup the nofault PIO read target. (There is no special reason why
+        * SH_IPI_ACCESS was selected.)
+        */
+       if (is_shub2()) {
+               xp_nofault_PIOR_target = SH2_IPI_ACCESS0;
+       } else {
+               xp_nofault_PIOR_target = SH1_IPI_ACCESS;
+       }
+
+       /* initialize the connection registration semaphores */
+       for (ch_number = 0; ch_number < XPC_NCHANNELS; ch_number++) {
+               sema_init(&xpc_registrations[ch_number].sema, 1);  /* mutex */
+       }
+
+       return 0;
+}
+module_init(xp_init);
+
+
+void __exit
+xp_exit(void)
+{
+       u64 func_addr = *(u64 *) xp_nofault_PIOR;
+       u64 err_func_addr = *(u64 *) xp_error_PIOR;
+
+
+       /* unregister the PIO read nofault code region */
+       (void) sn_register_nofault_code(func_addr, err_func_addr,
+                                       err_func_addr, 1, 0);
+}
+module_exit(xp_exit);
+
+
+MODULE_AUTHOR("Silicon Graphics, Inc.");
+MODULE_DESCRIPTION("Cross Partition (XP) base");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(xp_nofault_PIOR);
+EXPORT_SYMBOL(xp_nofault_PIOR_target);
+EXPORT_SYMBOL(xpc_registrations);
+EXPORT_SYMBOL(xpc_interface);
+EXPORT_SYMBOL(xpc_clear_interface);
+EXPORT_SYMBOL(xpc_set_interface);
+EXPORT_SYMBOL(xpc_connect);
+EXPORT_SYMBOL(xpc_disconnect);
+
diff --git a/arch/ia64/sn/kernel/xp_nofault.S b/arch/ia64/sn/kernel/xp_nofault.S
new file mode 100644 (file)
index 0000000..b772543
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 2004-2005 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+
+/*
+ * The xp_nofault_PIOR function takes a pointer to a remote PIO register
+ * and attempts to load and consume a value from it.  This function
+ * will be registered as a nofault code block.  In the event that the
+ * PIO read fails, the MCA handler will force the error to look
+ * corrected and vector to the xp_error_PIOR which will return an error.
+ *
+ *     extern int xp_nofault_PIOR(void *remote_register);
+ */
+
+       .global xp_nofault_PIOR
+xp_nofault_PIOR:
+       mov     r8=r0                   // Stage a success return value
+       ld8.acq r9=[r32];;              // PIO Read the specified register
+       adds    r9=1,r9                 // Add to force a consume
+       br.ret.sptk.many b0;;           // Return success
+
+       .global xp_error_PIOR
+xp_error_PIOR:
+       mov     r8=1                    // Return value of 1
+       br.ret.sptk.many b0;;           // Return failure
+
diff --git a/arch/ppc/configs/hdpu_defconfig b/arch/ppc/configs/hdpu_defconfig
new file mode 100644 (file)
index 0000000..956a178
--- /dev/null
@@ -0,0 +1,890 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11
+# Wed Mar 16 12:43:19 2005
+#
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_LOCK_KERNEL=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+# CONFIG_CPUSETS is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Processor
+#
+CONFIG_6xx=y
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_E500 is not set
+CONFIG_ALTIVEC=y
+# CONFIG_TAU is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_PM is not set
+CONFIG_PPC_STD_MMU=y
+# CONFIG_NOT_COHERENT_CACHE is not set
+
+#
+# Platform options
+#
+# CONFIG_PPC_MULTIPLATFORM is not set
+# CONFIG_APUS is not set
+# CONFIG_KATANA is not set
+# CONFIG_WILLOW is not set
+# CONFIG_CPCI690 is not set
+# CONFIG_PCORE is not set
+# CONFIG_POWERPMC250 is not set
+# CONFIG_CHESTNUT is not set
+# CONFIG_SPRUCE is not set
+CONFIG_HDPU=y
+# CONFIG_EV64260 is not set
+# CONFIG_LOPEC is not set
+# CONFIG_MCPN765 is not set
+# CONFIG_MVME5100 is not set
+# CONFIG_PPLUS is not set
+# CONFIG_PRPMC750 is not set
+# CONFIG_PRPMC800 is not set
+# CONFIG_SANDPOINT is not set
+# CONFIG_RADSTONE_PPC7D is not set
+# CONFIG_ADIR is not set
+# CONFIG_K2 is not set
+# CONFIG_PAL4 is not set
+# CONFIG_GEMINI is not set
+# CONFIG_EST8260 is not set
+# CONFIG_SBC82xx is not set
+# CONFIG_SBS8260 is not set
+# CONFIG_RPX8260 is not set
+# CONFIG_TQM8260 is not set
+# CONFIG_ADS8272 is not set
+# CONFIG_PQ2FADS is not set
+# CONFIG_LITE5200 is not set
+# CONFIG_MPC834x_SYS is not set
+CONFIG_MV64360=y
+CONFIG_MV64X60=y
+
+#
+# Set bridge options
+#
+CONFIG_MV64X60_BASE=0xf1000000
+CONFIG_MV64X60_NEW_BASE=0xf1000000
+# CONFIG_SMP is not set
+# CONFIG_IRQ_ALL_CPUS is not set
+# CONFIG_NR_CPUS is not set
+CONFIG_PREEMPT=y
+CONFIG_HIGHMEM=y
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="root=/dev/nfs ip=auto"
+
+#
+# Bus options
+#
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Advanced setup
+#
+CONFIG_ADVANCED_OPTIONS=y
+# CONFIG_HIGHMEM_START_BOOL is not set
+CONFIG_HIGHMEM_START=0xfe000000
+# CONFIG_LOWMEM_SIZE_BOOL is not set
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START_BOOL=y
+CONFIG_KERNEL_START=0x80000000
+# CONFIG_TASK_SIZE_BOOL is not set
+CONFIG_TASK_SIZE=0x80000000
+# CONFIG_BOOT_LOAD_BOOL is not set
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+# CONFIG_MTD_BLOCK is not set
+# CONFIG_MTD_BLOCK_RO is not set
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0xfc000000
+CONFIG_MTD_PHYSMAP_LEN=0x04000000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=4
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD 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_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=y
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+CONFIG_SCSI_AIC7XXX=y
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=32
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_AIC7XXX_DEBUG_MASK=0
+# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_IP_TCPDIAG is not set
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+CONFIG_MV643XX_ETH=y
+CONFIG_MV643XX_ETH_0=y
+# CONFIG_MV643XX_ETH_1 is not set
+# CONFIG_MV643XX_ETH_2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_MPSC=y
+CONFIG_SERIAL_MPSC_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+CONFIG_UDF_FS=y
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=15
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/arch/ppc/configs/mpc834x_sys_defconfig b/arch/ppc/configs/mpc834x_sys_defconfig
new file mode 100644 (file)
index 0000000..4a5522c
--- /dev/null
@@ -0,0 +1,644 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc4
+# Thu Feb 17 16:12:23 2005
+#
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Processor
+#
+CONFIG_6xx=y
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_E500 is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_PPC_GEN550=y
+CONFIG_83xx=y
+
+#
+# Freescale 83xx options
+#
+CONFIG_MPC834x_SYS=y
+CONFIG_MPC834x=y
+CONFIG_PPC_STD_MMU=y
+
+#
+# Platform options
+#
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Bus options
+#
+CONFIG_GENERIC_ISA_DMA=y
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=32768
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+
+#
+# Ethernet (1000 Mbit)
+#
+CONFIG_GIANFAR=y
+# CONFIG_GFAR_NAPI is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ISA is not set
+CONFIG_I2C_MPC=y
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/arch/ppc/configs/radstone_ppc7d_defconfig b/arch/ppc/configs/radstone_ppc7d_defconfig
new file mode 100644 (file)
index 0000000..7f6467e
--- /dev/null
@@ -0,0 +1,956 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11
+# Tue Mar 15 14:31:19 2005
+#
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Processor
+#
+CONFIG_6xx=y
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_E500 is not set
+CONFIG_ALTIVEC=y
+# CONFIG_TAU is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_PPC_GEN550=y
+# CONFIG_PM is not set
+CONFIG_PPC_STD_MMU=y
+# CONFIG_NOT_COHERENT_CACHE is not set
+
+#
+# Platform options
+#
+# CONFIG_PPC_MULTIPLATFORM is not set
+# CONFIG_APUS is not set
+# CONFIG_KATANA is not set
+# CONFIG_WILLOW is not set
+# CONFIG_CPCI690 is not set
+# CONFIG_PCORE is not set
+# CONFIG_POWERPMC250 is not set
+# CONFIG_CHESTNUT is not set
+# CONFIG_SPRUCE is not set
+# CONFIG_EV64260 is not set
+# CONFIG_LOPEC is not set
+# CONFIG_MCPN765 is not set
+# CONFIG_MVME5100 is not set
+# CONFIG_PPLUS is not set
+# CONFIG_PRPMC750 is not set
+# CONFIG_PRPMC800 is not set
+# CONFIG_SANDPOINT is not set
+CONFIG_RADSTONE_PPC7D=y
+# CONFIG_ADIR is not set
+# CONFIG_K2 is not set
+# CONFIG_PAL4 is not set
+# CONFIG_GEMINI is not set
+# CONFIG_EST8260 is not set
+# CONFIG_SBC82xx is not set
+# CONFIG_SBS8260 is not set
+# CONFIG_RPX8260 is not set
+# CONFIG_TQM8260 is not set
+# CONFIG_ADS8272 is not set
+# CONFIG_PQ2FADS is not set
+# CONFIG_LITE5200 is not set
+# CONFIG_MPC834x_SYS is not set
+CONFIG_MV64360=y
+CONFIG_MV64X60=y
+
+#
+# Set bridge options
+#
+CONFIG_MV64X60_BASE=0xfef00000
+CONFIG_MV64X60_NEW_BASE=0xfef00000
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttyS0,9600"
+
+#
+# Bus options
+#
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Advanced setup
+#
+CONFIG_ADVANCED_OPTIONS=y
+CONFIG_HIGHMEM_START=0xfe000000
+# CONFIG_LOWMEM_SIZE_BOOL is not set
+CONFIG_LOWMEM_SIZE=0x30000000
+# CONFIG_KERNEL_START_BOOL is not set
+CONFIG_KERNEL_START=0xc0000000
+# CONFIG_TASK_SIZE_BOOL is not set
+CONFIG_TASK_SIZE=0x80000000
+# CONFIG_BOOT_LOAD_BOOL is not set
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+# CONFIG_MTD_PARTITIONS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_FTL=y
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_GEOMETRY is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_XIP is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD 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_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=y
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=y
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+CONFIG_BRIDGE=y
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+# CONFIG_DE2104X is not set
+CONFIG_TULIP=y
+# CONFIG_TULIP_MWI is not set
+# CONFIG_TULIP_MMIO is not set
+# CONFIG_TULIP_NAPI is not set
+# CONFIG_DE4X5 is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_DM9102 is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=y
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+CONFIG_R8169=y
+CONFIG_R8169_NAPI=y
+CONFIG_SK98LIN=y
+# CONFIG_VIA_VELOCITY is not set
+CONFIG_TIGON3=y
+CONFIG_MV643XX_ETH=y
+CONFIG_MV643XX_ETH_0=y
+CONFIG_MV643XX_ETH_1=y
+# CONFIG_MV643XX_ETH_2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+CONFIG_KEYBOARD_XTKBD=y
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
+# Character devices
+#
+CONFIG_VT=y
+# CONFIG_VT_CONSOLE is not set
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_MPSC=y
+# CONFIG_SERIAL_MPSC_CONSOLE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_ISA is not set
+# CONFIG_I2C_MPC is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+CONFIG_I2C_MV64XXX=y
+
+#
+# Hardware Sensors Chip support
+#
+CONFIG_I2C_SENSOR=y
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+CONFIG_SENSORS_LM90=y
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_M41T00 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=y
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/arch/ppc/platforms/83xx/Makefile b/arch/ppc/platforms/83xx/Makefile
new file mode 100644 (file)
index 0000000..eb55341
--- /dev/null
@@ -0,0 +1,4 @@
+#
+# Makefile for the PowerPC 83xx linux kernel.
+#
+obj-$(CONFIG_MPC834x_SYS)      += mpc834x_sys.o
diff --git a/arch/ppc/syslib/m82xx_pci.h b/arch/ppc/syslib/m82xx_pci.h
new file mode 100644 (file)
index 0000000..924f73f
--- /dev/null
@@ -0,0 +1,92 @@
+
+#ifndef _PPC_KERNEL_M82XX_PCI_H
+#define _PPC_KERNEL_M82XX_PCI_H
+
+#include <asm/m8260_pci.h>
+/*
+ *   Local->PCI map (from CPU)                             controlled by
+ *   MPC826x master window
+ *
+ *   0xF6000000 - 0xF7FFFFFF    IO space
+ *   0x80000000 - 0xBFFFFFFF    CPU2PCI memory space       PCIBR0
+ *
+ *   0x80000000 - 0x9FFFFFFF    PCI Mem with prefetch      (Outbound ATU #1)
+ *   0xA0000000 - 0xBFFFFFFF    PCI Mem w/o  prefetch      (Outbound ATU #2)
+ *   0xF6000000 - 0xF7FFFFFF    32-bit PCI IO              (Outbound ATU #3)
+ *
+ *   PCI->Local map (from PCI)
+ *   MPC826x slave window                                  controlled by
+ *
+ *   0x00000000 - 0x07FFFFFF    MPC826x local memory       (Inbound ATU #1)
+ */
+
+/*
+ * Slave window that allows PCI masters to access MPC826x local memory.
+ * This window is set up using the first set of Inbound ATU registers
+ */
+
+#ifndef M82xx_PCI_SLAVE_MEM_LOCAL
+#define M82xx_PCI_SLAVE_MEM_LOCAL      (((struct bd_info *)__res)->bi_memstart)
+#define M82xx_PCI_SLAVE_MEM_BUS                (((struct bd_info *)__res)->bi_memstart)
+#define M82xx_PCI_SLAVE_MEM_SIZE       (((struct bd_info *)__res)->bi_memsize)
+#endif
+
+/*
+ * This is the window that allows the CPU to access PCI address space.
+ * It will be setup with the SIU PCIBR0 register. All three PCI master
+ * windows, which allow the CPU to access PCI prefetch, non prefetch,
+ * and IO space (see below), must all fit within this window.
+ */
+
+#ifndef M82xx_PCI_LOWER_MEM
+#define M82xx_PCI_LOWER_MEM            0x80000000
+#define M82xx_PCI_UPPER_MEM            0x9fffffff
+#define M82xx_PCI_MEM_OFFSET           0x00000000
+#define M82xx_PCI_MEM_SIZE             0x20000000
+#endif
+
+#ifndef M82xx_PCI_LOWER_MMIO
+#define M82xx_PCI_LOWER_MMIO           0xa0000000
+#define M82xx_PCI_UPPER_MMIO           0xafffffff
+#define M82xx_PCI_MMIO_OFFSET          0x00000000
+#define M82xx_PCI_MMIO_SIZE            0x20000000
+#endif
+
+#ifndef M82xx_PCI_LOWER_IO
+#define M82xx_PCI_LOWER_IO             0x00000000
+#define M82xx_PCI_UPPER_IO             0x01ffffff
+#define M82xx_PCI_IO_BASE              0xf6000000
+#define M82xx_PCI_IO_SIZE              0x02000000
+#endif
+
+#ifndef M82xx_PCI_PRIM_WND_SIZE
+#define M82xx_PCI_PRIM_WND_SIZE        ~(M82xx_PCI_IO_SIZE - 1U)
+#define M82xx_PCI_PRIM_WND_BASE                (M82xx_PCI_IO_BASE)
+#endif
+
+#ifndef M82xx_PCI_SEC_WND_SIZE
+#define M82xx_PCI_SEC_WND_SIZE                 ~(M82xx_PCI_MEM_SIZE + M82xx_PCI_MMIO_SIZE - 1U)
+#define M82xx_PCI_SEC_WND_BASE                 (M82xx_PCI_LOWER_MEM)
+#endif
+
+#ifndef POTA_ADDR_SHIFT
+#define POTA_ADDR_SHIFT                12
+#endif
+
+#ifndef PITA_ADDR_SHIFT
+#define PITA_ADDR_SHIFT                12
+#endif
+
+#ifndef _IO_BASE
+#define _IO_BASE isa_io_base
+#endif
+
+#ifdef CONFIG_8260_PCI9
+struct pci_controller;
+extern void setup_m8260_indirect_pci(struct pci_controller* hose,
+                                       u32 cfg_addr, u32 cfg_data);
+#else
+#define setup_m8260_indirect_pci setup_indirect_pci
+#endif
+
+#endif /* _PPC_KERNEL_M8260_PCI_H */
diff --git a/arch/sh64/kernel/module.c b/arch/sh64/kernel/module.c
new file mode 100644 (file)
index 0000000..2598f6b
--- /dev/null
@@ -0,0 +1,161 @@
+/*  Kernel module help for sh64.
+
+    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
+
+    Copyright 2004 SuperH (UK) Ltd
+    Author: Richard Curnow
+
+    Based on the sh version, and on code from the sh64-specific parts of
+    modutils, originally written by Richard Curnow and Ben Gaster.
+
+*/
+#include <linux/moduleloader.h>
+#include <linux/elf.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(fmt...)
+#endif
+
+void *module_alloc(unsigned long size)
+{
+       if (size == 0)
+               return NULL;
+       return vmalloc(size);
+}
+
+
+/* Free memory returned from module_alloc */
+void module_free(struct module *mod, void *module_region)
+{
+       vfree(module_region);
+       /* FIXME: If module_region == mod->init_region, trim exception
+           table entries. */
+}
+
+/* We don't need anything special. */
+int module_frob_arch_sections(Elf_Ehdr *hdr,
+                             Elf_Shdr *sechdrs,
+                             char *secstrings,
+                             struct module *mod)
+{
+       return 0;
+}
+
+int apply_relocate_add(Elf32_Shdr *sechdrs,
+                  const char *strtab,
+                  unsigned int symindex,
+                  unsigned int relsec,
+                  struct module *me)
+{
+       unsigned int i;
+       Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
+       Elf32_Sym *sym;
+       Elf32_Addr relocation;
+       uint32_t *location;
+       int align;
+       int is_shmedia;
+
+       DEBUGP("Applying relocate section %u to %u\n", relsec,
+              sechdrs[relsec].sh_info);
+       for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+               /* This is where to make the change */
+               location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+                       + rel[i].r_offset;
+               /* This is the symbol it is referring to.  Note that all
+                  undefined symbols have been resolved.  */
+               sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
+                       + ELF32_R_SYM(rel[i].r_info);
+               relocation = sym->st_value + rel[i].r_addend;
+               align = (int)location & 3;
+
+               /* For text addresses, bit2 of the st_other field indicates
+                * whether the symbol is SHmedia (1) or SHcompact (0).  If
+                * SHmedia, the LSB of the symbol needs to be asserted
+                * for the CPU to be in SHmedia mode when it starts executing
+                * the branch target. */
+               is_shmedia = (sym->st_other & 4) ? 1 : 0;
+               if (is_shmedia) {
+                       relocation |= 1;
+               }
+
+               switch (ELF32_R_TYPE(rel[i].r_info)) {
+               case R_SH_DIR32:
+                       DEBUGP("R_SH_DIR32 @%08lx = %08lx\n", (unsigned long) location, (unsigned long) relocation);
+                       *location += relocation;
+                       break;
+               case R_SH_REL32:
+                       DEBUGP("R_SH_REL32 @%08lx = %08lx\n", (unsigned long) location, (unsigned long) relocation);
+                       relocation -= (Elf32_Addr) location;
+                       *location += relocation;
+                       break;
+               case R_SH_IMM_LOW16:
+                       DEBUGP("R_SH_IMM_LOW16 @%08lx = %08lx\n", (unsigned long) location, (unsigned long) relocation);
+                       *location = (*location & ~0x3fffc00) |
+                               ((relocation & 0xffff) << 10);
+                       break;
+               case R_SH_IMM_MEDLOW16:
+                       DEBUGP("R_SH_IMM_MEDLOW16 @%08lx = %08lx\n", (unsigned long) location, (unsigned long) relocation);
+                       *location = (*location & ~0x3fffc00) |
+                               (((relocation >> 16) & 0xffff) << 10);
+                       break;
+               case R_SH_IMM_LOW16_PCREL:
+                       DEBUGP("R_SH_IMM_LOW16_PCREL @%08lx = %08lx\n", (unsigned long) location, (unsigned long) relocation);
+                       relocation -= (Elf32_Addr) location;
+                       *location = (*location & ~0x3fffc00) |
+                               ((relocation & 0xffff) << 10);
+                       break;
+               case R_SH_IMM_MEDLOW16_PCREL:
+                       DEBUGP("R_SH_IMM_MEDLOW16_PCREL @%08lx = %08lx\n", (unsigned long) location, (unsigned long) relocation);
+                       relocation -= (Elf32_Addr) location;
+                       *location = (*location & ~0x3fffc00) |
+                               (((relocation >> 16) & 0xffff) << 10);
+                       break;
+               default:
+                       printk(KERN_ERR "module %s: Unknown relocation: %u\n",
+                              me->name, ELF32_R_TYPE(rel[i].r_info));
+                       return -ENOEXEC;
+               }
+       }
+       return 0;
+}
+
+int apply_relocate(Elf32_Shdr *sechdrs,
+                      const char *strtab,
+                      unsigned int symindex,
+                      unsigned int relsec,
+                      struct module *me)
+{
+       printk(KERN_ERR "module %s: REL RELOCATION unsupported\n",
+              me->name);
+       return -ENOEXEC;
+}
+
+int module_finalize(const Elf_Ehdr *hdr,
+                   const Elf_Shdr *sechdrs,
+                   struct module *me)
+{
+       return 0;
+}
+
+void module_arch_cleanup(struct module *mod)
+{
+}
+
diff --git a/arch/sparc64/lib/csum_copy.S b/arch/sparc64/lib/csum_copy.S
new file mode 100644 (file)
index 0000000..71af488
--- /dev/null
@@ -0,0 +1,308 @@
+/* csum_copy.S: Checksum+copy code for sparc64
+ *
+ * Copyright (C) 2005 David S. Miller <davem@davemloft.net>
+ */
+
+#ifdef __KERNEL__
+#define GLOBAL_SPARE   %g7
+#else
+#define GLOBAL_SPARE   %g5
+#endif
+
+#ifndef EX_LD
+#define EX_LD(x)       x
+#endif
+
+#ifndef EX_ST
+#define EX_ST(x)       x
+#endif
+
+#ifndef EX_RETVAL
+#define EX_RETVAL(x)   x
+#endif
+
+#ifndef LOAD
+#define LOAD(type,addr,dest)   type [addr], dest
+#endif
+
+#ifndef STORE
+#define STORE(type,src,addr)   type src, [addr]
+#endif
+
+#ifndef FUNC_NAME
+#define FUNC_NAME      csum_partial_copy_nocheck
+#endif
+
+       .register       %g2, #scratch
+       .register       %g3, #scratch
+
+       .text
+
+90:
+       /* We checked for zero length already, so there must be
+        * at least one byte.
+        */
+       be,pt           %icc, 1f
+        nop
+       EX_LD(LOAD(ldub, %o0 + 0x00, %o4))
+       add             %o0, 1, %o0
+       sub             %o2, 1, %o2
+       EX_ST(STORE(stb, %o4, %o1 + 0x00))
+       add             %o1, 1, %o1
+1:     andcc           %o0, 0x2, %g0
+       be,pn           %icc, 80f
+        cmp            %o2, 2
+       blu,pn          %icc, 60f
+        nop
+       EX_LD(LOAD(lduh, %o0 + 0x00, %o5))
+       add             %o0, 2, %o0
+       sub             %o2, 2, %o2
+       EX_ST(STORE(sth, %o5, %o1 + 0x00))
+       add             %o1, 2, %o1
+       ba,pt           %xcc, 80f
+        add            %o5, %o4, %o4
+
+       .globl          FUNC_NAME
+FUNC_NAME:             /* %o0=src, %o1=dst, %o2=len, %o3=sum */
+       LOAD(prefetch, %o0 + 0x000, #n_reads)
+       xor             %o0, %o1, %g1
+       clr             %o4
+       andcc           %g1, 0x3, %g0
+       bne,pn          %icc, 95f
+        LOAD(prefetch, %o0 + 0x040, #n_reads)
+       
+       brz,pn          %o2, 70f
+        andcc          %o0, 0x3, %g0
+
+       /* We "remember" whether the lowest bit in the address
+        * was set in GLOBAL_SPARE.  Because if it is, we have to swap
+        * upper and lower 8 bit fields of the sum we calculate.
+       */
+       bne,pn          %icc, 90b
+        andcc          %o0, 0x1, GLOBAL_SPARE
+
+80:
+       LOAD(prefetch, %o0 + 0x080, #n_reads)
+       andncc          %o2, 0x3f, %g3
+
+       LOAD(prefetch, %o0 + 0x0c0, #n_reads)
+       sub             %o2, %g3, %o2
+       brz,pn          %g3, 2f
+        LOAD(prefetch, %o0 + 0x100, #n_reads)
+
+       /* So that we don't need to use the non-pairing
+        * add-with-carry instructions we accumulate 32-bit
+        * values into a 64-bit register.  At the end of the
+        * loop we fold it down to 32-bits and so on.
+        */
+       ba,pt           %xcc, 1f
+       LOAD(prefetch, %o0 + 0x140, #n_reads)
+
+       .align          32
+1:     EX_LD(LOAD(lduw, %o0 + 0x00, %o5))
+       EX_LD(LOAD(lduw, %o0 + 0x04, %g1))
+       EX_LD(LOAD(lduw, %o0 + 0x08, %g2))
+       add             %o4, %o5, %o4
+       EX_ST(STORE(stw, %o5, %o1 + 0x00))
+       EX_LD(LOAD(lduw, %o0 + 0x0c, %o5))
+       add             %o4, %g1, %o4
+       EX_ST(STORE(stw, %g1, %o1 + 0x04))
+       EX_LD(LOAD(lduw, %o0 + 0x10, %g1))
+       add             %o4, %g2, %o4
+       EX_ST(STORE(stw, %g2, %o1 + 0x08))
+       EX_LD(LOAD(lduw, %o0 + 0x14, %g2))
+       add             %o4, %o5, %o4
+       EX_ST(STORE(stw, %o5, %o1 + 0x0c))
+       EX_LD(LOAD(lduw, %o0 + 0x18, %o5))
+       add             %o4, %g1, %o4
+       EX_ST(STORE(stw, %g1, %o1 + 0x10))
+       EX_LD(LOAD(lduw, %o0 + 0x1c, %g1))
+       add             %o4, %g2, %o4
+       EX_ST(STORE(stw, %g2, %o1 + 0x14))
+       EX_LD(LOAD(lduw, %o0 + 0x20, %g2))
+       add             %o4, %o5, %o4
+       EX_ST(STORE(stw, %o5, %o1 + 0x18))
+       EX_LD(LOAD(lduw, %o0 + 0x24, %o5))
+       add             %o4, %g1, %o4
+       EX_ST(STORE(stw, %g1, %o1 + 0x1c))
+       EX_LD(LOAD(lduw, %o0 + 0x28, %g1))
+       add             %o4, %g2, %o4
+       EX_ST(STORE(stw, %g2, %o1 + 0x20))
+       EX_LD(LOAD(lduw, %o0 + 0x2c, %g2))
+       add             %o4, %o5, %o4
+       EX_ST(STORE(stw, %o5, %o1 + 0x24))
+       EX_LD(LOAD(lduw, %o0 + 0x30, %o5))
+       add             %o4, %g1, %o4
+       EX_ST(STORE(stw, %g1, %o1 + 0x28))
+       EX_LD(LOAD(lduw, %o0 + 0x34, %g1))
+       add             %o4, %g2, %o4
+       EX_ST(STORE(stw, %g2, %o1 + 0x2c))
+       EX_LD(LOAD(lduw, %o0 + 0x38, %g2))
+       add             %o4, %o5, %o4
+       EX_ST(STORE(stw, %o5, %o1 + 0x30))
+       EX_LD(LOAD(lduw, %o0 + 0x3c, %o5))
+       add             %o4, %g1, %o4
+       EX_ST(STORE(stw, %g1, %o1 + 0x34))
+       LOAD(prefetch, %o0 + 0x180, #n_reads)
+       add             %o4, %g2, %o4
+       EX_ST(STORE(stw, %g2, %o1 + 0x38))
+       subcc           %g3, 0x40, %g3
+       add             %o0, 0x40, %o0
+       add             %o4, %o5, %o4
+       EX_ST(STORE(stw, %o5, %o1 + 0x3c))
+       bne,pt          %icc, 1b
+        add            %o1, 0x40, %o1
+
+2:     and             %o2, 0x3c, %g3
+       brz,pn          %g3, 2f
+        sub            %o2, %g3, %o2
+1:     EX_LD(LOAD(lduw, %o0 + 0x00, %o5))
+       subcc           %g3, 0x4, %g3
+       add             %o0, 0x4, %o0
+       add             %o4, %o5, %o4
+       EX_ST(STORE(stw, %o5, %o1 + 0x00))
+       bne,pt          %icc, 1b
+        add            %o1, 0x4, %o1
+
+2:
+       /* fold 64-->32 */
+       srlx            %o4, 32, %o5
+       srl             %o4, 0, %o4
+       add             %o4, %o5, %o4
+       srlx            %o4, 32, %o5
+       srl             %o4, 0, %o4
+       add             %o4, %o5, %o4
+
+       /* fold 32-->16 */
+       sethi           %hi(0xffff0000), %g1
+       srl             %o4, 16, %o5
+       andn            %o4, %g1, %g2
+       add             %o5, %g2, %o4
+       srl             %o4, 16, %o5
+       andn            %o4, %g1, %g2
+       add             %o5, %g2, %o4
+
+60:
+       /* %o4 has the 16-bit sum we have calculated so-far.  */
+       cmp             %o2, 2
+       blu,pt          %icc, 1f
+        nop
+       EX_LD(LOAD(lduh, %o0 + 0x00, %o5))
+       sub             %o2, 2, %o2
+       add             %o0, 2, %o0
+       add             %o4, %o5, %o4
+       EX_ST(STORE(sth, %o5, %o1 + 0x00))
+       add             %o1, 0x2, %o1
+1:     brz,pt          %o2, 1f
+        nop
+       EX_LD(LOAD(ldub, %o0 + 0x00, %o5))
+       sub             %o2, 1, %o2
+       add             %o0, 1, %o0
+       EX_ST(STORE(stb, %o5, %o1 + 0x00))
+       sllx            %o5, 8, %o5
+       add             %o1, 1, %o1
+       add             %o4, %o5, %o4
+1:
+       /* fold 32-->16 */
+       sethi           %hi(0xffff0000), %g1
+       srl             %o4, 16, %o5
+       andn            %o4, %g1, %g2
+       add             %o5, %g2, %o4
+       srl             %o4, 16, %o5
+       andn            %o4, %g1, %g2
+       add             %o5, %g2, %o4
+
+1:     brz,pt          GLOBAL_SPARE, 1f
+        nop
+
+       /* We started with an odd byte, byte-swap the result.  */
+       srl             %o4, 8, %o5
+       and             %o4, 0xff, %g1
+       sll             %g1, 8, %g1
+       or              %o5, %g1, %o4
+
+1:     add             %o3, %o4, %o3
+
+70:
+       retl
+        mov            %o3, %o0
+
+95:    mov             0, GLOBAL_SPARE
+       brlez,pn        %o2, 4f
+        andcc          %o0, 1, %o5             
+       be,a,pt         %icc, 1f
+        srl            %o2, 1, %g1             
+       sub             %o2, 1, %o2     
+       EX_LD(LOAD(ldub, %o0, GLOBAL_SPARE))
+       add             %o0, 1, %o0     
+       EX_ST(STORE(stb, GLOBAL_SPARE, %o1))
+       srl             %o2, 1, %g1
+       add             %o1, 1, %o1
+1:     brz,a,pn        %g1, 3f
+        andcc          %o2, 1, %g0
+       andcc           %o0, 2, %g0     
+       be,a,pt         %icc, 1f
+        srl            %g1, 1, %g1
+       EX_LD(LOAD(lduh, %o0, %o4))
+       sub             %o2, 2, %o2     
+       srl             %o4, 8, %g2
+       sub             %g1, 1, %g1     
+       EX_ST(STORE(stb, %g2, %o1))
+       add             %o4, GLOBAL_SPARE, GLOBAL_SPARE
+       EX_ST(STORE(stb, %o4, %o1 + 1))
+       add             %o0, 2, %o0     
+       srl             %g1, 1, %g1
+       add             %o1, 2, %o1
+1:     brz,a,pn        %g1, 2f         
+        andcc          %o2, 2, %g0
+       EX_LD(LOAD(lduw, %o0, %o4))
+5:     srl             %o4, 24, %g2
+       srl             %o4, 16, %g3
+       EX_ST(STORE(stb, %g2, %o1))
+       srl             %o4, 8, %g2
+       EX_ST(STORE(stb, %g3, %o1 + 1))
+       add             %o0, 4, %o0
+       EX_ST(STORE(stb, %g2, %o1 + 2))
+       addcc           %o4, GLOBAL_SPARE, GLOBAL_SPARE
+       EX_ST(STORE(stb, %o4, %o1 + 3))
+       addc            GLOBAL_SPARE, %g0, GLOBAL_SPARE
+       add             %o1, 4, %o1
+       subcc           %g1, 1, %g1
+       bne,a,pt        %icc, 5b
+        EX_LD(LOAD(lduw, %o0, %o4))
+       sll             GLOBAL_SPARE, 16, %g2
+       srl             GLOBAL_SPARE, 16, GLOBAL_SPARE
+       srl             %g2, 16, %g2
+       andcc           %o2, 2, %g0
+       add             %g2, GLOBAL_SPARE, GLOBAL_SPARE 
+2:     be,a,pt         %icc, 3f                
+        andcc          %o2, 1, %g0
+       EX_LD(LOAD(lduh, %o0, %o4))
+       andcc           %o2, 1, %g0
+       srl             %o4, 8, %g2
+       add             %o0, 2, %o0     
+       EX_ST(STORE(stb, %g2, %o1))
+       add             GLOBAL_SPARE, %o4, GLOBAL_SPARE
+       EX_ST(STORE(stb, %o4, %o1 + 1))
+       add             %o1, 2, %o1
+3:     be,a,pt         %icc, 1f                
+        sll            GLOBAL_SPARE, 16, %o4
+       EX_LD(LOAD(ldub, %o0, %g2))
+       sll             %g2, 8, %o4     
+       EX_ST(STORE(stb, %g2, %o1))
+       add             GLOBAL_SPARE, %o4, GLOBAL_SPARE
+       sll             GLOBAL_SPARE, 16, %o4
+1:     addcc           %o4, GLOBAL_SPARE, GLOBAL_SPARE
+       srl             GLOBAL_SPARE, 16, %o4
+       addc            %g0, %o4, GLOBAL_SPARE
+       brz,pt          %o5, 4f
+        srl            GLOBAL_SPARE, 8, %o4
+       and             GLOBAL_SPARE, 0xff, %g2
+       and             %o4, 0xff, %o4
+       sll             %g2, 8, %g2
+       or              %g2, %o4, GLOBAL_SPARE
+4:     addcc           %o3, GLOBAL_SPARE, %o3
+       addc            %g0, %o3, %o0
+       retl
+        srl            %o0, 0, %o0
+       .size           FUNC_NAME, .-FUNC_NAME
diff --git a/arch/sparc64/lib/csum_copy_from_user.S b/arch/sparc64/lib/csum_copy_from_user.S
new file mode 100644 (file)
index 0000000..817ebda
--- /dev/null
@@ -0,0 +1,21 @@
+/* csum_copy_from_user.S: Checksum+copy from userspace.
+ *
+ * Copyright (C) 2005 David S. Miller (davem@davemloft.net)
+ */
+
+#define EX_LD(x)               \
+98:    x;                      \
+       .section .fixup;        \
+       .align 4;               \
+99:    retl;                   \
+        mov    -1, %o0;        \
+       .section __ex_table;    \
+       .align 4;               \
+       .word 98b, 99b;         \
+       .text;                  \
+       .align 4;
+
+#define FUNC_NAME              __csum_partial_copy_from_user
+#define LOAD(type,addr,dest)   type##a [addr] %asi, dest
+
+#include "csum_copy.S"
diff --git a/arch/sparc64/lib/csum_copy_to_user.S b/arch/sparc64/lib/csum_copy_to_user.S
new file mode 100644 (file)
index 0000000..c2f9463
--- /dev/null
@@ -0,0 +1,21 @@
+/* csum_copy_to_user.S: Checksum+copy to userspace.
+ *
+ * Copyright (C) 2005 David S. Miller (davem@davemloft.net)
+ */
+
+#define EX_ST(x)               \
+98:    x;                      \
+       .section .fixup;        \
+       .align 4;               \
+99:    retl;                   \
+        mov    -1, %o0;        \
+       .section __ex_table;    \
+       .align 4;               \
+       .word 98b, 99b;         \
+       .text;                  \
+       .align 4;
+
+#define FUNC_NAME              __csum_partial_copy_to_user
+#define STORE(type,src,addr)   type##a src, [addr] %asi
+
+#include "csum_copy.S"
diff --git a/arch/sparc64/lib/rwsem.S b/arch/sparc64/lib/rwsem.S
new file mode 100644 (file)
index 0000000..174ff7b
--- /dev/null
@@ -0,0 +1,165 @@
+/* rwsem.S: RW semaphore assembler.
+ *
+ * Written by David S. Miller (davem@redhat.com), 2001.
+ * Derived from asm-i386/rwsem.h
+ */
+
+#include <asm/rwsem-const.h>
+
+       .section        .sched.text
+
+       .globl          __down_read
+__down_read:
+1:     lduw            [%o0], %g1
+       add             %g1, 1, %g7
+       cas             [%o0], %g1, %g7
+       cmp             %g1, %g7
+       bne,pn          %icc, 1b
+        add            %g7, 1, %g7
+       cmp             %g7, 0
+       bl,pn           %icc, 3f
+        membar         #StoreLoad | #StoreStore
+2:
+       retl
+        nop
+3:
+       save            %sp, -192, %sp
+       call            rwsem_down_read_failed
+        mov            %i0, %o0
+       ret
+        restore
+       .size           __down_read, .-__down_read
+
+       .globl          __down_read_trylock
+__down_read_trylock:
+1:     lduw            [%o0], %g1
+       add             %g1, 1, %g7
+       cmp             %g7, 0
+       bl,pn           %icc, 2f
+        mov            0, %o1
+       cas             [%o0], %g1, %g7
+       cmp             %g1, %g7
+       bne,pn          %icc, 1b
+        mov            1, %o1
+       membar          #StoreLoad | #StoreStore
+2:     retl
+        mov            %o1, %o0
+       .size           __down_read_trylock, .-__down_read_trylock
+
+       .globl          __down_write
+__down_write:
+       sethi           %hi(RWSEM_ACTIVE_WRITE_BIAS), %g1
+       or              %g1, %lo(RWSEM_ACTIVE_WRITE_BIAS), %g1
+1:
+       lduw            [%o0], %g3
+       add             %g3, %g1, %g7
+       cas             [%o0], %g3, %g7
+       cmp             %g3, %g7
+       bne,pn          %icc, 1b
+        cmp            %g7, 0
+       bne,pn          %icc, 3f
+        membar         #StoreLoad | #StoreStore
+2:     retl
+        nop
+3:
+       save            %sp, -192, %sp
+       call            rwsem_down_write_failed
+        mov            %i0, %o0
+       ret
+        restore
+       .size           __down_write, .-__down_write
+
+       .globl          __down_write_trylock
+__down_write_trylock:
+       sethi           %hi(RWSEM_ACTIVE_WRITE_BIAS), %g1
+       or              %g1, %lo(RWSEM_ACTIVE_WRITE_BIAS), %g1
+1:
+       lduw            [%o0], %g3
+       cmp             %g3, 0
+       bne,pn          %icc, 2f
+        mov            0, %o1
+       add             %g3, %g1, %g7
+       cas             [%o0], %g3, %g7
+       cmp             %g3, %g7
+       bne,pn          %icc, 1b
+        mov            1, %o1
+       membar          #StoreLoad | #StoreStore
+2:     retl
+        mov            %o1, %o0
+       .size           __down_write_trylock, .-__down_write_trylock
+
+       .globl          __up_read
+__up_read:
+1:
+       lduw            [%o0], %g1
+       sub             %g1, 1, %g7
+       cas             [%o0], %g1, %g7
+       cmp             %g1, %g7
+       bne,pn          %icc, 1b
+        cmp            %g7, 0
+       bl,pn           %icc, 3f
+        membar         #StoreLoad | #StoreStore
+2:     retl
+        nop
+3:     sethi           %hi(RWSEM_ACTIVE_MASK), %g1
+       sub             %g7, 1, %g7
+       or              %g1, %lo(RWSEM_ACTIVE_MASK), %g1
+       andcc           %g7, %g1, %g0
+       bne,pn          %icc, 2b
+        nop
+       save            %sp, -192, %sp
+       call            rwsem_wake
+        mov            %i0, %o0
+       ret
+        restore
+       .size           __up_read, .-__up_read
+
+       .globl          __up_write
+__up_write:
+       sethi           %hi(RWSEM_ACTIVE_WRITE_BIAS), %g1
+       or              %g1, %lo(RWSEM_ACTIVE_WRITE_BIAS), %g1
+1:
+       lduw            [%o0], %g3
+       sub             %g3, %g1, %g7
+       cas             [%o0], %g3, %g7
+       cmp             %g3, %g7
+       bne,pn          %icc, 1b
+        sub            %g7, %g1, %g7
+       cmp             %g7, 0
+       bl,pn           %icc, 3f
+        membar         #StoreLoad | #StoreStore
+2:
+       retl
+        nop
+3:
+       save            %sp, -192, %sp
+       call            rwsem_wake
+        mov            %i0, %o0
+       ret
+        restore
+       .size           __up_write, .-__up_write
+
+       .globl          __downgrade_write
+__downgrade_write:
+       sethi           %hi(RWSEM_WAITING_BIAS), %g1
+       or              %g1, %lo(RWSEM_WAITING_BIAS), %g1
+1:
+       lduw            [%o0], %g3
+       sub             %g3, %g1, %g7
+       cas             [%o0], %g3, %g7
+       cmp             %g3, %g7
+       bne,pn          %icc, 1b
+        sub            %g7, %g1, %g7
+       cmp             %g7, 0
+       bl,pn           %icc, 3f
+        membar         #StoreLoad | #StoreStore
+2:
+       retl
+        nop
+3:
+       save            %sp, -192, %sp
+       call            rwsem_downgrade_wake
+        mov            %i0, %o0
+       ret
+        restore
+       .size           __downgrade_write, .-__downgrade_write
diff --git a/arch/um/drivers/slip_common.c b/arch/um/drivers/slip_common.c
new file mode 100644 (file)
index 0000000..e89cfc6
--- /dev/null
@@ -0,0 +1,54 @@
+#include <string.h>
+#include "slip_common.h"
+#include "net_user.h"
+
+int slip_proto_read(int fd, void *buf, int len, struct slip_proto *slip)
+{
+       int i, n, size, start;
+
+       if(slip->more > 0){
+               i = 0;
+               while(i < slip->more){
+                       size = slip_unesc(slip->ibuf[i++], slip->ibuf,
+                                         &slip->pos, &slip->esc);
+                       if(size){
+                               memcpy(buf, slip->ibuf, size);
+                               memmove(slip->ibuf, &slip->ibuf[i],
+                                       slip->more - i);
+                               slip->more = slip->more - i;
+                               return size;
+                       }
+               }
+               slip->more = 0;
+       }
+
+       n = net_read(fd, &slip->ibuf[slip->pos],
+                    sizeof(slip->ibuf) - slip->pos);
+       if(n <= 0)
+               return n;
+
+       start = slip->pos;
+       for(i = 0; i < n; i++){
+               size = slip_unesc(slip->ibuf[start + i], slip->ibuf,&slip->pos,
+                                 &slip->esc);
+               if(size){
+                       memcpy(buf, slip->ibuf, size);
+                       memmove(slip->ibuf, &slip->ibuf[start+i+1],
+                               n - (i + 1));
+                       slip->more = n - (i + 1);
+                       return size;
+               }
+       }
+       return 0;
+}
+
+int slip_proto_write(int fd, void *buf, int len, struct slip_proto *slip)
+{
+       int actual, n;
+
+       actual = slip_esc(buf, slip->obuf, len);
+       n = net_write(fd, slip->obuf, actual);
+       if(n < 0)
+               return n;
+       else return len;
+}
diff --git a/arch/um/drivers/slip_common.h b/arch/um/drivers/slip_common.h
new file mode 100644 (file)
index 0000000..2ae76d8
--- /dev/null
@@ -0,0 +1,104 @@
+#ifndef __UM_SLIP_COMMON_H
+#define __UM_SLIP_COMMON_H
+
+#define BUF_SIZE 1500
+ /* two bytes each for a (pathological) max packet of escaped chars +  *
+  * terminating END char + initial END char                            */
+#define ENC_BUF_SIZE (2 * BUF_SIZE + 2)
+
+/* SLIP protocol characters. */
+#define SLIP_END             0300      /* indicates end of frame       */
+#define SLIP_ESC             0333      /* indicates byte stuffing      */
+#define SLIP_ESC_END         0334      /* ESC ESC_END means END 'data' */
+#define SLIP_ESC_ESC         0335      /* ESC ESC_ESC means ESC 'data' */
+
+static inline int slip_unesc(unsigned char c, unsigned char *buf, int *pos,
+                             int *esc)
+{
+       int ret;
+
+       switch(c){
+       case SLIP_END:
+               *esc = 0;
+               ret=*pos;
+               *pos=0;
+               return(ret);
+       case SLIP_ESC:
+               *esc = 1;
+               return(0);
+       case SLIP_ESC_ESC:
+               if(*esc){
+                       *esc = 0;
+                       c = SLIP_ESC;
+               }
+               break;
+       case SLIP_ESC_END:
+               if(*esc){
+                       *esc = 0;
+                       c = SLIP_END;
+               }
+               break;
+       }
+       buf[(*pos)++] = c;
+       return(0);
+}
+
+static inline int slip_esc(unsigned char *s, unsigned char *d, int len)
+{
+       unsigned char *ptr = d;
+       unsigned char c;
+
+       /*
+        * Send an initial END character to flush out any
+        * data that may have accumulated in the receiver
+        * due to line noise.
+        */
+
+       *ptr++ = SLIP_END;
+
+       /*
+        * For each byte in the packet, send the appropriate
+        * character sequence, according to the SLIP protocol.
+        */
+
+       while (len-- > 0) {
+               switch(c = *s++) {
+               case SLIP_END:
+                       *ptr++ = SLIP_ESC;
+                       *ptr++ = SLIP_ESC_END;
+                       break;
+               case SLIP_ESC:
+                       *ptr++ = SLIP_ESC;
+                       *ptr++ = SLIP_ESC_ESC;
+                       break;
+               default:
+                       *ptr++ = c;
+                       break;
+               }
+       }
+       *ptr++ = SLIP_END;
+       return (ptr - d);
+}
+
+struct slip_proto {
+       unsigned char ibuf[ENC_BUF_SIZE];
+       unsigned char obuf[ENC_BUF_SIZE];
+       int more; /* more data: do not read fd until ibuf has been drained */
+       int pos;
+       int esc;
+};
+
+#define SLIP_PROTO_INIT { \
+       .ibuf   = { '\0' }, \
+       .obuf   = { '\0' }, \
+        .more  = 0, \
+       .pos    = 0, \
+       .esc    = 0 \
+}
+
+extern int slip_proto_read(int fd, void *buf, int len,
+                          struct slip_proto *slip);
+extern int slip_proto_write(int fd, void *buf, int len,
+                           struct slip_proto *slip);
+
+#endif
diff --git a/arch/um/include/sysdep-i386/faultinfo.h b/arch/um/include/sysdep-i386/faultinfo.h
new file mode 100644 (file)
index 0000000..db437cc
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2004 Fujitsu Siemens Computers GmbH
+ * Author: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
+ * Licensed under the GPL
+ */
+
+#ifndef __FAULTINFO_I386_H
+#define __FAULTINFO_I386_H
+
+/* this structure contains the full arch-specific faultinfo
+ * from the traps.
+ * On i386, ptrace_faultinfo unfortunately doesn't provide
+ * all the info, since trap_no is missing.
+ * All common elements are defined at the same position in
+ * both structures, thus making it easy to copy the
+ * contents without knowledge about the structure elements.
+ */
+struct faultinfo {
+        int error_code; /* in ptrace_faultinfo misleadingly called is_write */
+        unsigned long cr2; /* in ptrace_faultinfo called addr */
+        int trap_no; /* missing in ptrace_faultinfo */
+};
+
+#define FAULT_WRITE(fi) ((fi).error_code & 2)
+#define FAULT_ADDRESS(fi) ((fi).cr2)
+
+#define PTRACE_FULL_FAULTINFO 0
+
+#endif
diff --git a/arch/um/include/sysdep-i386/skas_ptrace.h b/arch/um/include/sysdep-i386/skas_ptrace.h
new file mode 100644 (file)
index 0000000..e27b8a7
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __SYSDEP_I386_SKAS_PTRACE_H
+#define __SYSDEP_I386_SKAS_PTRACE_H
+
+struct ptrace_faultinfo {
+        int is_write;
+        unsigned long addr;
+};
+
+struct ptrace_ldt {
+        int func;
+        void *ptr;
+        unsigned long bytecount;
+};
+
+#define PTRACE_LDT 54
+
+#endif
diff --git a/arch/um/include/sysdep-ia64/skas_ptrace.h b/arch/um/include/sysdep-ia64/skas_ptrace.h
new file mode 100644 (file)
index 0000000..25a38e7
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __SYSDEP_IA64_SKAS_PTRACE_H
+#define __SYSDEP_IA64_SKAS_PTRACE_H
+
+struct ptrace_faultinfo {
+        int is_write;
+        unsigned long addr;
+};
+
+struct ptrace_ldt {
+        int func;
+        void *ptr;
+        unsigned long bytecount;
+};
+
+#define PTRACE_LDT 54
+
+#endif
diff --git a/arch/um/include/sysdep-ppc/skas_ptrace.h b/arch/um/include/sysdep-ppc/skas_ptrace.h
new file mode 100644 (file)
index 0000000..d9fbbac
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __SYSDEP_PPC_SKAS_PTRACE_H
+#define __SYSDEP_PPC_SKAS_PTRACE_H
+
+struct ptrace_faultinfo {
+        int is_write;
+        unsigned long addr;
+};
+
+struct ptrace_ldt {
+        int func;
+        void *ptr;
+        unsigned long bytecount;
+};
+
+#define PTRACE_LDT 54
+
+#endif
diff --git a/arch/um/include/sysdep-x86_64/faultinfo.h b/arch/um/include/sysdep-x86_64/faultinfo.h
new file mode 100644 (file)
index 0000000..cb917b0
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2004 Fujitsu Siemens Computers GmbH
+ * Author: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
+ * Licensed under the GPL
+ */
+
+#ifndef __FAULTINFO_X86_64_H
+#define __FAULTINFO_X86_64_H
+
+/* this structure contains the full arch-specific faultinfo
+ * from the traps.
+ * On i386, ptrace_faultinfo unfortunately doesn't provide
+ * all the info, since trap_no is missing.
+ * All common elements are defined at the same position in
+ * both structures, thus making it easy to copy the
+ * contents without knowledge about the structure elements.
+ */
+struct faultinfo {
+        int error_code; /* in ptrace_faultinfo misleadingly called is_write */
+        unsigned long cr2; /* in ptrace_faultinfo called addr */
+        int trap_no; /* missing in ptrace_faultinfo */
+};
+
+#define FAULT_WRITE(fi) ((fi).error_code & 2)
+#define FAULT_ADDRESS(fi) ((fi).cr2)
+
+#define PTRACE_FULL_FAULTINFO 1
+
+#endif
diff --git a/arch/um/include/sysdep-x86_64/skas_ptrace.h b/arch/um/include/sysdep-x86_64/skas_ptrace.h
new file mode 100644 (file)
index 0000000..95db4be
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __SYSDEP_X86_64_SKAS_PTRACE_H
+#define __SYSDEP_X86_64_SKAS_PTRACE_H
+
+struct ptrace_faultinfo {
+        int is_write;
+        unsigned long addr;
+};
+
+struct ptrace_ldt {
+        int func;
+        void *ptr;
+        unsigned long bytecount;
+};
+
+#define PTRACE_LDT 54
+
+#endif
diff --git a/arch/um/kernel/initrd.c b/arch/um/kernel/initrd.c
new file mode 100644 (file)
index 0000000..82ecf90
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/init.h"
+#include "linux/bootmem.h"
+#include "linux/initrd.h"
+#include "asm/types.h"
+#include "user_util.h"
+#include "kern_util.h"
+#include "initrd.h"
+#include "init.h"
+#include "os.h"
+
+/* Changed by uml_initrd_setup, which is a setup */
+static char *initrd __initdata = NULL;
+
+static int __init read_initrd(void)
+{
+       void *area;
+       long long size;
+       int err;
+
+       if(initrd == NULL) return 0;
+       err = os_file_size(initrd, &size);
+       if(err) return 0;
+       area = alloc_bootmem(size);
+       if(area == NULL) return 0;
+       if(load_initrd(initrd, area, size) == -1) return 0;
+       initrd_start = (unsigned long) area;
+       initrd_end = initrd_start + size;
+       return 0;
+}
+
+__uml_postsetup(read_initrd);
+
+static int __init uml_initrd_setup(char *line, int *add)
+{
+       initrd = line;
+       return 0;
+}
+
+__uml_setup("initrd=", uml_initrd_setup,
+"initrd=<initrd image>\n"
+"    This is used to boot UML from an initrd image.  The argument is the\n"
+"    name of the file containing the image.\n\n"
+);
+
+int load_initrd(char *filename, void *buf, int size)
+{
+       int fd, n;
+
+       fd = os_open_file(filename, of_read(OPENFLAGS()), 0);
+       if(fd < 0){
+               printk("Opening '%s' failed - err = %d\n", filename, -fd);
+               return(-1);
+       }
+       n = os_read_file(fd, buf, size);
+       if(n != size){
+               printk("Read of %d bytes from '%s' failed, err = %d\n", size,
+                      filename, -n);
+               return(-1);
+       }
+
+       os_close_file(fd);
+       return(0);
+}
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/sys-x86_64/um_module.c b/arch/um/sys-x86_64/um_module.c
new file mode 100644 (file)
index 0000000..8b8eff1
--- /dev/null
@@ -0,0 +1,19 @@
+#include <linux/vmalloc.h>
+#include <linux/moduleloader.h>
+
+/*Copied from i386 arch/i386/kernel/module.c */
+void *module_alloc(unsigned long size)
+{
+       if (size == 0)
+               return NULL;
+       return vmalloc_exec(size);
+}
+
+/* Free memory returned from module_alloc */
+void module_free(struct module *mod, void *module_region)
+{
+       vfree(module_region);
+       /* FIXME: If module_region == mod->init_region, trim exception
+           table entries. */
+}
+
diff --git a/drivers/char/mbcs.h b/drivers/char/mbcs.h
new file mode 100644 (file)
index 0000000..e7fd47e
--- /dev/null
@@ -0,0 +1,553 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 2005 Silicon Graphics, Inc.  All rights reserved.
+ */
+
+#ifndef __MBCS_H__
+#define __MBCS_H__
+
+/*
+ * General macros
+ */
+#define MB     (1024*1024)
+#define MB2    (2*MB)
+#define MB4    (4*MB)
+#define MB6    (6*MB)
+
+/*
+ * Offsets and masks
+ */
+#define MBCS_CM_ID             0x0000  /* Identification */
+#define MBCS_CM_STATUS         0x0008  /* Status */
+#define MBCS_CM_ERROR_DETAIL1  0x0010  /* Error Detail1 */
+#define MBCS_CM_ERROR_DETAIL2  0x0018  /* Error Detail2 */
+#define MBCS_CM_CONTROL                0x0020  /* Control */
+#define MBCS_CM_REQ_TOUT       0x0028  /* Request Time-out */
+#define MBCS_CM_ERR_INT_DEST   0x0038  /* Error Interrupt Destination */
+#define MBCS_CM_TARG_FL                0x0050  /* Target Flush */
+#define MBCS_CM_ERR_STAT       0x0060  /* Error Status */
+#define MBCS_CM_CLR_ERR_STAT   0x0068  /* Clear Error Status */
+#define MBCS_CM_ERR_INT_EN     0x0070  /* Error Interrupt Enable */
+#define MBCS_RD_DMA_SYS_ADDR   0x0100  /* Read DMA System Address */
+#define MBCS_RD_DMA_LOC_ADDR   0x0108  /* Read DMA Local Address */
+#define MBCS_RD_DMA_CTRL       0x0110  /* Read DMA Control */
+#define MBCS_RD_DMA_AMO_DEST   0x0118  /* Read DMA AMO Destination */
+#define MBCS_RD_DMA_INT_DEST   0x0120  /* Read DMA Interrupt Destination */
+#define MBCS_RD_DMA_AUX_STAT   0x0130  /* Read DMA Auxillary Status */
+#define MBCS_WR_DMA_SYS_ADDR   0x0200  /* Write DMA System Address */
+#define MBCS_WR_DMA_LOC_ADDR   0x0208  /* Write DMA Local Address */
+#define MBCS_WR_DMA_CTRL       0x0210  /* Write DMA Control */
+#define MBCS_WR_DMA_AMO_DEST   0x0218  /* Write DMA AMO Destination */
+#define MBCS_WR_DMA_INT_DEST   0x0220  /* Write DMA Interrupt Destination */
+#define MBCS_WR_DMA_AUX_STAT   0x0230  /* Write DMA Auxillary Status */
+#define MBCS_ALG_AMO_DEST      0x0300  /* Algorithm AMO Destination */
+#define MBCS_ALG_INT_DEST      0x0308  /* Algorithm Interrupt Destination */
+#define MBCS_ALG_OFFSETS       0x0310
+#define MBCS_ALG_STEP          0x0318  /* Algorithm Step */
+
+#define MBCS_GSCR_START                0x0000000
+#define MBCS_DEBUG_START       0x0100000
+#define MBCS_RAM0_START                0x0200000
+#define MBCS_RAM1_START                0x0400000
+#define MBCS_RAM2_START                0x0600000
+
+#define MBCS_CM_CONTROL_REQ_TOUT_MASK 0x0000000000ffffffUL
+//#define PIO_BASE_ADDR_BASE_OFFSET_MASK 0x00fffffffff00000UL
+
+#define MBCS_SRAM_SIZE         (1024*1024)
+#define MBCS_CACHELINE_SIZE    128
+
+/*
+ * MMR get's and put's
+ */
+#define MBCS_MMR_ADDR(mmr_base, offset)((uint64_t *)(mmr_base + offset))
+#define MBCS_MMR_SET(mmr_base, offset, value) {                        \
+       uint64_t *mbcs_mmr_set_u64p, readback;                          \
+       mbcs_mmr_set_u64p = (uint64_t *)(mmr_base + offset);    \
+       *mbcs_mmr_set_u64p = value;                                     \
+       readback = *mbcs_mmr_set_u64p; \
+}
+#define MBCS_MMR_GET(mmr_base, offset) *(uint64_t *)(mmr_base + offset)
+#define MBCS_MMR_ZERO(mmr_base, offset) MBCS_MMR_SET(mmr_base, offset, 0)
+
+/*
+ * MBCS mmr structures
+ */
+union cm_id {
+       uint64_t cm_id_reg;
+       struct {
+               uint64_t always_one:1,  // 0
+                mfg_id:11,     // 11:1
+                part_num:16,   // 27:12
+                bitstream_rev:8,       // 35:28
+               :28;            // 63:36
+       };
+};
+
+union cm_status {
+       uint64_t cm_status_reg;
+       struct {
+               uint64_t pending_reads:8,       // 7:0
+                pending_writes:8,      // 15:8
+                ice_rsp_credits:8,     // 23:16
+                ice_req_credits:8,     // 31:24
+                cm_req_credits:8,      // 39:32
+               :1,             // 40
+                rd_dma_in_progress:1,  // 41
+                rd_dma_done:1, // 42
+               :1,             // 43
+                wr_dma_in_progress:1,  // 44
+                wr_dma_done:1, // 45
+                alg_waiting:1, // 46
+                alg_pipe_running:1,    // 47
+                alg_done:1,    // 48
+               :3,             // 51:49
+                pending_int_reqs:8,    // 59:52
+               :3,             // 62:60
+                alg_half_speed_sel:1;  // 63
+       };
+};
+
+union cm_error_detail1 {
+       uint64_t cm_error_detail1_reg;
+       struct {
+               uint64_t packet_type:4, // 3:0
+                source_id:2,   // 5:4
+                data_size:2,   // 7:6
+                tnum:8,        // 15:8
+                byte_enable:8, // 23:16
+                gfx_cred:8,    // 31:24
+                read_type:2,   // 33:32
+                pio_or_memory:1,       // 34
+                head_cw_error:1,       // 35
+               :12,            // 47:36
+                head_error_bit:1,      // 48
+                data_error_bit:1,      // 49
+               :13,            // 62:50
+                valid:1;       // 63
+       };
+};
+
+union cm_error_detail2 {
+       uint64_t cm_error_detail2_reg;
+       struct {
+               uint64_t address:56,    // 55:0
+               :8;             // 63:56
+       };
+};
+
+union cm_control {
+       uint64_t cm_control_reg;
+       struct {
+               uint64_t cm_id:2,       // 1:0
+               :2,             // 3:2
+                max_trans:5,   // 8:4
+               :3,             // 11:9
+                address_mode:1,        // 12
+               :7,             // 19:13
+                credit_limit:8,        // 27:20
+               :5,             // 32:28
+                rearm_stat_regs:1,     // 33
+                prescalar_byp:1,       // 34
+                force_gap_war:1,       // 35
+                rd_dma_go:1,   // 36
+                wr_dma_go:1,   // 37
+                alg_go:1,      // 38
+                rd_dma_clr:1,  // 39
+                wr_dma_clr:1,  // 40
+                alg_clr:1,     // 41
+               :2,             // 43:42
+                alg_wait_step:1,       // 44
+                alg_done_amo_en:1,     // 45
+                alg_done_int_en:1,     // 46
+               :1,             // 47
+                alg_sram0_locked:1,    // 48
+                alg_sram1_locked:1,    // 49
+                alg_sram2_locked:1,    // 50
+                alg_done_clr:1,        // 51
+               :12;            // 63:52
+       };
+};
+
+union cm_req_timeout {
+       uint64_t cm_req_timeout_reg;
+       struct {
+               uint64_t time_out:24,   // 23:0
+               :40;            // 63:24
+       };
+};
+
+union intr_dest {
+       uint64_t intr_dest_reg;
+       struct {
+               uint64_t address:56,    // 55:0
+                int_vector:8;  // 63:56
+       };
+};
+
+union cm_error_status {
+       uint64_t cm_error_status_reg;
+       struct {
+               uint64_t ecc_sbe:1,     // 0
+                ecc_mbe:1,     // 1
+                unsupported_req:1,     // 2
+                unexpected_rsp:1,      // 3
+                bad_length:1,  // 4
+                bad_datavalid:1,       // 5
+                buffer_overflow:1,     // 6
+                request_timeout:1,     // 7
+               :8,             // 15:8
+                head_inv_data_size:1,  // 16
+                rsp_pactype_inv:1,     // 17
+                head_sb_err:1, // 18
+                missing_head:1,        // 19
+                head_inv_rd_type:1,    // 20
+                head_cmd_err_bit:1,    // 21
+                req_addr_align_inv:1,  // 22
+                pio_req_addr_inv:1,    // 23
+                req_range_dsize_inv:1, // 24
+                early_term:1,  // 25
+                early_tail:1,  // 26
+                missing_tail:1,        // 27
+                data_flit_sb_err:1,    // 28
+                cm2hcm_req_cred_of:1,  // 29
+                cm2hcm_rsp_cred_of:1,  // 30
+                rx_bad_didn:1, // 31
+                rd_dma_err_rsp:1,      // 32
+                rd_dma_tnum_tout:1,    // 33
+                rd_dma_multi_tnum_tou:1,       // 34
+                wr_dma_err_rsp:1,      // 35
+                wr_dma_tnum_tout:1,    // 36
+                wr_dma_multi_tnum_tou:1,       // 37
+                alg_data_overflow:1,   // 38
+                alg_data_underflow:1,  // 39
+                ram0_access_conflict:1,        // 40
+                ram1_access_conflict:1,        // 41
+                ram2_access_conflict:1,        // 42
+                ram0_perr:1,   // 43
+                ram1_perr:1,   // 44
+                ram2_perr:1,   // 45
+                int_gen_rsp_err:1,     // 46
+                int_gen_tnum_tout:1,   // 47
+                rd_dma_prog_err:1,     // 48
+                wr_dma_prog_err:1,     // 49
+               :14;            // 63:50
+       };
+};
+
+union cm_clr_error_status {
+       uint64_t cm_clr_error_status_reg;
+       struct {
+               uint64_t clr_ecc_sbe:1, // 0
+                clr_ecc_mbe:1, // 1
+                clr_unsupported_req:1, // 2
+                clr_unexpected_rsp:1,  // 3
+                clr_bad_length:1,      // 4
+                clr_bad_datavalid:1,   // 5
+                clr_buffer_overflow:1, // 6
+                clr_request_timeout:1, // 7
+               :8,             // 15:8
+                clr_head_inv_data_siz:1,       // 16
+                clr_rsp_pactype_inv:1, // 17
+                clr_head_sb_err:1,     // 18
+                clr_missing_head:1,    // 19
+                clr_head_inv_rd_type:1,        // 20
+                clr_head_cmd_err_bit:1,        // 21
+                clr_req_addr_align_in:1,       // 22
+                clr_pio_req_addr_inv:1,        // 23
+                clr_req_range_dsize_i:1,       // 24
+                clr_early_term:1,      // 25
+                clr_early_tail:1,      // 26
+                clr_missing_tail:1,    // 27
+                clr_data_flit_sb_err:1,        // 28
+                clr_cm2hcm_req_cred_o:1,       // 29
+                clr_cm2hcm_rsp_cred_o:1,       // 30
+                clr_rx_bad_didn:1,     // 31
+                clr_rd_dma_err_rsp:1,  // 32
+                clr_rd_dma_tnum_tout:1,        // 33
+                clr_rd_dma_multi_tnum:1,       // 34
+                clr_wr_dma_err_rsp:1,  // 35
+                clr_wr_dma_tnum_tout:1,        // 36
+                clr_wr_dma_multi_tnum:1,       // 37
+                clr_alg_data_overflow:1,       // 38
+                clr_alg_data_underflo:1,       // 39
+                clr_ram0_access_confl:1,       // 40
+                clr_ram1_access_confl:1,       // 41
+                clr_ram2_access_confl:1,       // 42
+                clr_ram0_perr:1,       // 43
+                clr_ram1_perr:1,       // 44
+                clr_ram2_perr:1,       // 45
+                clr_int_gen_rsp_err:1, // 46
+                clr_int_gen_tnum_tout:1,       // 47
+                clr_rd_dma_prog_err:1, // 48
+                clr_wr_dma_prog_err:1, // 49
+               :14;            // 63:50
+       };
+};
+
+union cm_error_intr_enable {
+       uint64_t cm_error_intr_enable_reg;
+       struct {
+               uint64_t int_en_ecc_sbe:1,      // 0
+                int_en_ecc_mbe:1,      // 1
+                int_en_unsupported_re:1,       // 2
+                int_en_unexpected_rsp:1,       // 3
+                int_en_bad_length:1,   // 4
+                int_en_bad_datavalid:1,        // 5
+                int_en_buffer_overflo:1,       // 6
+                int_en_request_timeou:1,       // 7
+               :8,             // 15:8
+                int_en_head_inv_data_:1,       // 16
+                int_en_rsp_pactype_in:1,       // 17
+                int_en_head_sb_err:1,  // 18
+                int_en_missing_head:1, // 19
+                int_en_head_inv_rd_ty:1,       // 20
+                int_en_head_cmd_err_b:1,       // 21
+                int_en_req_addr_align:1,       // 22
+                int_en_pio_req_addr_i:1,       // 23
+                int_en_req_range_dsiz:1,       // 24
+                int_en_early_term:1,   // 25
+                int_en_early_tail:1,   // 26
+                int_en_missing_tail:1, // 27
+                int_en_data_flit_sb_e:1,       // 28
+                int_en_cm2hcm_req_cre:1,       // 29
+                int_en_cm2hcm_rsp_cre:1,       // 30
+                int_en_rx_bad_didn:1,  // 31
+                int_en_rd_dma_err_rsp:1,       // 32
+                int_en_rd_dma_tnum_to:1,       // 33
+                int_en_rd_dma_multi_t:1,       // 34
+                int_en_wr_dma_err_rsp:1,       // 35
+                int_en_wr_dma_tnum_to:1,       // 36
+                int_en_wr_dma_multi_t:1,       // 37
+                int_en_alg_data_overf:1,       // 38
+                int_en_alg_data_under:1,       // 39
+                int_en_ram0_access_co:1,       // 40
+                int_en_ram1_access_co:1,       // 41
+                int_en_ram2_access_co:1,       // 42
+                int_en_ram0_perr:1,    // 43
+                int_en_ram1_perr:1,    // 44
+                int_en_ram2_perr:1,    // 45
+                int_en_int_gen_rsp_er:1,       // 46
+                int_en_int_gen_tnum_t:1,       // 47
+                int_en_rd_dma_prog_er:1,       // 48
+                int_en_wr_dma_prog_er:1,       // 49
+               :14;            // 63:50
+       };
+};
+
+struct cm_mmr {
+       union cm_id id;
+       union cm_status status;
+       union cm_error_detail1 err_detail1;
+       union cm_error_detail2 err_detail2;
+       union cm_control control;
+       union cm_req_timeout req_timeout;
+       uint64_t reserved1[1];
+       union intr_dest int_dest;
+       uint64_t reserved2[2];
+       uint64_t targ_flush;
+       uint64_t reserved3[1];
+       union cm_error_status err_status;
+       union cm_clr_error_status clr_err_status;
+       union cm_error_intr_enable int_enable;
+};
+
+union dma_hostaddr {
+       uint64_t dma_hostaddr_reg;
+       struct {
+               uint64_t dma_sys_addr:56,       // 55:0
+               :8;             // 63:56
+       };
+};
+
+union dma_localaddr {
+       uint64_t dma_localaddr_reg;
+       struct {
+               uint64_t dma_ram_addr:21,       // 20:0
+                dma_ram_sel:2, // 22:21
+               :41;            // 63:23
+       };
+};
+
+union dma_control {
+       uint64_t dma_control_reg;
+       struct {
+               uint64_t dma_op_length:16,      // 15:0
+               :18,            // 33:16
+                done_amo_en:1, // 34
+                done_int_en:1, // 35
+               :1,             // 36
+                pio_mem_n:1,   // 37
+               :26;            // 63:38
+       };
+};
+
+union dma_amo_dest {
+       uint64_t dma_amo_dest_reg;
+       struct {
+               uint64_t dma_amo_sys_addr:56,   // 55:0
+                dma_amo_mod_type:3,    // 58:56
+               :5;             // 63:59
+       };
+};
+
+union rdma_aux_status {
+       uint64_t rdma_aux_status_reg;
+       struct {
+               uint64_t op_num_pacs_left:17,   // 16:0
+               :5,             // 21:17
+                lrsp_buff_empty:1,     // 22
+               :17,            // 39:23
+                pending_reqs_left:6,   // 45:40
+               :18;            // 63:46
+       };
+};
+
+struct rdma_mmr {
+       union dma_hostaddr host_addr;
+       union dma_localaddr local_addr;
+       union dma_control control;
+       union dma_amo_dest amo_dest;
+       union intr_dest intr_dest;
+       union rdma_aux_status aux_status;
+};
+
+union wdma_aux_status {
+       uint64_t wdma_aux_status_reg;
+       struct {
+               uint64_t op_num_pacs_left:17,   // 16:0
+               :4,             // 20:17
+                lreq_buff_empty:1,     // 21
+               :18,            // 39:22
+                pending_reqs_left:6,   // 45:40
+               :18;            // 63:46
+       };
+};
+
+struct wdma_mmr {
+       union dma_hostaddr host_addr;
+       union dma_localaddr local_addr;
+       union dma_control control;
+       union dma_amo_dest amo_dest;
+       union intr_dest intr_dest;
+       union wdma_aux_status aux_status;
+};
+
+union algo_step {
+       uint64_t algo_step_reg;
+       struct {
+               uint64_t alg_step_cnt:16,       // 15:0
+               :48;            // 63:16
+       };
+};
+
+struct algo_mmr {
+       union dma_amo_dest amo_dest;
+       union intr_dest intr_dest;
+       union {
+               uint64_t algo_offset_reg;
+               struct {
+                       uint64_t sram0_offset:7,        // 6:0
+                       reserved0:1,    // 7
+                       sram1_offset:7, // 14:8
+                       reserved1:1,    // 15
+                       sram2_offset:7, // 22:16
+                       reserved2:14;   // 63:23
+               };
+       } sram_offset;
+       union algo_step step;
+};
+
+struct mbcs_mmr {
+       struct cm_mmr cm;
+       uint64_t reserved1[17];
+       struct rdma_mmr rdDma;
+       uint64_t reserved2[25];
+       struct wdma_mmr wrDma;
+       uint64_t reserved3[25];
+       struct algo_mmr algo;
+       uint64_t reserved4[156];
+};
+
+/*
+ * defines
+ */
+#define DEVICE_NAME "mbcs"
+#define MBCS_PART_NUM 0xfff0
+#define MBCS_PART_NUM_ALG0 0xf001
+#define MBCS_MFG_NUM  0x1
+
+struct algoblock {
+       uint64_t amoHostDest;
+       uint64_t amoModType;
+       uint64_t intrHostDest;
+       uint64_t intrVector;
+       uint64_t algoStepCount;
+};
+
+struct getdma {
+       uint64_t hostAddr;
+       uint64_t localAddr;
+       uint64_t bytes;
+       uint64_t DoneAmoEnable;
+       uint64_t DoneIntEnable;
+       uint64_t peerIO;
+       uint64_t amoHostDest;
+       uint64_t amoModType;
+       uint64_t intrHostDest;
+       uint64_t intrVector;
+};
+
+struct putdma {
+       uint64_t hostAddr;
+       uint64_t localAddr;
+       uint64_t bytes;
+       uint64_t DoneAmoEnable;
+       uint64_t DoneIntEnable;
+       uint64_t peerIO;
+       uint64_t amoHostDest;
+       uint64_t amoModType;
+       uint64_t intrHostDest;
+       uint64_t intrVector;
+};
+
+struct mbcs_soft {
+       struct list_head list;
+       struct cx_dev *cxdev;
+       int major;
+       int nasid;
+       void *mmr_base;
+       wait_queue_head_t dmawrite_queue;
+       wait_queue_head_t dmaread_queue;
+       wait_queue_head_t algo_queue;
+       struct sn_irq_info *get_sn_irq;
+       struct sn_irq_info *put_sn_irq;
+       struct sn_irq_info *algo_sn_irq;
+       struct getdma getdma;
+       struct putdma putdma;
+       struct algoblock algo;
+       uint64_t gscr_addr;     // pio addr
+       uint64_t ram0_addr;     // pio addr
+       uint64_t ram1_addr;     // pio addr
+       uint64_t ram2_addr;     // pio addr
+       uint64_t debug_addr;    // pio addr
+       atomic_t dmawrite_done;
+       atomic_t dmaread_done;
+       atomic_t algo_done;
+       struct semaphore dmawritelock;
+       struct semaphore dmareadlock;
+       struct semaphore algolock;
+};
+
+extern int mbcs_open(struct inode *ip, struct file *fp);
+extern ssize_t mbcs_sram_read(struct file *fp, char __user *buf, size_t len,
+                             loff_t * off);
+extern ssize_t mbcs_sram_write(struct file *fp, const char __user *buf, size_t len,
+                              loff_t * off);
+extern loff_t mbcs_sram_llseek(struct file *filp, loff_t off, int whence);
+extern int mbcs_gscr_mmap(struct file *fp, struct vm_area_struct *vma);
+
+#endif                         // __MBCS_H__
diff --git a/drivers/md/dm-bio-record.h b/drivers/md/dm-bio-record.h
new file mode 100644 (file)
index 0000000..d3ec217
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef DM_BIO_RECORD_H
+#define DM_BIO_RECORD_H
+
+#include <linux/bio.h>
+
+/*
+ * There are lots of mutable fields in the bio struct that get
+ * changed by the lower levels of the block layer.  Some targets,
+ * such as multipath, may wish to resubmit a bio on error.  The
+ * functions in this file help the target record and restore the
+ * original bio state.
+ */
+struct dm_bio_details {
+       sector_t bi_sector;
+       struct block_device *bi_bdev;
+       unsigned int bi_size;
+       unsigned short bi_idx;
+       unsigned long bi_flags;
+};
+
+static inline void dm_bio_record(struct dm_bio_details *bd, struct bio *bio)
+{
+       bd->bi_sector = bio->bi_sector;
+       bd->bi_bdev = bio->bi_bdev;
+       bd->bi_size = bio->bi_size;
+       bd->bi_idx = bio->bi_idx;
+       bd->bi_flags = bio->bi_flags;
+}
+
+static inline void dm_bio_restore(struct dm_bio_details *bd, struct bio *bio)
+{
+       bio->bi_sector = bd->bi_sector;
+       bio->bi_bdev = bd->bi_bdev;
+       bio->bi_size = bd->bi_size;
+       bio->bi_idx = bd->bi_idx;
+       bio->bi_flags = bd->bi_flags;
+}
+
+#endif
diff --git a/drivers/media/dvb/b2c2/flexcop-dma.c b/drivers/media/dvb/b2c2/flexcop-dma.c
new file mode 100644 (file)
index 0000000..8d27060
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
+ *
+ * flexcop-dma.c - methods for configuring and controlling the DMA of the FlexCop.
+ *
+ * see flexcop.c for copyright information.
+ */
+#include "flexcop.h"
+
+int flexcop_dma_allocate(struct pci_dev *pdev, struct flexcop_dma *dma, u32 size)
+{
+       u8 *tcpu;
+       dma_addr_t tdma;
+
+       if (size % 2) {
+               err("dma buffersize has to be even.");
+               return -EINVAL;
+       }
+
+       if ((tcpu = pci_alloc_consistent(pdev, size, &tdma)) != NULL) {
+               dma->pdev = pdev;
+               dma->cpu_addr0 = tcpu;
+               dma->dma_addr0 = tdma;
+               dma->cpu_addr1 = tcpu + size/2;
+               dma->dma_addr1 = tdma + size/2;
+               dma->size = size/2;
+               return 0;
+       }
+       return -ENOMEM;
+}
+EXPORT_SYMBOL(flexcop_dma_allocate);
+
+void flexcop_dma_free(struct flexcop_dma *dma)
+{
+       pci_free_consistent(dma->pdev, dma->size*2,dma->cpu_addr0, dma->dma_addr0);
+       memset(dma,0,sizeof(struct flexcop_dma));
+}
+EXPORT_SYMBOL(flexcop_dma_free);
+
+int flexcop_dma_control_timer_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff)
+{
+       flexcop_ibi_value v = fc->read_ibi_reg(fc,ctrl_208);
+
+       if (no & FC_DMA_1)
+               v.ctrl_208.DMA1_Timer_Enable_sig = onoff;
+
+       if (no & FC_DMA_2)
+               v.ctrl_208.DMA2_Timer_Enable_sig = onoff;
+
+       fc->write_ibi_reg(fc,ctrl_208,v);
+       return 0;
+}
+EXPORT_SYMBOL(flexcop_dma_control_timer_irq);
+
+int flexcop_dma_control_size_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff)
+{
+       flexcop_ibi_value v = fc->read_ibi_reg(fc,ctrl_208);
+
+       if (no & FC_DMA_1)
+               v.ctrl_208.DMA1_IRQ_Enable_sig = onoff;
+
+       if (no & FC_DMA_2)
+               v.ctrl_208.DMA2_IRQ_Enable_sig = onoff;
+
+       fc->write_ibi_reg(fc,ctrl_208,v);
+       return 0;
+}
+EXPORT_SYMBOL(flexcop_dma_control_size_irq);
+
+int flexcop_dma_control_packet_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff)
+{
+       flexcop_ibi_value v = fc->read_ibi_reg(fc,ctrl_208);
+
+       if (no & FC_DMA_1)
+               v.ctrl_208.DMA1_Size_IRQ_Enable_sig = onoff;
+
+       if (no & FC_DMA_2)
+               v.ctrl_208.DMA2_Size_IRQ_Enable_sig = onoff;
+
+       fc->write_ibi_reg(fc,ctrl_208,v);
+       return 0;
+}
+EXPORT_SYMBOL(flexcop_dma_control_packet_irq);
+
+int flexcop_dma_config(struct flexcop_device *fc, struct flexcop_dma *dma, flexcop_dma_index_t dma_idx,flexcop_dma_addr_index_t index)
+{
+
+       flexcop_ibi_value v0x0,v0x4,v0xc;
+       v0x0.raw = v0x4.raw = v0xc.raw = 0;
+
+       v0x0.dma_0x0.dma_address0        = dma->dma_addr0 >> 2;
+       v0xc.dma_0xc.dma_address1        = dma->dma_addr1 >> 2;
+       v0x4.dma_0x4_write.dma_addr_size = dma->size / 4;
+
+       if (index & FC_DMA_SUBADDR_0)
+               v0x0.dma_0x0.dma_0start = 1;
+
+       if (index & FC_DMA_SUBADDR_1)
+               v0xc.dma_0xc.dma_1start = 1;
+
+       if (dma_idx & FC_DMA_1) {
+               fc->write_ibi_reg(fc,dma1_000,v0x0);
+               fc->write_ibi_reg(fc,dma1_004,v0x4);
+               fc->write_ibi_reg(fc,dma1_00c,v0xc);
+       } else { /* (dma_idx & FC_DMA_2) */
+               fc->write_ibi_reg(fc,dma2_010,v0x0);
+               fc->write_ibi_reg(fc,dma2_014,v0x4);
+               fc->write_ibi_reg(fc,dma2_01c,v0xc);
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(flexcop_dma_config);
+
+static int flexcop_dma_remap(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, int onoff)
+{
+       flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_00c : dma2_01c;
+       flexcop_ibi_value v = fc->read_ibi_reg(fc,r);
+       v.dma_0xc.remap_enable = onoff;
+       fc->write_ibi_reg(fc,r,v);
+       return 0;
+}
+
+/* 1 cycles = 1.97 msec */
+int flexcop_dma_config_timer(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, u8 cycles)
+{
+       flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_004 : dma2_014;
+       flexcop_ibi_value v = fc->read_ibi_reg(fc,r);
+
+       flexcop_dma_remap(fc,dma_idx,0);
+
+       v.dma_0x4_write.dmatimer = cycles >> 1;
+       fc->write_ibi_reg(fc,r,v);
+       return 0;
+}
+EXPORT_SYMBOL(flexcop_dma_config_timer);
+
+int flexcop_dma_config_packet_count(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, u8 packets)
+{
+       flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_004 : dma2_014;
+       flexcop_ibi_value v = fc->read_ibi_reg(fc,r);
+
+       flexcop_dma_remap(fc,dma_idx,1);
+
+       v.dma_0x4_remap.DMA_maxpackets = packets;
+       fc->write_ibi_reg(fc,r,v);
+       return 0;
+}
+EXPORT_SYMBOL(flexcop_dma_config_packet_count);
diff --git a/drivers/media/dvb/b2c2/flexcop-eeprom.c b/drivers/media/dvb/b2c2/flexcop-eeprom.c
new file mode 100644 (file)
index 0000000..bbcf070
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
+ *
+ * flexcop-eeprom.c - eeprom access methods (currently only MAC address reading is used)
+ *
+ * see flexcop.c for copyright information.
+ */
+#include "flexcop.h"
+
+#if 0
+/*EEPROM (Skystar2 has one "24LC08B" chip on board) */
+static int eeprom_write(struct adapter *adapter, u16 addr, u8 *buf, u16 len)
+{
+       return flex_i2c_write(adapter, 0x20000000, 0x50, addr, buf, len);
+}
+
+static int eeprom_lrc_write(struct adapter *adapter, u32 addr, u32 len, u8 *wbuf, u8 *rbuf, int retries)
+{
+       int i;
+
+       for (i = 0; i < retries; i++) {
+               if (eeprom_write(adapter, addr, wbuf, len) == len) {
+                       if (eeprom_lrc_read(adapter, addr, len, rbuf, retries) == 1)
+                               return 1;
+               }
+       }
+
+       return 0;
+}
+
+/* These functions could be used to unlock SkyStar2 cards. */
+
+static int eeprom_writeKey(struct adapter *adapter, u8 *key, u32 len)
+{
+       u8 rbuf[20];
+       u8 wbuf[20];
+
+       if (len != 16)
+               return 0;
+
+       memcpy(wbuf, key, len);
+
+       wbuf[16] = 0;
+       wbuf[17] = 0;
+       wbuf[18] = 0;
+       wbuf[19] = calc_lrc(wbuf, 19);
+
+       return eeprom_lrc_write(adapter, 0x3e4, 20, wbuf, rbuf, 4);
+}
+
+static int eeprom_readKey(struct adapter *adapter, u8 *key, u32 len)
+{
+       u8 buf[20];
+
+       if (len != 16)
+               return 0;
+
+       if (eeprom_lrc_read(adapter, 0x3e4, 20, buf, 4) == 0)
+               return 0;
+
+       memcpy(key, buf, len);
+
+       return 1;
+}
+
+static char eeprom_set_mac_addr(struct adapter *adapter, char type, u8 *mac)
+{
+       u8 tmp[8];
+
+       if (type != 0) {
+               tmp[0] = mac[0];
+               tmp[1] = mac[1];
+               tmp[2] = mac[2];
+               tmp[3] = mac[5];
+               tmp[4] = mac[6];
+               tmp[5] = mac[7];
+
+       } else {
+
+               tmp[0] = mac[0];
+               tmp[1] = mac[1];
+               tmp[2] = mac[2];
+               tmp[3] = mac[3];
+               tmp[4] = mac[4];
+               tmp[5] = mac[5];
+       }
+
+       tmp[6] = 0;
+       tmp[7] = calc_lrc(tmp, 7);
+
+       if (eeprom_write(adapter, 0x3f8, tmp, 8) == 8)
+               return 1;
+
+       return 0;
+}
+
+static int flexcop_eeprom_read(struct flexcop_device *fc, u16 addr, u8 *buf, u16 len)
+{
+       return fc->i2c_request(fc,FC_READ,FC_I2C_PORT_EEPROM,0x50,addr,buf,len);
+}
+
+#endif
+
+static u8 calc_lrc(u8 *buf, int len)
+{
+       int i;
+       u8 sum = 0;
+       for (i = 0; i < len; i++)
+               sum = sum ^ buf[i];
+       return sum;
+}
+
+static int flexcop_eeprom_request(struct flexcop_device *fc, flexcop_access_op_t op, u16 addr, u8 *buf, u16 len, int retries)
+{
+       int i,ret = 0;
+       u8 chipaddr =  0x50 | ((addr >> 8) & 3);
+       for (i = 0; i < retries; i++)
+               if ((ret = fc->i2c_request(fc,op,FC_I2C_PORT_EEPROM,chipaddr,addr & 0xff,buf,len)) == 0)
+                       break;
+       return ret;
+}
+
+static int flexcop_eeprom_lrc_read(struct flexcop_device *fc, u16 addr, u8 *buf, u16 len, int retries)
+{
+       int ret = flexcop_eeprom_request(fc,FC_READ,addr,buf,len,retries);
+       if (ret == 0)
+               if (calc_lrc(buf, len - 1) != buf[len - 1])
+                       ret = -EINVAL;
+       return ret;
+}
+
+/* JJ's comment about extended == 1: it is not presently used anywhere but was
+ * added to the low-level functions for possible support of EUI64
+ */
+int flexcop_eeprom_check_mac_addr(struct flexcop_device *fc, int extended)
+{
+       u8 buf[8];
+       int ret = 0;
+
+       if ((ret = flexcop_eeprom_lrc_read(fc,0x3f8,buf,8,4)) == 0) {
+               if (extended != 0) {
+                       err("TODO: extended (EUI64) MAC addresses aren't completely supported yet");
+                       ret = -EINVAL;
+/*                     memcpy(fc->dvb_adapter.proposed_mac,buf,3);
+                       mac[3] = 0xfe;
+                       mac[4] = 0xff;
+                       memcpy(&fc->dvb_adapter.proposed_mac[3],&buf[5],3); */
+               } else
+                       memcpy(fc->dvb_adapter.proposed_mac,buf,6);
+       }
+       return ret;
+}
+EXPORT_SYMBOL(flexcop_eeprom_check_mac_addr);
diff --git a/drivers/media/dvb/b2c2/flexcop-hw-filter.c b/drivers/media/dvb/b2c2/flexcop-hw-filter.c
new file mode 100644 (file)
index 0000000..2baf43d
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
+ *
+ * flexcop-hw-filter.c - pid and mac address filtering and corresponding control functions.
+ *
+ * see flexcop.c for copyright information.
+ */
+#include "flexcop.h"
+
+static void flexcop_rcv_data_ctrl(struct flexcop_device *fc, int onoff)
+{
+       flexcop_set_ibi_value(ctrl_208,Rcv_Data_sig,onoff);
+}
+
+void flexcop_smc_ctrl(struct flexcop_device *fc, int onoff)
+{
+       flexcop_set_ibi_value(ctrl_208,SMC_Enable_sig,onoff);
+}
+
+void flexcop_null_filter_ctrl(struct flexcop_device *fc, int onoff)
+{
+       flexcop_set_ibi_value(ctrl_208,Null_filter_sig,onoff);
+}
+
+void flexcop_set_mac_filter(struct flexcop_device *fc, u8 mac[6])
+{
+       flexcop_ibi_value v418,v41c;
+       v41c = fc->read_ibi_reg(fc,mac_address_41c);
+
+       v418.mac_address_418.MAC1 = mac[0];
+       v418.mac_address_418.MAC2 = mac[1];
+       v418.mac_address_418.MAC3 = mac[2];
+       v418.mac_address_418.MAC6 = mac[3];
+       v41c.mac_address_41c.MAC7 = mac[4];
+       v41c.mac_address_41c.MAC8 = mac[5];
+
+       fc->write_ibi_reg(fc,mac_address_418,v418);
+       fc->write_ibi_reg(fc,mac_address_41c,v41c);
+}
+
+void flexcop_mac_filter_ctrl(struct flexcop_device *fc, int onoff)
+{
+       flexcop_set_ibi_value(ctrl_208,MAC_filter_Mode_sig,onoff);
+}
+
+static void flexcop_pid_group_filter(struct flexcop_device *fc, u16 pid, u16 mask)
+{
+       /* index_reg_310.extra_index_reg need to 0 or 7 to work */
+       flexcop_ibi_value v30c;
+       v30c.pid_filter_30c_ext_ind_0_7.Group_PID = pid;
+       v30c.pid_filter_30c_ext_ind_0_7.Group_mask = mask;
+       fc->write_ibi_reg(fc,pid_filter_30c,v30c);
+}
+
+static void flexcop_pid_group_filter_ctrl(struct flexcop_device *fc, int onoff)
+{
+       flexcop_set_ibi_value(ctrl_208,Mask_filter_sig,onoff);
+}
+
+/* this fancy define reduces the code size of the quite similar PID controlling of
+ * the first 6 PIDs
+ */
+
+#define pid_ctrl(vregname,field,enablefield,trans_field,transval) \
+       flexcop_ibi_value vpid = fc->read_ibi_reg(fc, vregname), \
+                                         v208 = fc->read_ibi_reg(fc, ctrl_208); \
+\
+       vpid.vregname.field = onoff ? pid : 0x1fff; \
+       vpid.vregname.trans_field = transval; \
+       v208.ctrl_208.enablefield = onoff; \
+\
+       fc->write_ibi_reg(fc,vregname,vpid); \
+       fc->write_ibi_reg(fc,ctrl_208,v208);
+
+static void flexcop_pid_Stream1_PID_ctrl(struct flexcop_device *fc, u16 pid, int onoff)
+{
+       pid_ctrl(pid_filter_300,Stream1_PID,Stream1_filter_sig,Stream1_trans,0);
+}
+
+static void flexcop_pid_Stream2_PID_ctrl(struct flexcop_device *fc, u16 pid, int onoff)
+{
+       pid_ctrl(pid_filter_300,Stream2_PID,Stream2_filter_sig,Stream2_trans,0);
+}
+
+static void flexcop_pid_PCR_PID_ctrl(struct flexcop_device *fc, u16 pid, int onoff)
+{
+       pid_ctrl(pid_filter_304,PCR_PID,PCR_filter_sig,PCR_trans,0);
+}
+
+static void flexcop_pid_PMT_PID_ctrl(struct flexcop_device *fc, u16 pid, int onoff)
+{
+       pid_ctrl(pid_filter_304,PMT_PID,PMT_filter_sig,PMT_trans,0);
+}
+
+static void flexcop_pid_EMM_PID_ctrl(struct flexcop_device *fc, u16 pid, int onoff)
+{
+       pid_ctrl(pid_filter_308,EMM_PID,EMM_filter_sig,EMM_trans,0);
+}
+
+static void flexcop_pid_ECM_PID_ctrl(struct flexcop_device *fc, u16 pid, int onoff)
+{
+       pid_ctrl(pid_filter_308,ECM_PID,ECM_filter_sig,ECM_trans,0);
+}
+
+static void flexcop_pid_control(struct flexcop_device *fc, int index, u16 pid,int onoff)
+{
+       if (pid == 0x2000)
+               return;
+
+       deb_ts("setting pid: %5d %04x at index %d '%s'\n",pid,pid,index,onoff ? "on" : "off");
+
+       /* We could use bit magic here to reduce source code size.
+        * I decided against it, but to use the real register names */
+       switch (index) {
+               case 0: flexcop_pid_Stream1_PID_ctrl(fc,pid,onoff); break;
+               case 1: flexcop_pid_Stream2_PID_ctrl(fc,pid,onoff); break;
+               case 2: flexcop_pid_PCR_PID_ctrl(fc,pid,onoff); break;
+               case 3: flexcop_pid_PMT_PID_ctrl(fc,pid,onoff); break;
+               case 4: flexcop_pid_EMM_PID_ctrl(fc,pid,onoff); break;
+               case 5: flexcop_pid_ECM_PID_ctrl(fc,pid,onoff); break;
+               default:
+                       if (fc->has_32_hw_pid_filter && index < 38) {
+                               flexcop_ibi_value vpid,vid;
+
+                               /* set the index */
+                               vid = fc->read_ibi_reg(fc,index_reg_310);
+                               vid.index_reg_310.index_reg = index - 6;
+                               fc->write_ibi_reg(fc,index_reg_310, vid);
+
+                               vpid = fc->read_ibi_reg(fc,pid_n_reg_314);
+                               vpid.pid_n_reg_314.PID = onoff ? pid : 0x1fff;
+                               vpid.pid_n_reg_314.PID_enable_bit = onoff;
+                               fc->write_ibi_reg(fc,pid_n_reg_314, vpid);
+                       }
+                       break;
+       }
+}
+
+static int flexcop_toggle_fullts_streaming(struct flexcop_device *fc,int onoff)
+{
+       if (fc->fullts_streaming_state != onoff) {
+               deb_ts("%s full TS transfer\n",onoff ? "enabling" : "disabling");
+               flexcop_pid_group_filter(fc, 0, 0x1fe0 * (!onoff));
+               flexcop_pid_group_filter_ctrl(fc,onoff);
+               fc->fullts_streaming_state = onoff;
+       }
+       return 0;
+}
+
+int flexcop_pid_feed_control(struct flexcop_device *fc, struct dvb_demux_feed *dvbdmxfeed, int onoff)
+{
+       int max_pid_filter = 6 + fc->has_32_hw_pid_filter*32;
+
+       fc->feedcount += onoff ? 1 : -1;
+       if (dvbdmxfeed->index >= max_pid_filter)
+               fc->extra_feedcount += onoff ? 1 : -1;
+
+       /* toggle complete-TS-streaming when:
+        * - pid_filtering is not enabled and it is the first or last feed requested
+        * - pid_filtering is enabled,
+        *   - but the number of requested feeds is exceeded
+        *   - or the requested pid is 0x2000 */
+
+       if (!fc->pid_filtering && fc->feedcount == onoff)
+               flexcop_toggle_fullts_streaming(fc,onoff);
+
+       if (fc->pid_filtering) {
+               flexcop_pid_control(fc,dvbdmxfeed->index,dvbdmxfeed->pid,onoff);
+
+               if (fc->extra_feedcount > 0)
+                       flexcop_toggle_fullts_streaming(fc,1);
+               else if (dvbdmxfeed->pid == 0x2000)
+                       flexcop_toggle_fullts_streaming(fc,onoff);
+               else
+                       flexcop_toggle_fullts_streaming(fc,0);
+       }
+
+       /* if it was the first or last feed request change the stream-status */
+       if (fc->feedcount == onoff) {
+               flexcop_rcv_data_ctrl(fc,onoff);
+               if (fc->stream_control)
+                       fc->stream_control(fc,onoff);
+       }
+
+       return 0;
+}
+
+void flexcop_hw_filter_init(struct flexcop_device *fc)
+{
+       int i;
+       flexcop_ibi_value v;
+       for (i = 0; i < 6 + 32*fc->has_32_hw_pid_filter; i++)
+               flexcop_pid_control(fc,i,0x1fff,0);
+
+       flexcop_pid_group_filter(fc, 0, 0x1fe0);
+       flexcop_pid_group_filter_ctrl(fc,0);
+
+       v = fc->read_ibi_reg(fc,pid_filter_308);
+       v.pid_filter_308.EMM_filter_4 = 1;
+       v.pid_filter_308.EMM_filter_6 = 0;
+       fc->write_ibi_reg(fc,pid_filter_308,v);
+
+       flexcop_null_filter_ctrl(fc, 1);
+}
diff --git a/drivers/media/dvb/b2c2/flexcop-misc.c b/drivers/media/dvb/b2c2/flexcop-misc.c
new file mode 100644 (file)
index 0000000..19e06da
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
+ *
+ * flexcop-misc.c - miscellaneous functions.
+ *
+ * see flexcop.c for copyright information.
+ */
+#include "flexcop.h"
+
+void flexcop_determine_revision(struct flexcop_device *fc)
+{
+       flexcop_ibi_value v = fc->read_ibi_reg(fc,misc_204);
+
+       switch (v.misc_204.Rev_N_sig_revision_hi) {
+               case 0x2:
+                       deb_info("found a FlexCopII.\n");
+                       fc->rev = FLEXCOP_II;
+                       break;
+               case 0x3:
+                       deb_info("found a FlexCopIIb.\n");
+                       fc->rev = FLEXCOP_IIB;
+                       break;
+               case 0x0:
+                       deb_info("found a FlexCopIII.\n");
+                       fc->rev = FLEXCOP_III;
+                       break;
+               default:
+                       err("unkown FlexCop Revision: %x. Please report the linux-dvb@linuxtv.org.",v.misc_204.Rev_N_sig_revision_hi);
+                       break;
+       }
+
+       if ((fc->has_32_hw_pid_filter = v.misc_204.Rev_N_sig_caps))
+               deb_info("this FlexCop has the additional 32 hardware pid filter.\n");
+       else
+               deb_info("this FlexCop has only the 6 basic main hardware pid filter.\n");
+       /* bus parts have to decide if hw pid filtering is used or not. */
+}
+
+const char *flexcop_revision_names[] = {
+       "Unkown chip",
+       "FlexCopII",
+       "FlexCopIIb",
+       "FlexCopIII",
+};
+
+const char *flexcop_device_names[] = {
+       "Unkown device",
+       "AirStar 2 DVB-T",
+       "AirStar 2 ATSC",
+       "SkyStar 2 DVB-S",
+       "SkyStar 2 DVB-S (old version)",
+       "CableStar 2 DVB-C",
+};
+
+const char *flexcop_bus_names[] = {
+       "USB",
+       "PCI",
+};
+
+void flexcop_device_name(struct flexcop_device *fc,const char *prefix,const
+               char *suffix)
+{
+       info("%s '%s' at the '%s' bus controlled by a '%s' %s",prefix,
+                       flexcop_device_names[fc->dev_type],flexcop_bus_names[fc->bus_type],
+                       flexcop_revision_names[fc->rev],suffix);
+}
diff --git a/drivers/media/dvb/b2c2/flexcop-reg.h b/drivers/media/dvb/b2c2/flexcop-reg.h
new file mode 100644 (file)
index 0000000..5e131be
--- /dev/null
@@ -0,0 +1,701 @@
+/*
+ * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
+ *
+ * flexcop-reg.h - register abstraction for FlexCopII, FlexCopIIb and FlexCopIII
+ *
+ * see flexcop.c for copyright information.
+ */
+#ifndef __FLEXCOP_REG_H__
+#define __FLEXCOP_REG_H__
+
+
+typedef enum {
+       FLEXCOP_UNK = 0,
+       FLEXCOP_II,
+       FLEXCOP_IIB,
+       FLEXCOP_III,
+} flexcop_revision_t;
+
+extern const char *flexcop_revision_names[];
+
+typedef enum {
+       FC_UNK = 0,
+       FC_AIR_DVB,
+       FC_AIR_ATSC,
+       FC_SKY,
+       FC_SKY_OLD,
+       FC_CABLE,
+} flexcop_device_type_t;
+
+typedef enum {
+       FC_USB = 0,
+       FC_PCI,
+} flexcop_bus_t;
+
+extern const char *flexcop_device_names[];
+
+/* FlexCop IBI Registers */
+
+/* flexcop_ibi_reg - a huge union representing the register structure */
+typedef union {
+       u32 raw;
+
+/* DMA 0x000 to 0x01c
+ * DMA1 0x000 to 0x00c
+ * DMA2 0x010 to 0x01c
+ */
+       struct {
+               u32 dma_0start        : 1;   /* set: data will be delivered to dma1_address0 */
+        u32 dma_0No_update    : 1;   /* set: dma1_cur_address will be updated, unset: no update */
+        u32 dma_address0      :30;   /* physical/virtual host memory address0 DMA */
+       } dma_0x0;
+
+       struct {
+               u32 DMA_maxpackets    : 8;   /* (remapped) PCI DMA1 Packet Count Interrupt. This variable
+                                                                               is able to be read and written while bit(1) of register
+                                                                               0x00c (remap_enable) is set. This variable represents
+                                                                               the number of packets that will be transmitted to the PCI
+                                                                               host using PCI DMA1 before an interrupt to the PCI is
+                                                                               asserted. This functionality may be enabled using bit(20)
+                                                                               of register 0x208. N=0 disables the IRQ. */
+               u32 dma_addr_size     :24;   /* size of memory buffer in DWORDs (bytesize / 4) for DMA */
+       } dma_0x4_remap;
+
+       struct {
+               u32 dma1timer         : 7;   /* reading PCI DMA1 timer ... when remap_enable is 0 */
+               u32 unused            : 1;
+               u32 dma_addr_size     :24;
+       } dma_0x4_read;
+
+       struct {
+               u32 unused            : 1;
+               u32 dmatimer          : 7;   /* writing PCI DMA1 timer ... when remap_enable is 0 */
+               u32 dma_addr_size     :24;
+       } dma_0x4_write;
+
+       struct {
+               u32 unused            : 2;
+               u32 dma_cur_addr      :30;   /* current physical host memory address pointer for DMA */
+       } dma_0x8;
+
+       struct {
+               u32 dma_1start        : 1;   /* set: data will be delivered to dma_address1, when dma_address0 is full */
+               u32 remap_enable      : 1;   /* remap enable for 0x0x4(7:0) */
+               u32 dma_address1      :30;   /* Physical/virtual address 1 on DMA */
+       } dma_0xc;
+
+/* Two-wire Serial Master and Clock 0x100-0x110 */
+       struct {
+//             u32 slave_transmitter : 1;   /* ???*/
+               u32 chipaddr          : 7;   /* two-line serial address of the target slave */
+               u32 reserved1         : 1;
+               u32 baseaddr          : 8;   /* address of the location of the read/write operation */
+               u32 data1_reg         : 8;   /* first byte in two-line serial read/write operation */
+               u32 working_start     : 1;  /* when doing a write operation this indicator is 0 when ready
+                                                                         * set to 1 when doing a write operation */
+               u32 twoWS_rw          : 1;   /* read/write indicator (1 = read, 0 write) */
+               u32 total_bytes       : 2;   /* number of data bytes in each two-line serial transaction (0 = 1 byte, 11 = 4byte)*/
+               u32 twoWS_port_reg    : 2;   /* port selection: 01 - Front End/Demod, 10 - EEPROM, 11 - Tuner */
+               u32 no_base_addr_ack_error : 1;   /* writing: write-req: frame is produced w/o baseaddr, read-req: read-cycles w/o
+                                                                         * preceding address assignment write frame
+                                                                         * ACK_ERROR = 1 when no ACK from slave in the last transaction */
+               u32 st_done           : 1;   /* indicator for transaction is done */
+       } tw_sm_c_100;
+
+       struct {
+               u32 data2_reg         : 8;   /* 2nd data byte */
+               u32 data3_reg         : 8;   /* 3rd data byte */
+               u32 data4_reg         : 8;   /* 4th data byte */
+               u32 exlicit_stops     : 1;   /* when set, transactions are produced w/o trailing STOP flag, then send isolated STOP flags */
+               u32 force_stop        : 1;   /* isolated stop flag */
+               u32 unused            : 6;
+       } tw_sm_c_104;
+
+/* Clock. The register allows the FCIII to convert an incoming Master clock
+ * (MCLK) signal into a lower frequency clock through the use of a LowCounter
+ * (TLO) and a High- Counter (THI). The time counts for THI and TLO are
+ * measured in MCLK; each count represents 4 MCLK input clock cycles.
+ *
+ * The default output for port #1 is set for Front End Demod communication. (0x108)
+ * The default output for port #2 is set for EEPROM communication. (0x10c)
+ * The default output for port #3 is set for Tuner communication. (0x110)
+ */
+       struct {
+               u32 thi1              : 6;   /* Thi for port #1 (def: 100110b; 38) */
+               u32 reserved1         : 2;
+               u32 tlo1              : 5;   /* Tlo for port #1 (def: 11100b; 28) */
+               u32 reserved2         :19;
+       } tw_sm_c_108;
+
+       struct {
+               u32 thi1              : 6;   /* Thi for port #2 (def: 111001b; 57) */
+               u32 reserved1         : 2;
+               u32 tlo1              : 5;   /* Tlo for port #2 (def: 11100b; 28) */
+               u32 reserved2         :19;
+       } tw_sm_c_10c;
+
+       struct {
+               u32 thi1              : 6;   /* Thi for port #3 (def: 111001b; 57) */
+               u32 reserved1         : 2;
+               u32 tlo1              : 5;   /* Tlo for port #3 (def: 11100b; 28) */
+               u32 reserved2         :19;
+       } tw_sm_c_110;
+
+/* LNB Switch Frequency 0x200
+ * Clock that creates the LNB switch tone. The default is set to have a fixed
+ * low output (not oscillating) to the LNB_CTL line.
+ */
+       struct {
+               u32 LNB_CTLHighCount_sig :15; /* It is the number of pre-scaled clock cycles that will be low. */
+               u32 LNB_CTLLowCount_sig  :15; /* For example, to obtain a 22KHz output given a 45 Mhz Master
+                                                                               Clock signal (MCLK), set PreScalar=01 and LowCounter value to 0x1ff. */
+               u32 LNB_CTLPrescaler_sig : 2; /* pre-scaler divides MCLK: 00 (no division), 01 by 2, 10 by 4, 11 by 12 */
+       } lnb_switch_freq_200;
+
+/* ACPI, Peripheral Reset, LNB Polarity
+ * ACPI power conservation mode, LNB polarity selection (low or high voltage),
+ * and peripheral reset.
+ */
+       struct {
+               u32 ACPI1_sig         : 1;   /* turn of the power of tuner and LNB, not implemented in FCIII */
+               u32 ACPI3_sig         : 1;   /* turn of power of the complete satelite receiver board (except FCIII) */
+               u32 LNB_L_H_sig       : 1;   /* low or high voltage for LNB. (0 = low, 1 = high) */
+               u32 Per_reset_sig     : 1;   /* misc. init reset (default: 1), to reset set to low and back to high */
+               u32 reserved          :20;
+               u32 Rev_N_sig_revision_hi : 4;/* 0xc in case of FCIII */
+               u32 Rev_N_sig_reserved1 : 2;
+               u32 Rev_N_sig_caps    : 1;   /* if 1, FCIII has 32 PID- and MAC-filters and is capable of IP multicast */
+               u32 Rev_N_sig_reserved2 : 1;
+       } misc_204;
+
+/* Control and Status 0x208 to 0x21c */
+/* Gross enable and disable control */
+       struct {
+               u32 Stream1_filter_sig : 1;  /* Stream1 PID filtering */
+               u32 Stream2_filter_sig : 1;  /* Stream2 PID filtering */
+               u32 PCR_filter_sig    : 1;   /* PCR PID filter */
+               u32 PMT_filter_sig    : 1;   /* PMT PID filter */
+
+               u32 EMM_filter_sig    : 1;   /* EMM PID filter */
+               u32 ECM_filter_sig    : 1;   /* ECM PID filter */
+               u32 Null_filter_sig   : 1;   /* Filters null packets, PID=0x1fff. */
+               u32 Mask_filter_sig   : 1;   /* mask PID filter */
+
+               u32 WAN_Enable_sig    : 1;   /* WAN output line through V8 memory space is activated. */
+               u32 WAN_CA_Enable_sig : 1;   /* not in FCIII */
+               u32 CA_Enable_sig     : 1;   /* not in FCIII */
+               u32 SMC_Enable_sig    : 1;   /* CI stream data (CAI) goes directly to the smart card intf (opposed IBI 0x600 or SC-cmd buf). */
+
+               u32 Per_CA_Enable_sig : 1;   /* not in FCIII */
+               u32 Multi2_Enable_sig : 1;   /* ? */
+               u32 MAC_filter_Mode_sig : 1; /* (MAC_filter_enable) Globally enables MAC filters for Net PID filteres. */
+               u32 Rcv_Data_sig      : 1;   /* PID filtering module enable. When this bit is a one, the PID filter will
+                                                                               examine and process packets according to all other (individual) PID
+                                                                               filtering controls. If it a zero, no packet processing of any kind will
+                                                                               take place. All data from the tuner will be thrown away. */
+
+               u32 DMA1_IRQ_Enable_sig : 1; /* When set, a DWORD counter is enabled on PCI DMA1 that asserts the PCI
+                                                                         * interrupt after the specified count for filling the buffer. */
+               u32 DMA1_Timer_Enable_sig : 1; /* When set, a timer is enabled on PCI DMA1 that asserts the PCI interrupt
+                                                                                       after a specified amount of time. */
+               u32 DMA2_IRQ_Enable_sig : 1;   /* same as DMA1_IRQ_Enable_sig but for DMA2 */
+               u32 DMA2_Timer_Enable_sig : 1;   /* same as DMA1_Timer_Enable_sig but for DMA2 */
+
+               u32 DMA1_Size_IRQ_Enable_sig : 1; /* When set, a packet count detector is enabled on PCI DMA1 that asserts the PCI interrupt. */
+               u32 DMA2_Size_IRQ_Enable_sig : 1; /* When set, a packet count detector is enabled on PCI DMA2 that asserts the PCI interrupt. */
+               u32 Mailbox_from_V8_Enable_sig: 1; /* When set, writes to the mailbox register produce an interrupt to the
+                                                                                       PCI host to indicate that mailbox data is available. */
+
+               u32 unused            : 9;
+       } ctrl_208;
+
+/* General status. When a PCI interrupt occurs, this register is read to
+ * discover the reason for the interrupt.
+ */
+       struct {
+               u32 DMA1_IRQ_Status   : 1;   /* When set(1) the DMA1 counter had generated an IRQ. Read Only. */
+               u32 DMA1_Timer_Status : 1;   /* When set(1) the DMA1 timer had generated an IRQ. Read Only. */
+               u32 DMA2_IRQ_Status   : 1;   /* When set(1) the DMA2 counter had generated an IRQ. Read Only. */
+               u32 DMA2_Timer_Status : 1;   /* When set(1) the DMA2 timer had generated an IRQ. Read Only. */
+               u32 DMA1_Size_IRQ_Status : 1; /* (Read only). This register is read after an interrupt to */
+               u32 DMA2_Size_IRQ_Status : 1; /* find out why we had an IRQ. Reading this register will clear this bit. Packet count*/
+               u32 Mailbox_from_V8_Status_sig: 1; /* Same as above. Reading this register will clear this bit. */
+               u32 Data_receiver_error : 1; /* 1 indicate an error in the receiver Front End (Tuner module) */
+               u32 Continuity_error_flag : 1;   /* 1 indicates a continuity error in the TS stream. */
+               u32 LLC_SNAP_FLAG_set : 1;   /* 1 indicates that the LCC_SNAP_FLAG was set. */
+               u32 Transport_Error   : 1;   /*  When set indicates that an unexpected packet was received. */
+               u32 reserved          :21;
+       } irq_20c;
+
+
+/* Software reset register */
+       struct {
+               u32 reset_blocks      : 8;   /* Enabled when Block_reset_enable = 0xB2 and 0x208 bits 15:8 = 0x00.
+                                                                               Each bit location represents a 0x100 block of registers. Writing
+                                                                               a one in a bit location resets that block of registers and the logic
+                                                                               that it controls. */
+               u32 Block_reset_enable : 8;  /* This variable is set to 0xB2 when the register is written. */
+               u32 Special_controls  :16;   /* Asserts Reset_V8 => 0xC258; Turns on pci encryption => 0xC25A;
+                                                                               Turns off pci encryption => 0xC259 Note: pci_encryption default
+                                                                               at power-up is ON. */
+       } sw_reset_210;
+
+       struct {
+               u32 vuart_oe_sig      : 1;   /* When clear, the V8 processor has sole control of the serial UART
+                                                                               (RS-232 Smart Card interface). When set, the IBI interface
+                                                                               defined by register 0x600 controls the serial UART. */
+               u32 v2WS_oe_sig       : 1;   /* When clear, the V8 processor has direct control of the Two-line
+                                                                               Serial Master EEPROM target. When set, the Two-line Serial Master
+                                                                               EEPROM target interface is controlled by IBI register 0x100. */
+               u32 halt_V8_sig       : 1;   /* When set, contiguous wait states are applied to the V8-space
+                                                                               bus masters. Once this signal is cleared, normal V8-space
+                                                                               operations resume. */
+               u32 section_pkg_enable_sig: 1; /* When set, this signal enables the front end translation circuitry
+                                                                                 to process section packed transport streams. */
+               u32 s2p_sel_sig       : 1;   /* Serial to parallel conversion. When set, polarized transport data
+                                                                               within the FlexCop3 front end circuitry is converted from a serial
+                                                                               stream into parallel data before downstream processing otherwise
+                                                                               interprets the data. */
+               u32 unused1           : 3;
+               u32 polarity_PS_CLK_sig: 1;  /* This signal is used to invert the input polarity of the tranport
+                                                                               stream CLOCK signal before any processing occurs on the transport
+                                                                               stream within FlexCop3. */
+               u32 polarity_PS_VALID_sig: 1; /* This signal is used to invert the input polarity of the tranport
+                                                                               stream VALID signal before any processing occurs on the transport
+                                                                               stream within FlexCop3. */
+               u32 polarity_PS_SYNC_sig: 1; /* This signal is used to invert the input polarity of the tranport
+                                                                               stream SYNC signal before any processing occurs on the transport
+                                                                               stream within FlexCop3. */
+               u32 polarity_PS_ERR_sig: 1;  /* This signal is used to invert the input polarity of the tranport
+                                                                               stream ERROR signal before any processing occurs on the transport
+                                                                               stream within FlexCop3. */
+               u32 unused2           :20;
+       } misc_214;
+
+/* Mailbox from V8 to host */
+       struct {
+               u32 Mailbox_from_V8   :32;   /* When this register is written by either the V8 processor or by an
+                                                                               end host, an interrupt is generated to the PCI host to indicate
+                                                                               that mailbox data is available. Reading register 20c will clear
+                                                                               the IRQ. */
+       } mbox_v8_to_host_218;
+
+/* Mailbox from host to v8 Mailbox_to_V8
+ * Mailbox_to_V8 mailbox storage register
+ * used to send messages from PCI to V8. Writing to this register will send an
+ * IRQ to the V8. Then it can read the data from here. Reading this register
+ * will clear the IRQ. If the V8 is halted and bit 31 of this register is set,
+ * then this register is used instead as a direct interface to access the
+ * V8space memory.
+ */
+       struct {
+               u32 sysramaccess_data : 8;   /* Data byte written or read from the specified address in V8 SysRAM. */
+               u32 sysramaccess_addr :15;   /* 15 bit address used to access V8 Sys-RAM. */
+               u32 unused            : 7;
+               u32 sysramaccess_write: 1;   /* Write flag used to latch data into the V8 SysRAM. */
+               u32 sysramaccess_busmuster: 1; /* Setting this bit when the V8 is halted at 0x214 Bit(2) allows
+                                                                                 this IBI register interface to directly drive the V8-space memory. */
+       } mbox_host_to_v8_21c;
+
+
+/* PIDs, Translation Bit, SMC Filter Select 0x300 to 0x31c */
+       struct {
+               u32 Stream1_PID       :13;   /* Primary use is receiving Net data, so these 13 bits normally
+                                                                               hold the PID value for the desired network stream. */
+               u32 Stream1_trans     : 1;   /* When set, Net translation will take place for Net data ferried in TS packets. */
+               u32 MAC_Multicast_filter : 1;   /* When clear, multicast MAC filtering is not allowed for Stream1 and PID_n filters. */
+               u32 debug_flag_pid_saved : 1;
+               u32 Stream2_PID       :13;   /* 13 bits for Stream 2 PID filter value. General use. */
+               u32 Stream2_trans     : 1;   /* When set Tables/CAI translation will take place for the data ferried in
+                                                                               Stream2_PID TS packets. */
+               u32 debug_flag_write_status00 : 1;
+               u32 debug_fifo_problem : 1;
+       } pid_filter_300;
+
+       struct {
+               u32 PCR_PID           :13;   /* PCR stream PID filter value. Primary use is Program Clock Reference stream filtering. */
+               u32 PCR_trans         : 1;   /* When set, Tables/CAI translation will take place for these packets. */
+               u32 debug_overrun3    : 1;
+               u32 debug_overrun2    : 1;
+               u32 PMT_PID           :13;   /* stream PID filter value. Primary use is Program Management Table segment filtering. */
+               u32 PMT_trans         : 1;   /* When set, Tables/CAI translation will take place for these packets. */
+               u32 reserved          : 2;
+       } pid_filter_304;
+
+       struct {
+               u32 EMM_PID           :13;   /* EMM PID filter value. Primary use is Entitlement Management Messaging for
+                                                                               conditional access-related data. */
+               u32 EMM_trans         : 1;   /* When set, Tables/CAI translation will take place for these packets. */
+               u32 EMM_filter_4      : 1;   /* When set will pass only EMM data possessing the same ID code as the
+                                                                               first four bytes (32 bits) of the end-user s 6-byte Smart Card ID number Select */
+               u32 EMM_filter_6      : 1;   /* When set will pass only EMM data possessing the same 6-byte code as the end-users
+                                                                               complete 6-byte Smart Card ID number. */
+               u32 ECM_PID           :13;   /* ECM PID filter value. Primary use is Entitlement Control Messaging for conditional
+                                                                               access-related data. */
+               u32 ECM_trans         : 1;   /* When set, Tables/CAI translation will take place for these packets. */
+               u32 reserved          : 2;
+       } pid_filter_308;
+
+       struct {
+               u32 Group_PID     :13;   /* PID value for group filtering. */
+               u32 Group_trans   : 1;   /* When set, Tables/CAI translation will take place for these packets. */
+               u32 unused1       : 2;
+               u32 Group_mask    :13;   /* Mask value used in logical "and" equation that defines group filtering */
+               u32 unused2       : 3;
+       } pid_filter_30c_ext_ind_0_7;
+
+       struct {
+               u32 net_master_read :17;
+               u32 unused        :15;
+       } pid_filter_30c_ext_ind_1;
+
+       struct {
+               u32 net_master_write :17;
+               u32 unused        :15;
+       } pid_filter_30c_ext_ind_2;
+
+       struct {
+               u32 next_net_master_write :17;
+               u32 unused        :15;
+       } pid_filter_30c_ext_ind_3;
+
+       struct {
+               u32 unused1       : 1;
+               u32 state_write   :10;
+               u32 reserved1     : 6;   /* default: 000100 */
+               u32 stack_read    :10;
+               u32 reserved2     : 5;   /* default: 00100 */
+       } pid_filter_30c_ext_ind_4;
+
+       struct {
+               u32 stack_cnt     :10;
+               u32 unused        :22;
+       } pid_filter_30c_ext_ind_5;
+
+       struct {
+               u32 pid_fsm_save_reg0 : 2;
+               u32 pid_fsm_save_reg1 : 2;
+               u32 pid_fsm_save_reg2 : 2;
+               u32 pid_fsm_save_reg3 : 2;
+               u32 pid_fsm_save_reg4 : 2;
+               u32 pid_fsm_save_reg300 : 2;
+               u32 write_status1 : 2;
+               u32 write_status4 : 2;
+               u32 data_size_reg :12;
+               u32 unused        : 4;
+       } pid_filter_30c_ext_ind_6;
+
+       struct {
+               u32 index_reg         : 5;   /* (Index pointer) Points at an internal PIDn register. A binary code
+                                                                               representing one of 32 internal PIDn registers as well as its
+                                                                               corresponding internal MAC_lown register. */
+               u32 extra_index_reg   : 3;   /* This vector is used to select between sets of debug signals routed to register 0x30c. */
+               u32 AB_select         : 1;   /* Used in conjunction with 0x31c. read/write to the MAC_highA or MAC_highB register
+                                                                               0=MAC_highB register, 1=MAC_highA */
+               u32 pass_alltables    : 1;   /* 1=Net packets are not filtered against the Network Table ID found in register 0x400.
+                                                                               All types of networks (DVB, ATSC, ISDB) are passed. */
+               u32 unused            :22;
+       } index_reg_310;
+
+       struct {
+               u32 PID               :13;   /* PID value */
+               u32 PID_trans         : 1;   /* translation will take place for packets filtered */
+               u32 PID_enable_bit    : 1;   /* When set this PID filter is enabled */
+               u32 reserved          :17;
+       } pid_n_reg_314;
+
+       struct {
+               u32 A4_byte           : 8;
+               u32 A5_byte           : 8;
+               u32 A6_byte           : 8;
+               u32 Enable_bit        : 1;   /* enabled (1) or disabled (1) */
+               u32 HighAB_bit        : 1;   /* use MAC_highA (1) or MAC_highB (0) as MSB */
+               u32 reserved          : 6;
+       } mac_low_reg_318;
+
+       struct {
+               u32 A1_byte           : 8;
+               u32 A2_byte           : 8;
+               u32 A3_byte           : 8;
+               u32 reserved          : 8;
+       } mac_high_reg_31c;
+
+/* Table, SMCID,MACDestination Filters 0x400 to 0x41c */
+       struct {
+               u32 reserved          :16;
+#define fc_data_Tag_ID_DVB  0x3e
+#define fc_data_Tag_ID_ATSC 0x3f
+#define fc_data_Tag_ID_IDSB 0x8b
+               u32 data_Tag_ID       :16;
+       } data_tag_400;
+
+       struct {
+               u32 Card_IDbyte6      : 8;
+               u32 Card_IDbyte5      : 8;
+               u32 Card_IDbyte4      : 8;
+               u32 Card_IDbyte3      : 8;
+       } card_id_408;
+
+       struct {
+               u32 Card_IDbyte2      : 8;
+               u32 Card_IDbyte1      : 8;
+       } card_id_40c;
+
+       /* holding the unique mac address of the receiver which houses the FlexCopIII */
+       struct {
+               u32 MAC1              : 8;
+               u32 MAC2              : 8;
+               u32 MAC3              : 8;
+               u32 MAC6              : 8;
+       } mac_address_418;
+
+       struct {
+               u32 MAC7              : 8;
+               u32 MAC8              : 8;
+               u32 reserved          : 16;
+       } mac_address_41c;
+
+       struct {
+               u32 transmitter_data_byte : 8;
+               u32 ReceiveDataReady  : 1;
+               u32 ReceiveByteFrameError: 1;
+               u32 txbuffempty       : 1;
+               u32 reserved          :21;
+       } ci_600;
+
+       struct {
+               u32 pi_d              : 8;
+               u32 pi_ha             :20;
+               u32 pi_rw             : 1;
+               u32 pi_component_reg  : 3;
+       } pi_604;
+
+       struct {
+               u32 serialReset       : 1;
+               u32 oncecycle_read    : 1;
+               u32 Timer_Read_req    : 1;
+               u32 Timer_Load_req    : 1;
+               u32 timer_data        : 7;
+               u32 unused            : 1; /* ??? not mentioned in data book */
+               u32 Timer_addr        : 5;
+               u32 reserved          : 3;
+               u32 pcmcia_a_mod_pwr_n : 1;
+               u32 pcmcia_b_mod_pwr_n : 1;
+               u32 config_Done_stat  : 1;
+               u32 config_Init_stat  : 1;
+               u32 config_Prog_n     : 1;
+               u32 config_wr_n       : 1;
+               u32 config_cs_n       : 1;
+               u32 config_cclk       : 1;
+               u32 pi_CiMax_IRQ_n    : 1;
+               u32 pi_timeout_status : 1;
+               u32 pi_wait_n         : 1;
+               u32 pi_busy_n         : 1;
+       } pi_608;
+
+       struct {
+               u32 PID               :13;
+               u32 key_enable        : 1;
+#define fc_key_code_default 0x1
+#define fc_key_code_even    0x2
+#define fc_key_code_odd     0x3
+               u32 key_code          : 2;
+               u32 key_array_col     : 3;
+               u32 key_array_row     : 5;
+               u32 dvb_en            : 1; /* 0=TS bypasses the Descrambler */
+               u32 rw_flag           : 1;
+               u32 reserved          : 6;
+       } dvb_reg_60c;
+
+/* SRAM and Output Destination 0x700 to 0x714 */
+       struct {
+               u32 sram_addr         :15;
+               u32 sram_rw           : 1;   /* 0=write, 1=read */
+               u32 sram_data         : 8;
+               u32 sc_xfer_bit       : 1;
+               u32 reserved1         : 3;
+               u32 oe_pin_reg        : 1;
+               u32 ce_pin_reg        : 1;
+               u32 reserved2         : 1;
+               u32 start_sram_ibi    : 1;
+       } sram_ctrl_reg_700;
+
+       struct {
+               u32 net_addr_read     :16;
+               u32 net_addr_write    :16;
+       } net_buf_reg_704;
+
+       struct {
+               u32 cai_read          :11;
+               u32 reserved1         : 5;
+               u32 cai_write         :11;
+               u32 reserved2         : 6;
+               u32 cai_cnt           : 4;
+       } cai_buf_reg_708;
+
+       struct {
+               u32 cao_read          :11;
+               u32 reserved1         : 5;
+               u32 cap_write         :11;
+               u32 reserved2         : 6;
+               u32 cao_cnt           : 4;
+       } cao_buf_reg_70c;
+
+       struct {
+               u32 media_read        :11;
+               u32 reserved1         : 5;
+               u32 media_write       :11;
+               u32 reserved2         : 6;
+               u32 media_cnt         : 4;
+       } media_buf_reg_710;
+
+       struct {
+               u32 NET_Dest          : 2;
+               u32 CAI_Dest          : 2;
+               u32 CAO_Dest          : 2;
+               u32 MEDIA_Dest        : 2;
+               u32 net_ovflow_error  : 1;
+               u32 media_ovflow_error : 1;
+               u32 cai_ovflow_error  : 1;
+               u32 cao_ovflow_error  : 1;
+               u32 ctrl_usb_wan      : 1;
+               u32 ctrl_sramdma      : 1;
+               u32 ctrl_maximumfill  : 1;
+               u32 reserved          :17;
+       } sram_dest_reg_714;
+
+       struct {
+               u32 net_cnt           :12;
+               u32 reserved1         : 4;
+               u32 net_addr_read     : 1;
+               u32 reserved2         : 3;
+               u32 net_addr_write    : 1;
+               u32 reserved3         :11;
+       } net_buf_reg_718;
+
+       struct {
+               u32 wan_speed_sig     : 2;
+               u32 reserved1         : 6;
+               u32 wan_wait_state    : 8;
+               u32 sram_chip         : 2;
+               u32 sram_memmap       : 2;
+               u32 reserved2         : 4;
+               u32 wan_pkt_frame     : 4;
+               u32 reserved3         : 4;
+       } wan_ctrl_reg_71c;
+} flexcop_ibi_value;
+
+extern flexcop_ibi_value ibi_zero;
+
+typedef enum {
+       FC_I2C_PORT_DEMOD  = 1,
+       FC_I2C_PORT_EEPROM = 2,
+       FC_I2C_PORT_TUNER  = 3,
+} flexcop_i2c_port_t;
+
+typedef enum {
+       FC_WRITE = 0,
+       FC_READ  = 1,
+} flexcop_access_op_t;
+
+typedef enum {
+       FC_SRAM_DEST_NET   = 1,
+       FC_SRAM_DEST_CAI   = 2,
+       FC_SRAM_DEST_CAO   = 4,
+       FC_SRAM_DEST_MEDIA = 8
+} flexcop_sram_dest_t;
+
+typedef enum {
+       FC_SRAM_DEST_TARGET_WAN_USB = 0,
+       FC_SRAM_DEST_TARGET_DMA1    = 1,
+       FC_SRAM_DEST_TARGET_DMA2    = 2,
+       FC_SRAM_DEST_TARGET_FC3_CA  = 3
+} flexcop_sram_dest_target_t;
+
+typedef enum {
+       FC_SRAM_2_32KB  = 0, /*  64KB */
+       FC_SRAM_1_32KB  = 1, /*  32KB - default fow FCII */
+       FC_SRAM_1_128KB = 2, /* 128KB */
+       FC_SRAM_1_48KB  = 3, /*  48KB - default for FCIII */
+} flexcop_sram_type_t;
+
+typedef enum {
+       FC_WAN_SPEED_4MBITS  = 0,
+       FC_WAN_SPEED_8MBITS  = 1,
+       FC_WAN_SPEED_12MBITS = 2,
+       FC_WAN_SPEED_16MBITS = 3,
+} flexcop_wan_speed_t;
+
+typedef enum {
+       FC_DMA_1 = 1,
+       FC_DMA_2 = 2,
+} flexcop_dma_index_t;
+
+typedef enum {
+       FC_DMA_SUBADDR_0 = 1,
+       FC_DMA_SUBADDR_1 = 2,
+} flexcop_dma_addr_index_t;
+
+/* names of the particular registers */
+typedef enum {
+       dma1_000            = 0x000,
+       dma1_004            = 0x004,
+       dma1_008            = 0x008,
+       dma1_00c            = 0x00c,
+       dma2_010            = 0x010,
+       dma2_014            = 0x014,
+       dma2_018            = 0x018,
+       dma2_01c            = 0x01c,
+
+       tw_sm_c_100         = 0x100,
+       tw_sm_c_104         = 0x104,
+       tw_sm_c_108         = 0x108,
+       tw_sm_c_10c         = 0x10c,
+       tw_sm_c_110         = 0x110,
+
+       lnb_switch_freq_200 = 0x200,
+       misc_204            = 0x204,
+       ctrl_208            = 0x208,
+       irq_20c             = 0x20c,
+       sw_reset_210        = 0x210,
+       misc_214            = 0x214,
+       mbox_v8_to_host_218 = 0x218,
+       mbox_host_to_v8_21c = 0x21c,
+
+       pid_filter_300      = 0x300,
+       pid_filter_304      = 0x304,
+       pid_filter_308      = 0x308,
+       pid_filter_30c      = 0x30c,
+       index_reg_310       = 0x310,
+       pid_n_reg_314       = 0x314,
+       mac_low_reg_318     = 0x318,
+       mac_high_reg_31c    = 0x31c,
+
+       data_tag_400        = 0x400,
+       card_id_408         = 0x408,
+       card_id_40c         = 0x40c,
+       mac_address_418     = 0x418,
+       mac_address_41c     = 0x41c,
+
+       ci_600              = 0x600,
+       pi_604              = 0x604,
+       pi_608              = 0x608,
+       dvb_reg_60c         = 0x60c,
+
+       sram_ctrl_reg_700   = 0x700,
+       net_buf_reg_704     = 0x704,
+       cai_buf_reg_708     = 0x708,
+       cao_buf_reg_70c     = 0x70c,
+       media_buf_reg_710   = 0x710,
+       sram_dest_reg_714   = 0x714,
+       net_buf_reg_718     = 0x718,
+       wan_ctrl_reg_71c    = 0x71c,
+} flexcop_ibi_register;
+
+#define flexcop_set_ibi_value(reg,attr,val) { \
+       flexcop_ibi_value v = fc->read_ibi_reg(fc,reg); \
+       v.reg.attr = val; \
+       fc->write_ibi_reg(fc,reg,v); \
+}
+
+#endif
diff --git a/drivers/media/dvb/b2c2/flexcop-sram.c b/drivers/media/dvb/b2c2/flexcop-sram.c
new file mode 100644 (file)
index 0000000..01570ec
--- /dev/null
@@ -0,0 +1,403 @@
+/*
+ * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
+ *
+ * flexcop-sram.c - functions for controlling the SRAM.
+ *
+ * see flexcop.c for copyright information.
+ */
+#include "flexcop.h"
+
+static void flexcop_sram_set_chip (struct flexcop_device *fc, flexcop_sram_type_t type)
+{
+       flexcop_set_ibi_value(wan_ctrl_reg_71c,sram_chip,type);
+}
+
+int flexcop_sram_init(struct flexcop_device *fc)
+{
+       switch (fc->rev) {
+               case FLEXCOP_II:
+               case FLEXCOP_IIB:
+                       flexcop_sram_set_chip(fc,FC_SRAM_1_32KB);
+                       break;
+               case FLEXCOP_III:
+                       flexcop_sram_set_chip(fc,FC_SRAM_1_48KB);
+                       break;
+               default:
+                       return -EINVAL;
+       }
+       return 0;
+}
+
+int flexcop_sram_set_dest(struct flexcop_device *fc, flexcop_sram_dest_t dest, flexcop_sram_dest_target_t target)
+{
+       flexcop_ibi_value v;
+
+       v = fc->read_ibi_reg(fc,sram_dest_reg_714);
+
+       if (fc->rev != FLEXCOP_III && target == FC_SRAM_DEST_TARGET_FC3_CA) {
+               err("SRAM destination target to available on FlexCopII(b)\n");
+               return -EINVAL;
+       }
+
+       deb_sram("sram dest: %x target: %x\n",dest, target);
+
+       if (dest & FC_SRAM_DEST_NET)
+               v.sram_dest_reg_714.NET_Dest = target;
+       if (dest & FC_SRAM_DEST_CAI)
+               v.sram_dest_reg_714.CAI_Dest = target;
+       if (dest & FC_SRAM_DEST_CAO)
+               v.sram_dest_reg_714.CAO_Dest = target;
+       if (dest & FC_SRAM_DEST_MEDIA)
+               v.sram_dest_reg_714.MEDIA_Dest = target;
+
+       fc->write_ibi_reg(fc,sram_dest_reg_714,v);
+       udelay(1000); /* TODO delay really necessary */
+
+       return 0;
+}
+EXPORT_SYMBOL(flexcop_sram_set_dest);
+
+void flexcop_wan_set_speed(struct flexcop_device *fc, flexcop_wan_speed_t s)
+{
+       flexcop_set_ibi_value(wan_ctrl_reg_71c,wan_speed_sig,s);
+}
+EXPORT_SYMBOL(flexcop_wan_set_speed);
+
+void flexcop_sram_ctrl(struct flexcop_device *fc, int usb_wan, int sramdma, int maximumfill)
+{
+       flexcop_ibi_value v = fc->read_ibi_reg(fc,sram_dest_reg_714);
+       v.sram_dest_reg_714.ctrl_usb_wan = usb_wan;
+       v.sram_dest_reg_714.ctrl_sramdma = sramdma;
+       v.sram_dest_reg_714.ctrl_maximumfill = maximumfill;
+       fc->write_ibi_reg(fc,sram_dest_reg_714,v);
+}
+EXPORT_SYMBOL(flexcop_sram_ctrl);
+
+#if 0
+static void flexcop_sram_write(struct adapter *adapter, u32 bank, u32 addr, u8 *buf, u32 len)
+{
+       int i, retries;
+       u32 command;
+
+       for (i = 0; i < len; i++) {
+               command = bank | addr | 0x04000000 | (*buf << 0x10);
+
+               retries = 2;
+
+               while (((read_reg_dw(adapter, 0x700) & 0x80000000) != 0) && (retries > 0)) {
+                       mdelay(1);
+                       retries--;
+               };
+
+               if (retries == 0)
+                       printk("%s: SRAM timeout\n", __FUNCTION__);
+
+               write_reg_dw(adapter, 0x700, command);
+
+               buf++;
+               addr++;
+       }
+}
+
+static void flex_sram_read(struct adapter *adapter, u32 bank, u32 addr, u8 *buf, u32 len)
+{
+       int i, retries;
+       u32 command, value;
+
+       for (i = 0; i < len; i++) {
+               command = bank | addr | 0x04008000;
+
+               retries = 10000;
+
+               while (((read_reg_dw(adapter, 0x700) & 0x80000000) != 0) && (retries > 0)) {
+                       mdelay(1);
+                       retries--;
+               };
+
+               if (retries == 0)
+                       printk("%s: SRAM timeout\n", __FUNCTION__);
+
+               write_reg_dw(adapter, 0x700, command);
+
+               retries = 10000;
+
+               while (((read_reg_dw(adapter, 0x700) & 0x80000000) != 0) && (retries > 0)) {
+                       mdelay(1);
+                       retries--;
+               };
+
+               if (retries == 0)
+                       printk("%s: SRAM timeout\n", __FUNCTION__);
+
+               value = read_reg_dw(adapter, 0x700) >> 0x10;
+
+               *buf = (value & 0xff);
+
+               addr++;
+               buf++;
+       }
+}
+
+static void sram_write_chunk(struct adapter *adapter, u32 addr, u8 *buf, u16 len)
+{
+       u32 bank;
+
+       bank = 0;
+
+       if (adapter->dw_sram_type == 0x20000) {
+               bank = (addr & 0x18000) << 0x0d;
+       }
+
+       if (adapter->dw_sram_type == 0x00000) {
+               if ((addr >> 0x0f) == 0)
+                       bank = 0x20000000;
+               else
+                       bank = 0x10000000;
+       }
+
+       flex_sram_write(adapter, bank, addr & 0x7fff, buf, len);
+}
+
+static void sram_read_chunk(struct adapter *adapter, u32 addr, u8 *buf, u16 len)
+{
+       u32 bank;
+
+       bank = 0;
+
+       if (adapter->dw_sram_type == 0x20000) {
+               bank = (addr & 0x18000) << 0x0d;
+       }
+
+       if (adapter->dw_sram_type == 0x00000) {
+               if ((addr >> 0x0f) == 0)
+                       bank = 0x20000000;
+               else
+                       bank = 0x10000000;
+       }
+
+       flex_sram_read(adapter, bank, addr & 0x7fff, buf, len);
+}
+
+static void sram_read(struct adapter *adapter, u32 addr, u8 *buf, u32 len)
+{
+       u32 length;
+
+       while (len != 0) {
+               length = len;
+
+               // check if the address range belongs to the same
+               // 32K memory chip. If not, the data is read from
+               // one chip at a time.
+               if ((addr >> 0x0f) != ((addr + len - 1) >> 0x0f)) {
+                       length = (((addr >> 0x0f) + 1) << 0x0f) - addr;
+               }
+
+               sram_read_chunk(adapter, addr, buf, length);
+
+               addr = addr + length;
+               buf = buf + length;
+               len = len - length;
+       }
+}
+
+static void sram_write(struct adapter *adapter, u32 addr, u8 *buf, u32 len)
+{
+       u32 length;
+
+       while (len != 0) {
+               length = len;
+
+               // check if the address range belongs to the same
+               // 32K memory chip. If not, the data is written to
+               // one chip at a time.
+               if ((addr >> 0x0f) != ((addr + len - 1) >> 0x0f)) {
+                       length = (((addr >> 0x0f) + 1) << 0x0f) - addr;
+               }
+
+               sram_write_chunk(adapter, addr, buf, length);
+
+               addr = addr + length;
+               buf = buf + length;
+               len = len - length;
+       }
+}
+
+static void sram_set_size(struct adapter *adapter, u32 mask)
+{
+       write_reg_dw(adapter, 0x71c, (mask | (~0x30000 & read_reg_dw(adapter, 0x71c))));
+}
+
+static void sram_init(struct adapter *adapter)
+{
+       u32 tmp;
+
+       tmp = read_reg_dw(adapter, 0x71c);
+
+       write_reg_dw(adapter, 0x71c, 1);
+
+       if (read_reg_dw(adapter, 0x71c) != 0) {
+               write_reg_dw(adapter, 0x71c, tmp);
+
+               adapter->dw_sram_type = tmp & 0x30000;
+
+               ddprintk("%s: dw_sram_type = %x\n", __FUNCTION__, adapter->dw_sram_type);
+
+       } else {
+
+               adapter->dw_sram_type = 0x10000;
+
+               ddprintk("%s: dw_sram_type = %x\n", __FUNCTION__, adapter->dw_sram_type);
+       }
+
+       /* return value is never used? */
+/*     return adapter->dw_sram_type; */
+}
+
+static int sram_test_location(struct adapter *adapter, u32 mask, u32 addr)
+{
+       u8 tmp1, tmp2;
+
+       dprintk("%s: mask = %x, addr = %x\n", __FUNCTION__, mask, addr);
+
+       sram_set_size(adapter, mask);
+       sram_init(adapter);
+
+       tmp2 = 0xa5;
+       tmp1 = 0x4f;
+
+       sram_write(adapter, addr, &tmp2, 1);
+       sram_write(adapter, addr + 4, &tmp1, 1);
+
+       tmp2 = 0;
+
+       mdelay(20);
+
+       sram_read(adapter, addr, &tmp2, 1);
+       sram_read(adapter, addr, &tmp2, 1);
+
+       dprintk("%s: wrote 0xa5, read 0x%2x\n", __FUNCTION__, tmp2);
+
+       if (tmp2 != 0xa5)
+               return 0;
+
+       tmp2 = 0x5a;
+       tmp1 = 0xf4;
+
+       sram_write(adapter, addr, &tmp2, 1);
+       sram_write(adapter, addr + 4, &tmp1, 1);
+
+       tmp2 = 0;
+
+       mdelay(20);
+
+       sram_read(adapter, addr, &tmp2, 1);
+       sram_read(adapter, addr, &tmp2, 1);
+
+       dprintk("%s: wrote 0x5a, read 0x%2x\n", __FUNCTION__, tmp2);
+
+       if (tmp2 != 0x5a)
+               return 0;
+
+       return 1;
+}
+
+static u32 sram_length(struct adapter *adapter)
+{
+       if (adapter->dw_sram_type == 0x10000)
+               return 32768;   //  32K
+       if (adapter->dw_sram_type == 0x00000)
+               return 65536;   //  64K
+       if (adapter->dw_sram_type == 0x20000)
+               return 131072;  // 128K
+
+       return 32768;           // 32K
+}
+
+/* FlexcopII can work with 32K, 64K or 128K of external SRAM memory.
+    - for 128K there are 4x32K chips at bank 0,1,2,3.
+    - for  64K there are 2x32K chips at bank 1,2.
+    - for  32K there is one 32K chip at bank 0.
+
+   FlexCop works only with one bank at a time. The bank is selected
+   by bits 28-29 of the 0x700 register.
+
+   bank 0 covers addresses 0x00000-0x07fff
+   bank 1 covers addresses 0x08000-0x0ffff
+   bank 2 covers addresses 0x10000-0x17fff
+   bank 3 covers addresses 0x18000-0x1ffff
+*/
+
+static int flexcop_sram_detect(struct flexcop_device *fc)
+{
+       flexcop_ibi_value r208,r71c_0,vr71c_1;
+
+       r208 = fc->read_ibi_reg(fc, ctrl_208);
+       fc->write_ibi_reg(fc, ctrl_208, ibi_zero);
+
+       r71c_0 = fc->read_ibi_reg(fc, wan_ctrl_reg_71c);
+
+       write_reg_dw(adapter, 0x71c, 1);
+
+       tmp3 = read_reg_dw(adapter, 0x71c);
+
+       dprintk("%s: tmp3 = %x\n", __FUNCTION__, tmp3);
+
+       write_reg_dw(adapter, 0x71c, tmp2);
+
+       // check for internal SRAM ???
+       tmp3--;
+       if (tmp3 != 0) {
+               sram_set_size(adapter, 0x10000);
+               sram_init(adapter);
+               write_reg_dw(adapter, 0x208, tmp);
+
+               dprintk("%s: sram size = 32K\n", __FUNCTION__);
+
+               return 32;
+       }
+
+       if (sram_test_location(adapter, 0x20000, 0x18000) != 0) {
+               sram_set_size(adapter, 0x20000);
+               sram_init(adapter);
+               write_reg_dw(adapter, 0x208, tmp);
+
+               dprintk("%s: sram size = 128K\n", __FUNCTION__);
+
+               return 128;
+       }
+
+       if (sram_test_location(adapter, 0x00000, 0x10000) != 0) {
+               sram_set_size(adapter, 0x00000);
+               sram_init(adapter);
+               write_reg_dw(adapter, 0x208, tmp);
+
+               dprintk("%s: sram size = 64K\n", __FUNCTION__);
+
+               return 64;
+       }
+
+       if (sram_test_location(adapter, 0x10000, 0x00000) != 0) {
+               sram_set_size(adapter, 0x10000);
+               sram_init(adapter);
+               write_reg_dw(adapter, 0x208, tmp);
+
+               dprintk("%s: sram size = 32K\n", __FUNCTION__);
+
+               return 32;
+       }
+
+       sram_set_size(adapter, 0x10000);
+       sram_init(adapter);
+       write_reg_dw(adapter, 0x208, tmp);
+
+       dprintk("%s: SRAM detection failed. Set to 32K \n", __FUNCTION__);
+
+       return 0;
+}
+
+static void sll_detect_sram_size(struct adapter *adapter)
+{
+       sram_detect_for_flex2(adapter);
+}
+
+#endif
diff --git a/drivers/media/dvb/b2c2/flexcop-usb.h b/drivers/media/dvb/b2c2/flexcop-usb.h
new file mode 100644 (file)
index 0000000..630e647
--- /dev/null
@@ -0,0 +1,119 @@
+#ifndef __FLEXCOP_USB_H_INCLUDED__
+#define __FLEXCOP_USB_H_INCLUDED__
+
+#include <linux/usb.h>
+
+/* transfer parameters */
+#define B2C2_USB_FRAMES_PER_ISO                4
+#define B2C2_USB_NUM_ISO_URB           4
+
+#define B2C2_USB_CTRL_PIPE_IN          usb_rcvctrlpipe(fc_usb->udev,0)
+#define B2C2_USB_CTRL_PIPE_OUT         usb_sndctrlpipe(fc_usb->udev,0)
+#define B2C2_USB_DATA_PIPE                     usb_rcvisocpipe(fc_usb->udev,0x81)
+
+struct flexcop_usb {
+       struct usb_device *udev;
+       struct usb_interface *uintf;
+
+       u8 *iso_buffer;
+       int buffer_size;
+       dma_addr_t dma_addr;
+       struct urb *iso_urb[B2C2_USB_NUM_ISO_URB];
+
+       struct flexcop_device *fc_dev;
+
+       u8 tmp_buffer[1023+190];
+       int tmp_buffer_length;
+};
+
+#if 0
+/* request types TODO What is its use?*/
+typedef enum {
+
+/* something is wrong with this part
+       RTYPE_READ_DW         = (1 << 6),
+       RTYPE_WRITE_DW_1      = (3 << 6),
+       RTYPE_READ_V8_MEMORY  = (6 << 6),
+       RTYPE_WRITE_V8_MEMORY = (7 << 6),
+       RTYPE_WRITE_V8_FLASH  = (8 << 6),
+       RTYPE_GENERIC         = (9 << 6),
+*/
+} flexcop_usb_request_type_t;
+#endif
+
+/* request */
+typedef enum {
+       B2C2_USB_WRITE_V8_MEM = 0x04,
+       B2C2_USB_READ_V8_MEM  = 0x05,
+       B2C2_USB_READ_REG     = 0x08,
+       B2C2_USB_WRITE_REG    = 0x0A,
+/*     B2C2_USB_WRITEREGLO   = 0x0A, */
+       B2C2_USB_WRITEREGHI   = 0x0B,
+       B2C2_USB_FLASH_BLOCK  = 0x10,
+       B2C2_USB_I2C_REQUEST  = 0x11,
+       B2C2_USB_UTILITY      = 0x12,
+} flexcop_usb_request_t;
+
+/* function definition for I2C_REQUEST */
+typedef enum {
+       USB_FUNC_I2C_WRITE       = 0x01,
+       USB_FUNC_I2C_MULTIWRITE  = 0x02,
+       USB_FUNC_I2C_READ        = 0x03,
+       USB_FUNC_I2C_REPEATWRITE = 0x04,
+       USB_FUNC_GET_DESCRIPTOR  = 0x05,
+       USB_FUNC_I2C_REPEATREAD  = 0x06,
+/* DKT 020208 - add this to support special case of DiSEqC */
+       USB_FUNC_I2C_CHECKWRITE  = 0x07,
+       USB_FUNC_I2C_CHECKRESULT = 0x08,
+} flexcop_usb_i2c_function_t;
+
+/*
+ * function definition for UTILITY request 0x12
+ * DKT 020304 - new utility function
+ */
+typedef enum {
+       UTILITY_SET_FILTER          = 0x01,
+       UTILITY_DATA_ENABLE         = 0x02,
+       UTILITY_FLEX_MULTIWRITE     = 0x03,
+       UTILITY_SET_BUFFER_SIZE     = 0x04,
+       UTILITY_FLEX_OPERATOR       = 0x05,
+       UTILITY_FLEX_RESET300_START = 0x06,
+       UTILITY_FLEX_RESET300_STOP  = 0x07,
+       UTILITY_FLEX_RESET300       = 0x08,
+       UTILITY_SET_ISO_SIZE        = 0x09,
+       UTILITY_DATA_RESET          = 0x0A,
+       UTILITY_GET_DATA_STATUS     = 0x10,
+       UTILITY_GET_V8_REG          = 0x11,
+/* DKT 020326 - add function for v1.14 */
+       UTILITY_SRAM_WRITE          = 0x12,
+       UTILITY_SRAM_READ           = 0x13,
+       UTILITY_SRAM_TESTFILL       = 0x14,
+       UTILITY_SRAM_TESTSET        = 0x15,
+       UTILITY_SRAM_TESTVERIFY     = 0x16,
+} flexcop_usb_utility_function_t;
+
+#define B2C2_WAIT_FOR_OPERATION_RW  1*HZ       /* 1 s */
+#define B2C2_WAIT_FOR_OPERATION_RDW 3*HZ       /* 3 s */
+#define B2C2_WAIT_FOR_OPERATION_WDW 1*HZ       /* 1 s */
+
+#define B2C2_WAIT_FOR_OPERATION_V8READ   3*HZ  /* 3 s */
+#define B2C2_WAIT_FOR_OPERATION_V8WRITE  3*HZ  /* 3 s */
+#define B2C2_WAIT_FOR_OPERATION_V8FLASH  3*HZ  /* 3 s */
+
+typedef enum {
+       V8_MEMORY_PAGE_DVB_CI = 0x20,
+       V8_MEMORY_PAGE_DVB_DS = 0x40,
+       V8_MEMORY_PAGE_MULTI2 = 0x60,
+       V8_MEMORY_PAGE_FLASH  = 0x80
+} flexcop_usb_mem_page_t;
+
+#define V8_MEMORY_EXTENDED      (1 << 15)
+
+#define USB_MEM_READ_MAX                32
+#define USB_MEM_WRITE_MAX               1
+#define USB_FLASH_MAX                   8
+
+#define V8_MEMORY_PAGE_SIZE     0x8000      // 32K
+#define V8_MEMORY_PAGE_MASK     0x7FFF
+
+#endif
diff --git a/drivers/media/dvb/b2c2/flexcop.h b/drivers/media/dvb/b2c2/flexcop.h
new file mode 100644 (file)
index 0000000..caa343a
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
+ *
+ * flexcop.h - private header file for all flexcop-chip-source files.
+ *
+ * see flexcop.c for copyright information.
+ */
+#ifndef __FLEXCOP_H__
+#define __FLEXCOP_H___
+
+#define FC_LOG_PREFIX "b2c2-flexcop"
+#include "flexcop-common.h"
+
+extern int b2c2_flexcop_debug;
+
+/* debug */
+#ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG
+#define dprintk(level,args...) \
+       do { if ((b2c2_flexcop_debug & level)) printk(args); } while (0)
+#else
+#define dprintk(level,args...)
+#endif
+
+#define deb_info(args...)  dprintk(0x01,args)
+#define deb_tuner(args...) dprintk(0x02,args)
+#define deb_i2c(args...)   dprintk(0x04,args)
+#define deb_ts(args...)    dprintk(0x08,args)
+#define deb_sram(args...)  dprintk(0x10,args)
+
+#endif
diff --git a/drivers/media/dvb/bt8xx/dst_ca.h b/drivers/media/dvb/bt8xx/dst_ca.h
new file mode 100644 (file)
index 0000000..59cd0dd
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+       CA-driver for TwinHan DST Frontend/Card
+
+       Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, write to the Free Software
+       Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef _DST_CA_H_
+#define _DST_CA_H_
+
+#define RETRIES                        5
+
+
+#define        CA_APP_INFO_ENQUIRY     0x9f8020
+#define        CA_APP_INFO             0x9f8021
+#define        CA_ENTER_MENU           0x9f8022
+#define CA_INFO_ENQUIRY                0x9f8030
+#define        CA_INFO                 0x9f8031
+#define CA_PMT                 0x9f8032
+#define CA_PMT_REPLY           0x9f8033
+
+#define CA_CLOSE_MMI           0x9f8800
+#define CA_DISPLAY_CONTROL     0x9f8801
+#define CA_DISPLAY_REPLY       0x9f8802
+#define CA_TEXT_LAST           0x9f8803
+#define CA_TEXT_MORE           0x9f8804
+#define CA_KEYPAD_CONTROL      0x9f8805
+#define CA_KEYPRESS            0x9f8806
+
+#define CA_ENQUIRY             0x9f8807
+#define CA_ANSWER              0x9f8808
+#define CA_MENU_LAST           0x9f8809
+#define CA_MENU_MORE           0x9f880a
+#define CA_MENU_ANSWER         0x9f880b
+#define CA_LIST_LAST           0x9f880c
+#define CA_LIST_MORE           0x9f880d
+
+
+struct dst_ca_private {
+       struct dst_state *dst;
+       struct dvb_device *dvbdev;
+};
+
+
+#endif
diff --git a/drivers/media/video/mt20xx.c b/drivers/media/video/mt20xx.c
new file mode 100644 (file)
index 0000000..95ad17b
--- /dev/null
@@ -0,0 +1,558 @@
+/*
+ * $Id: mt20xx.c,v 1.4 2005/03/04 09:24:56 kraxel Exp $
+ *
+ * i2c tv tuner chip device driver
+ * controls microtune tuners, mt2032 + mt2050 at the moment.
+ */
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/videodev.h>
+#include <linux/moduleparam.h>
+#include <media/tuner.h>
+
+/* ---------------------------------------------------------------------- */
+
+static unsigned int optimize_vco  = 1;
+module_param(optimize_vco,      int, 0644);
+
+static unsigned int tv_antenna    = 1;
+module_param(tv_antenna,        int, 0644);
+
+static unsigned int radio_antenna = 0;
+module_param(radio_antenna,     int, 0644);
+
+/* ---------------------------------------------------------------------- */
+
+#define MT2032 0x04
+#define MT2030 0x06
+#define MT2040 0x07
+#define MT2050 0x42
+
+static char *microtune_part[] = {
+       [ MT2030 ] = "MT2030",
+       [ MT2032 ] = "MT2032",
+       [ MT2040 ] = "MT2040",
+       [ MT2050 ] = "MT2050",
+};
+
+// IsSpurInBand()?
+static int mt2032_spurcheck(struct i2c_client *c,
+                           int f1, int f2, int spectrum_from,int spectrum_to)
+{
+       struct tuner *t = i2c_get_clientdata(c);
+       int n1=1,n2,f;
+
+       f1=f1/1000; //scale to kHz to avoid 32bit overflows
+       f2=f2/1000;
+       spectrum_from/=1000;
+       spectrum_to/=1000;
+
+       tuner_dbg("spurcheck f1=%d f2=%d  from=%d to=%d\n",
+                 f1,f2,spectrum_from,spectrum_to);
+
+       do {
+           n2=-n1;
+           f=n1*(f1-f2);
+           do {
+               n2--;
+               f=f-f2;
+               tuner_dbg("spurtest n1=%d n2=%d ftest=%d\n",n1,n2,f);
+
+               if( (f>spectrum_from) && (f<spectrum_to))
+                       tuner_dbg("mt2032 spurcheck triggered: %d\n",n1);
+           } while ( (f>(f2-spectrum_to)) || (n2>-5));
+           n1++;
+       } while (n1<5);
+
+       return 1;
+}
+
+static int mt2032_compute_freq(struct i2c_client *c,
+                              unsigned int rfin,
+                              unsigned int if1, unsigned int if2,
+                              unsigned int spectrum_from,
+                              unsigned int spectrum_to,
+                              unsigned char *buf,
+                              int *ret_sel,
+                              unsigned int xogc) //all in Hz
+{
+       struct tuner *t = i2c_get_clientdata(c);
+        unsigned int fref,lo1,lo1n,lo1a,s,sel,lo1freq, desired_lo1,
+               desired_lo2,lo2,lo2n,lo2a,lo2num,lo2freq;
+
+        fref= 5250 *1000; //5.25MHz
+       desired_lo1=rfin+if1;
+
+       lo1=(2*(desired_lo1/1000)+(fref/1000)) / (2*fref/1000);
+        lo1n=lo1/8;
+        lo1a=lo1-(lo1n*8);
+
+        s=rfin/1000/1000+1090;
+
+       if(optimize_vco) {
+               if(s>1890) sel=0;
+               else if(s>1720) sel=1;
+               else if(s>1530) sel=2;
+               else if(s>1370) sel=3;
+               else sel=4; // >1090
+       }
+       else {
+               if(s>1790) sel=0; // <1958
+               else if(s>1617) sel=1;
+               else if(s>1449) sel=2;
+               else if(s>1291) sel=3;
+               else sel=4; // >1090
+       }
+       *ret_sel=sel;
+
+        lo1freq=(lo1a+8*lo1n)*fref;
+
+       tuner_dbg("mt2032: rfin=%d lo1=%d lo1n=%d lo1a=%d sel=%d, lo1freq=%d\n",
+                 rfin,lo1,lo1n,lo1a,sel,lo1freq);
+
+        desired_lo2=lo1freq-rfin-if2;
+        lo2=(desired_lo2)/fref;
+        lo2n=lo2/8;
+        lo2a=lo2-(lo2n*8);
+        lo2num=((desired_lo2/1000)%(fref/1000))* 3780/(fref/1000); //scale to fit in 32bit arith
+        lo2freq=(lo2a+8*lo2n)*fref + lo2num*(fref/1000)/3780*1000;
+
+       tuner_dbg("mt2032: rfin=%d lo2=%d lo2n=%d lo2a=%d num=%d lo2freq=%d\n",
+                 rfin,lo2,lo2n,lo2a,lo2num,lo2freq);
+
+        if(lo1a<0 || lo1a>7 || lo1n<17 ||lo1n>48 || lo2a<0 ||lo2a >7 ||lo2n<17 || lo2n>30) {
+               tuner_info("mt2032: frequency parameters out of range: %d %d %d %d\n",
+                          lo1a, lo1n, lo2a,lo2n);
+                return(-1);
+        }
+
+       mt2032_spurcheck(c, lo1freq, desired_lo2,  spectrum_from, spectrum_to);
+       // should recalculate lo1 (one step up/down)
+
+       // set up MT2032 register map for transfer over i2c
+       buf[0]=lo1n-1;
+       buf[1]=lo1a | (sel<<4);
+       buf[2]=0x86; // LOGC
+       buf[3]=0x0f; //reserved
+       buf[4]=0x1f;
+       buf[5]=(lo2n-1) | (lo2a<<5);
+       if(rfin >400*1000*1000)
+                buf[6]=0xe4;
+        else
+                buf[6]=0xf4; // set PKEN per rev 1.2
+       buf[7]=8+xogc;
+       buf[8]=0xc3; //reserved
+       buf[9]=0x4e; //reserved
+       buf[10]=0xec; //reserved
+       buf[11]=(lo2num&0xff);
+       buf[12]=(lo2num>>8) |0x80; // Lo2RST
+
+       return 0;
+}
+
+static int mt2032_check_lo_lock(struct i2c_client *c)
+{
+       struct tuner *t = i2c_get_clientdata(c);
+       int try,lock=0;
+       unsigned char buf[2];
+
+       for(try=0;try<10;try++) {
+               buf[0]=0x0e;
+               i2c_master_send(c,buf,1);
+               i2c_master_recv(c,buf,1);
+               tuner_dbg("mt2032 Reg.E=0x%02x\n",buf[0]);
+               lock=buf[0] &0x06;
+
+               if (lock==6)
+                       break;
+
+               tuner_dbg("mt2032: pll wait 1ms for lock (0x%2x)\n",buf[0]);
+               udelay(1000);
+       }
+        return lock;
+}
+
+static int mt2032_optimize_vco(struct i2c_client *c,int sel,int lock)
+{
+       struct tuner *t = i2c_get_clientdata(c);
+       unsigned char buf[2];
+       int tad1;
+
+       buf[0]=0x0f;
+       i2c_master_send(c,buf,1);
+       i2c_master_recv(c,buf,1);
+       tuner_dbg("mt2032 Reg.F=0x%02x\n",buf[0]);
+       tad1=buf[0]&0x07;
+
+       if(tad1 ==0) return lock;
+       if(tad1 ==1) return lock;
+
+       if(tad1==2) {
+               if(sel==0)
+                       return lock;
+               else sel--;
+       }
+       else {
+               if(sel<4)
+                       sel++;
+               else
+                       return lock;
+       }
+
+       tuner_dbg("mt2032 optimize_vco: sel=%d\n",sel);
+
+       buf[0]=0x0f;
+       buf[1]=sel;
+        i2c_master_send(c,buf,2);
+       lock=mt2032_check_lo_lock(c);
+       return lock;
+}
+
+
+static void mt2032_set_if_freq(struct i2c_client *c, unsigned int rfin,
+                              unsigned int if1, unsigned int if2,
+                              unsigned int from, unsigned int to)
+{
+       unsigned char buf[21];
+       int lint_try,ret,sel,lock=0;
+       struct tuner *t = i2c_get_clientdata(c);
+
+       tuner_dbg("mt2032_set_if_freq rfin=%d if1=%d if2=%d from=%d to=%d\n",
+                 rfin,if1,if2,from,to);
+
+        buf[0]=0;
+        ret=i2c_master_send(c,buf,1);
+        i2c_master_recv(c,buf,21);
+
+       buf[0]=0;
+       ret=mt2032_compute_freq(c,rfin,if1,if2,from,to,&buf[1],&sel,t->xogc);
+       if (ret<0)
+               return;
+
+        // send only the relevant registers per Rev. 1.2
+        buf[0]=0;
+        ret=i2c_master_send(c,buf,4);
+        buf[5]=5;
+        ret=i2c_master_send(c,buf+5,4);
+        buf[11]=11;
+        ret=i2c_master_send(c,buf+11,3);
+        if(ret!=3)
+               tuner_warn("i2c i/o error: rc == %d (should be 3)\n",ret);
+
+       // wait for PLLs to lock (per manual), retry LINT if not.
+       for(lint_try=0; lint_try<2; lint_try++) {
+               lock=mt2032_check_lo_lock(c);
+
+               if(optimize_vco)
+                       lock=mt2032_optimize_vco(c,sel,lock);
+               if(lock==6) break;
+
+               tuner_dbg("mt2032: re-init PLLs by LINT\n");
+               buf[0]=7;
+               buf[1]=0x80 +8+t->xogc; // set LINT to re-init PLLs
+               i2c_master_send(c,buf,2);
+               mdelay(10);
+               buf[1]=8+t->xogc;
+               i2c_master_send(c,buf,2);
+        }
+
+       if (lock!=6)
+               tuner_warn("MT2032 Fatal Error: PLLs didn't lock.\n");
+
+       buf[0]=2;
+       buf[1]=0x20; // LOGC for optimal phase noise
+       ret=i2c_master_send(c,buf,2);
+       if (ret!=2)
+               tuner_warn("i2c i/o error: rc == %d (should be 2)\n",ret);
+}
+
+
+static void mt2032_set_tv_freq(struct i2c_client *c, unsigned int freq)
+{
+       struct tuner *t = i2c_get_clientdata(c);
+       int if2,from,to;
+
+       // signal bandwidth and picture carrier
+       if (t->std & V4L2_STD_525_60) {
+               // NTSC
+               from = 40750*1000;
+               to   = 46750*1000;
+               if2  = 45750*1000;
+       } else {
+               // PAL
+               from = 32900*1000;
+               to   = 39900*1000;
+               if2  = 38900*1000;
+       }
+
+        mt2032_set_if_freq(c, freq*62500 /* freq*1000*1000/16 */,
+                          1090*1000*1000, if2, from, to);
+}
+
+static void mt2032_set_radio_freq(struct i2c_client *c, unsigned int freq)
+{
+       struct tuner *t = i2c_get_clientdata(c);
+       int if2 = t->radio_if2;
+
+       // per Manual for FM tuning: first if center freq. 1085 MHz
+        mt2032_set_if_freq(c, freq*62500 /* freq*1000*1000/16 */,
+                          1085*1000*1000,if2,if2,if2);
+}
+
+// Initalization as described in "MT203x Programming Procedures", Rev 1.2, Feb.2001
+static int mt2032_init(struct i2c_client *c)
+{
+       struct tuner *t = i2c_get_clientdata(c);
+        unsigned char buf[21];
+        int ret,xogc,xok=0;
+
+       // Initialize Registers per spec.
+        buf[1]=2; // Index to register 2
+        buf[2]=0xff;
+        buf[3]=0x0f;
+        buf[4]=0x1f;
+        ret=i2c_master_send(c,buf+1,4);
+
+        buf[5]=6; // Index register 6
+        buf[6]=0xe4;
+        buf[7]=0x8f;
+        buf[8]=0xc3;
+        buf[9]=0x4e;
+        buf[10]=0xec;
+        ret=i2c_master_send(c,buf+5,6);
+
+        buf[12]=13;  // Index register 13
+        buf[13]=0x32;
+        ret=i2c_master_send(c,buf+12,2);
+
+        // Adjust XOGC (register 7), wait for XOK
+        xogc=7;
+        do {
+               tuner_dbg("mt2032: xogc = 0x%02x\n",xogc&0x07);
+                mdelay(10);
+                buf[0]=0x0e;
+                i2c_master_send(c,buf,1);
+                i2c_master_recv(c,buf,1);
+                xok=buf[0]&0x01;
+                tuner_dbg("mt2032: xok = 0x%02x\n",xok);
+                if (xok == 1) break;
+
+                xogc--;
+                tuner_dbg("mt2032: xogc = 0x%02x\n",xogc&0x07);
+                if (xogc == 3) {
+                        xogc=4; // min. 4 per spec
+                        break;
+                }
+                buf[0]=0x07;
+                buf[1]=0x88 + xogc;
+                ret=i2c_master_send(c,buf,2);
+                if (ret!=2)
+                       tuner_warn("i2c i/o error: rc == %d (should be 2)\n",ret);
+        } while (xok != 1 );
+       t->xogc=xogc;
+
+       t->tv_freq    = mt2032_set_tv_freq;
+       t->radio_freq = mt2032_set_radio_freq;
+        return(1);
+}
+
+static void mt2050_set_antenna(struct i2c_client *c, unsigned char antenna)
+{
+       struct tuner *t = i2c_get_clientdata(c);
+       unsigned char buf[2];
+       int ret;
+
+       buf[0] = 6;
+       buf[1] = antenna ? 0x11 : 0x10;
+       ret=i2c_master_send(c,buf,2);
+       tuner_dbg("mt2050: enabled antenna connector %d\n", antenna);
+}
+
+static void mt2050_set_if_freq(struct i2c_client *c,unsigned int freq, unsigned int if2)
+{
+       struct tuner *t = i2c_get_clientdata(c);
+       unsigned int if1=1218*1000*1000;
+       unsigned int f_lo1,f_lo2,lo1,lo2,f_lo1_modulo,f_lo2_modulo,num1,num2,div1a,div1b,div2a,div2b;
+       int ret;
+       unsigned char buf[6];
+
+       tuner_dbg("mt2050_set_if_freq freq=%d if1=%d if2=%d\n",
+                 freq,if1,if2);
+
+       f_lo1=freq+if1;
+       f_lo1=(f_lo1/1000000)*1000000;
+
+       f_lo2=f_lo1-freq-if2;
+       f_lo2=(f_lo2/50000)*50000;
+
+       lo1=f_lo1/4000000;
+       lo2=f_lo2/4000000;
+
+       f_lo1_modulo= f_lo1-(lo1*4000000);
+       f_lo2_modulo= f_lo2-(lo2*4000000);
+
+       num1=4*f_lo1_modulo/4000000;
+       num2=4096*(f_lo2_modulo/1000)/4000;
+
+       // todo spurchecks
+
+       div1a=(lo1/12)-1;
+       div1b=lo1-(div1a+1)*12;
+
+       div2a=(lo2/8)-1;
+       div2b=lo2-(div2a+1)*8;
+
+       if (tuner_debug > 1) {
+               tuner_dbg("lo1 lo2 = %d %d\n", lo1, lo2);
+               tuner_dbg("num1 num2 div1a div1b div2a div2b= %x %x %x %x %x %x\n",
+                         num1,num2,div1a,div1b,div2a,div2b);
+       }
+
+       buf[0]=1;
+       buf[1]= 4*div1b + num1;
+       if(freq<275*1000*1000) buf[1] = buf[1]|0x80;
+
+       buf[2]=div1a;
+       buf[3]=32*div2b + num2/256;
+       buf[4]=num2-(num2/256)*256;
+       buf[5]=div2a;
+       if(num2!=0) buf[5]=buf[5]|0x40;
+
+       if (tuner_debug > 1) {
+               int i;
+               tuner_dbg("bufs is: ");
+               for(i=0;i<6;i++)
+                       printk("%x ",buf[i]);
+               printk("\n");
+       }
+
+       ret=i2c_master_send(c,buf,6);
+        if (ret!=6)
+               tuner_warn("i2c i/o error: rc == %d (should be 6)\n",ret);
+}
+
+static void mt2050_set_tv_freq(struct i2c_client *c, unsigned int freq)
+{
+       struct tuner *t = i2c_get_clientdata(c);
+       unsigned int if2;
+
+       if (t->std & V4L2_STD_525_60) {
+               // NTSC
+                if2 = 45750*1000;
+        } else {
+                // PAL
+                if2 = 38900*1000;
+        }
+       if (V4L2_TUNER_DIGITAL_TV == t->mode) {
+               // DVB (pinnacle 300i)
+               if2 = 36150*1000;
+       }
+       mt2050_set_if_freq(c, freq*62500, if2);
+       mt2050_set_antenna(c, tv_antenna);
+}
+
+static void mt2050_set_radio_freq(struct i2c_client *c, unsigned int freq)
+{
+       struct tuner *t = i2c_get_clientdata(c);
+       int if2 = t->radio_if2;
+
+       mt2050_set_if_freq(c, freq*62500, if2);
+       mt2050_set_antenna(c, radio_antenna);
+}
+
+static int mt2050_init(struct i2c_client *c)
+{
+       struct tuner *t = i2c_get_clientdata(c);
+       unsigned char buf[2];
+       int ret;
+
+       buf[0]=6;
+       buf[1]=0x10;
+       ret=i2c_master_send(c,buf,2); //  power
+
+       buf[0]=0x0f;
+       buf[1]=0x0f;
+       ret=i2c_master_send(c,buf,2); // m1lo
+
+       buf[0]=0x0d;
+       ret=i2c_master_send(c,buf,1);
+       i2c_master_recv(c,buf,1);
+
+       tuner_dbg("mt2050: sro is %x\n",buf[0]);
+       t->tv_freq    = mt2050_set_tv_freq;
+       t->radio_freq = mt2050_set_radio_freq;
+       return 0;
+}
+
+int microtune_init(struct i2c_client *c)
+{
+       struct tuner *t = i2c_get_clientdata(c);
+       char *name;
+        unsigned char buf[21];
+       int company_code;
+
+       memset(buf,0,sizeof(buf));
+       t->tv_freq    = NULL;
+       t->radio_freq = NULL;
+       name = "unknown";
+
+        i2c_master_send(c,buf,1);
+        i2c_master_recv(c,buf,21);
+        if (tuner_debug) {
+                int i;
+               tuner_dbg("MT20xx hexdump:");
+                for(i=0;i<21;i++) {
+                        printk(" %02x",buf[i]);
+                        if(((i+1)%8)==0) printk(" ");
+                }
+                printk("\n");
+        }
+       company_code = buf[0x11] << 8 | buf[0x12];
+       tuner_info("microtune: companycode=%04x part=%02x rev=%02x\n",
+                  company_code,buf[0x13],buf[0x14]);
+
+#if 0
+       /* seems to cause more problems than it solves ... */
+       switch (company_code) {
+       case 0x30bf:
+       case 0x3cbf:
+       case 0x3dbf:
+       case 0x4d54:
+       case 0x8e81:
+       case 0x8e91:
+               /* ok (?) */
+               break;
+       default:
+               tuner_warn("tuner: microtune: unknown companycode\n");
+               return 0;
+       }
+#endif
+
+       if (buf[0x13] < ARRAY_SIZE(microtune_part) &&
+           NULL != microtune_part[buf[0x13]])
+               name = microtune_part[buf[0x13]];
+       switch (buf[0x13]) {
+       case MT2032:
+               mt2032_init(c);
+               break;
+       case MT2050:
+               mt2050_init(c);
+               break;
+       default:
+               tuner_info("microtune %s found, not (yet?) supported, sorry :-/\n",
+                          name);
+                return 0;
+        }
+
+       strlcpy(c->name, name, sizeof(c->name));
+       tuner_info("microtune %s found, OK\n",name);
+       return 0;
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/misc/hdpuftrs/Makefile b/drivers/misc/hdpuftrs/Makefile
new file mode 100644 (file)
index 0000000..ac74ae6
--- /dev/null
@@ -0,0 +1 @@
+obj-$(CONFIG_HDPU_FEATURES) := hdpu_cpustate.o hdpu_nexus.o
diff --git a/drivers/misc/hdpuftrs/hdpu_cpustate.c b/drivers/misc/hdpuftrs/hdpu_cpustate.c
new file mode 100644 (file)
index 0000000..7501fab
--- /dev/null
@@ -0,0 +1,234 @@
+/*
+ *     Sky CPU State Driver
+ *
+ *     Copyright (C) 2002 Brian Waite
+ *
+ *     This driver allows use of the CPU state bits
+ *     It exports the /dev/sky_cpustate and also
+ *     /proc/sky_cpustate pseudo-file for status information.
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     as published by the Free Software Foundation; either version
+ *     2 of the License, or (at your option) any later version.
+ *
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/miscdevice.h>
+#include <linux/pci.h>
+#include <linux/proc_fs.h>
+#include <linux/device.h>
+#include <asm/uaccess.h>
+#include <linux/hdpu_features.h>
+
+#define SKY_CPUSTATE_VERSION           "1.1"
+
+static int hdpu_cpustate_probe(struct device *ddev);
+static int hdpu_cpustate_remove(struct device *ddev);
+
+struct cpustate_t cpustate;
+
+static int cpustate_get_ref(int excl)
+{
+
+       int retval = -EBUSY;
+
+       spin_lock(&cpustate.lock);
+
+       if (cpustate.excl)
+               goto out_busy;
+
+       if (excl) {
+               if (cpustate.open_count)
+                       goto out_busy;
+               cpustate.excl = 1;
+       }
+
+       cpustate.open_count++;
+       retval = 0;
+
+      out_busy:
+       spin_unlock(&cpustate.lock);
+       return retval;
+}
+
+static int cpustate_free_ref(void)
+{
+
+       spin_lock(&cpustate.lock);
+
+       cpustate.excl = 0;
+       cpustate.open_count--;
+
+       spin_unlock(&cpustate.lock);
+       return 0;
+}
+
+unsigned char cpustate_get_state(void)
+{
+
+       return cpustate.cached_val;
+}
+
+void cpustate_set_state(unsigned char new_state)
+{
+       unsigned int state = (new_state << 21);
+
+#ifdef DEBUG_CPUSTATE
+       printk("CPUSTATE -> 0x%x\n", new_state);
+#endif
+       spin_lock(&cpustate.lock);
+       cpustate.cached_val = new_state;
+       writel((0xff << 21), cpustate.clr_addr);
+       writel(state, cpustate.set_addr);
+       spin_unlock(&cpustate.lock);
+}
+
+/*
+ *     Now all the various file operations that we export.
+ */
+
+static ssize_t cpustate_read(struct file *file, char *buf,
+                            size_t count, loff_t * ppos)
+{
+       unsigned char data;
+
+       if (count < 0)
+               return -EFAULT;
+       if (count == 0)
+               return 0;
+
+       data = cpustate_get_state();
+       if (copy_to_user(buf, &data, sizeof(unsigned char)))
+               return -EFAULT;
+       return sizeof(unsigned char);
+}
+
+static ssize_t cpustate_write(struct file *file, const char *buf,
+                             size_t count, loff_t * ppos)
+{
+       unsigned char data;
+
+       if (count < 0)
+               return -EFAULT;
+
+       if (count == 0)
+               return 0;
+
+       if (copy_from_user((unsigned char *)&data, buf, sizeof(unsigned char)))
+               return -EFAULT;
+
+       cpustate_set_state(data);
+       return sizeof(unsigned char);
+}
+
+static int cpustate_open(struct inode *inode, struct file *file)
+{
+       return cpustate_get_ref((file->f_flags & O_EXCL));
+}
+
+static int cpustate_release(struct inode *inode, struct file *file)
+{
+       return cpustate_free_ref();
+}
+
+/*
+ *     Info exported via "/proc/sky_cpustate".
+ */
+static int cpustate_read_proc(char *page, char **start, off_t off,
+                             int count, int *eof, void *data)
+{
+       char *p = page;
+       int len = 0;
+
+       p += sprintf(p, "CPU State: %04x\n", cpustate_get_state());
+       len = p - page;
+
+       if (len <= off + count)
+               *eof = 1;
+       *start = page + off;
+       len -= off;
+       if (len > count)
+               len = count;
+       if (len < 0)
+               len = 0;
+       return len;
+}
+
+static struct device_driver hdpu_cpustate_driver = {
+       .name = HDPU_CPUSTATE_NAME,
+       .bus = &platform_bus_type,
+       .probe = hdpu_cpustate_probe,
+       .remove = hdpu_cpustate_remove,
+};
+
+/*
+ *     The various file operations we support.
+ */
+static struct file_operations cpustate_fops = {
+      owner:THIS_MODULE,
+      open:cpustate_open,
+      release:cpustate_release,
+      read:cpustate_read,
+      write:cpustate_write,
+      fasync:NULL,
+      poll:NULL,
+      ioctl:NULL,
+      llseek:no_llseek,
+
+};
+
+static struct miscdevice cpustate_dev = {
+       MISC_DYNAMIC_MINOR,
+       "sky_cpustate",
+       &cpustate_fops
+};
+
+static int hdpu_cpustate_probe(struct device *ddev)
+{
+       struct platform_device *pdev = to_platform_device(ddev);
+       struct resource *res;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       cpustate.set_addr = (unsigned long *)res->start;
+       cpustate.clr_addr = (unsigned long *)res->end - 1;
+
+       misc_register(&cpustate_dev);
+       create_proc_read_entry("sky_cpustate", 0, 0, cpustate_read_proc, NULL);
+
+       printk(KERN_INFO "Sky CPU State Driver v" SKY_CPUSTATE_VERSION "\n");
+       return 0;
+}
+static int hdpu_cpustate_remove(struct device *ddev)
+{
+
+       cpustate.set_addr = 0;
+       cpustate.clr_addr = 0;
+
+       remove_proc_entry("sky_cpustate", NULL);
+       misc_deregister(&cpustate_dev);
+       return 0;
+
+}
+
+static int __init cpustate_init(void)
+{
+       int rc;
+       rc = driver_register(&hdpu_cpustate_driver);
+       return rc;
+}
+
+static void __exit cpustate_exit(void)
+{
+       driver_unregister(&hdpu_cpustate_driver);
+}
+
+module_init(cpustate_init);
+module_exit(cpustate_exit);
+
+MODULE_AUTHOR("Brian Waite");
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/hdpuftrs/hdpu_nexus.c b/drivers/misc/hdpuftrs/hdpu_nexus.c
new file mode 100644 (file)
index 0000000..c203b27
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ *     Sky Nexus Register Driver
+ *
+ *     Copyright (C) 2002 Brian Waite
+ *
+ *     This driver allows reading the Nexus register
+ *     It exports the /proc/sky_chassis_id and also
+ *     /proc/sky_slot_id pseudo-file for status information.
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     as published by the Free Software Foundation; either version
+ *     2 of the License, or (at your option) any later version.
+ *
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/proc_fs.h>
+#include <linux/hdpu_features.h>
+#include <linux/pci.h>
+
+#include <linux/device.h>
+
+static int hdpu_nexus_probe(struct device *ddev);
+static int hdpu_nexus_remove(struct device *ddev);
+
+static struct proc_dir_entry *hdpu_slot_id;
+static struct proc_dir_entry *hdpu_chassis_id;
+static int slot_id = -1;
+static int chassis_id = -1;
+
+static struct device_driver hdpu_nexus_driver = {
+       .name = HDPU_NEXUS_NAME,
+       .bus = &platform_bus_type,
+       .probe = hdpu_nexus_probe,
+       .remove = hdpu_nexus_remove,
+};
+
+int hdpu_slot_id_read(char *buffer, char **buffer_location, off_t offset,
+                     int buffer_length, int *zero, void *ptr)
+{
+
+       if (offset > 0)
+               return 0;
+       return sprintf(buffer, "%d\n", slot_id);
+}
+
+int hdpu_chassis_id_read(char *buffer, char **buffer_location, off_t offset,
+                        int buffer_length, int *zero, void *ptr)
+{
+
+       if (offset > 0)
+               return 0;
+       return sprintf(buffer, "%d\n", chassis_id);
+}
+
+static int hdpu_nexus_probe(struct device *ddev)
+{
+       struct platform_device *pdev = to_platform_device(ddev);
+       struct resource *res;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       int *nexus_id_addr;
+       nexus_id_addr =
+           ioremap(res->start, (unsigned long)(res->end - res->start));
+       if (nexus_id_addr) {
+               slot_id = (*nexus_id_addr >> 8) & 0x1f;
+               chassis_id = *nexus_id_addr & 0xff;
+               iounmap(nexus_id_addr);
+       } else
+               printk("Could not map slot id\n");
+       hdpu_slot_id = create_proc_entry("sky_slot_id", 0666, &proc_root);
+       hdpu_slot_id->read_proc = hdpu_slot_id_read;
+       hdpu_slot_id->nlink = 1;
+
+       hdpu_chassis_id = create_proc_entry("sky_chassis_id", 0666, &proc_root);
+       hdpu_chassis_id->read_proc = hdpu_chassis_id_read;
+       hdpu_chassis_id->nlink = 1;
+       return 0;
+}
+
+static int hdpu_nexus_remove(struct device *ddev)
+{
+       slot_id = -1;
+       chassis_id = -1;
+       remove_proc_entry("sky_slot_id", &proc_root);
+       remove_proc_entry("sky_chassis_id", &proc_root);
+       hdpu_slot_id = 0;
+       hdpu_chassis_id = 0;
+       return 0;
+}
+
+static int __init nexus_init(void)
+{
+       int rc;
+       rc = driver_register(&hdpu_nexus_driver);
+       return rc;
+}
+
+static void __exit nexus_exit(void)
+{
+       driver_unregister(&hdpu_nexus_driver);
+}
+
+module_init(nexus_init);
+module_exit(nexus_exit);
+
+MODULE_AUTHOR("Brian Waite");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/atmel.h b/drivers/net/wireless/atmel.h
new file mode 100644 (file)
index 0000000..825000e
--- /dev/null
@@ -0,0 +1,43 @@
+/*** -*- linux-c -*- **********************************************************
+
+     Driver for Atmel at76c502 at76c504 and at76c506 wireless cards.
+
+         Copyright 2005 Dan Williams and Red Hat, Inc.
+
+    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 software 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 Atmel wireless lan drivers; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+******************************************************************************/
+
+#ifndef _ATMEL_H
+#define _ATMEL_H
+
+typedef enum {
+       ATMEL_FW_TYPE_NONE = 0,
+       ATMEL_FW_TYPE_502,
+       ATMEL_FW_TYPE_502D,
+       ATMEL_FW_TYPE_502E,
+       ATMEL_FW_TYPE_502_3COM,
+       ATMEL_FW_TYPE_504,
+       ATMEL_FW_TYPE_504_2958,
+       ATMEL_FW_TYPE_504A_2958,
+       ATMEL_FW_TYPE_506
+} AtmelFWType;
+
+struct net_device *init_atmel_card(unsigned short, int, const AtmelFWType, struct device *, 
+                                   int (*present_func)(void *), void * );
+void stop_atmel_card( struct net_device *, int );
+int atmel_open( struct net_device * );
+
+#endif
diff --git a/drivers/serial/jsm/Makefile b/drivers/serial/jsm/Makefile
new file mode 100644 (file)
index 0000000..e46b6e0
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# Makefile for Jasmine adapter
+#
+
+obj-$(CONFIG_SERIAL_JSM) += jsm.o
+
+jsm-objs :=    jsm_driver.o jsm_neo.o jsm_tty.o
+
diff --git a/drivers/sh/Makefile b/drivers/sh/Makefile
new file mode 100644 (file)
index 0000000..8a14389
--- /dev/null
@@ -0,0 +1,6 @@
+#
+# Makefile for the SuperH specific drivers.
+#
+
+obj-$(CONFIG_SUPERHYWAY) += superhyway/
+
diff --git a/drivers/sh/superhyway/Makefile b/drivers/sh/superhyway/Makefile
new file mode 100644 (file)
index 0000000..499dc47
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# Makefile for the SuperHyway bus drivers.
+#
+
+obj-$(CONFIG_SUPERHYWAY)       += superhyway.o
+obj-$(CONFIG_SYSFS)            += superhyway-sysfs.o
+
diff --git a/drivers/sh/superhyway/superhyway-sysfs.c b/drivers/sh/superhyway/superhyway-sysfs.c
new file mode 100644 (file)
index 0000000..39ab6a1
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * drivers/sh/superhyway/superhyway-sysfs.c
+ *
+ * SuperHyway Bus sysfs interface
+ *
+ * Copyright (C) 2004, 2005  Paul Mundt <lethal@linux-sh.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/types.h>
+#include <linux/superhyway.h>
+
+#define superhyway_ro_attr(name, fmt, field)                           \
+static ssize_t name##_show(struct device *dev, char *buf)              \
+{                                                                      \
+       struct superhyway_device *s = to_superhyway_device(dev);        \
+       return sprintf(buf, fmt, s->field);                             \
+}
+
+/* VCR flags */
+superhyway_ro_attr(perr_flags, "0x%02x\n", vcr.perr_flags);
+superhyway_ro_attr(merr_flags, "0x%02x\n", vcr.merr_flags);
+superhyway_ro_attr(mod_vers, "0x%04x\n", vcr.mod_vers);
+superhyway_ro_attr(mod_id, "0x%04x\n", vcr.mod_id);
+superhyway_ro_attr(bot_mb, "0x%02x\n", vcr.bot_mb);
+superhyway_ro_attr(top_mb, "0x%02x\n", vcr.top_mb);
+
+/* Misc */
+superhyway_ro_attr(resource, "0x%08lx\n", resource.start);
+
+struct device_attribute superhyway_dev_attrs[] = {
+       __ATTR_RO(perr_flags),
+       __ATTR_RO(merr_flags),
+       __ATTR_RO(mod_vers),
+       __ATTR_RO(mod_id),
+       __ATTR_RO(bot_mb),
+       __ATTR_RO(top_mb),
+       __ATTR_RO(resource),
+       __ATTR_NULL,
+};
+
diff --git a/drivers/sh/superhyway/superhyway.c b/drivers/sh/superhyway/superhyway.c
new file mode 100644 (file)
index 0000000..f056276
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ * drivers/sh/superhyway/superhyway.c
+ *
+ * SuperHyway Bus Driver
+ *
+ * Copyright (C) 2004, 2005  Paul Mundt <lethal@linux-sh.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/superhyway.h>
+
+static int superhyway_devices;
+
+static struct device superhyway_bus_device = {
+       .bus_id = "superhyway",
+};
+
+static void superhyway_device_release(struct device *dev)
+{
+       kfree(to_superhyway_device(dev));
+}
+
+/**
+ * superhyway_add_device - Add a SuperHyway module
+ * @mod_id: Module ID (taken from MODULE.VCR.MOD_ID).
+ * @base: Physical address where module is mapped.
+ * @vcr: VCR value.
+ *
+ * This is responsible for adding a new SuperHyway module. This sets up a new
+ * struct superhyway_device for the module being added. Each one of @mod_id,
+ * @base, and @vcr are registered with the new device for further use
+ * elsewhere.
+ *
+ * Devices are initially added in the order that they are scanned (from the
+ * top-down of the memory map), and are assigned an ID based on the order that
+ * they are added. Any manual addition of a module will thus get the ID after
+ * the devices already discovered regardless of where it resides in memory.
+ *
+ * Further work can and should be done in superhyway_scan_bus(), to be sure
+ * that any new modules are properly discovered and subsequently registered.
+ */
+int superhyway_add_device(unsigned int mod_id, unsigned long base,
+                         unsigned long long vcr)
+{
+       struct superhyway_device *dev;
+
+       dev = kmalloc(sizeof(struct superhyway_device), GFP_KERNEL);
+       if (!dev)
+               return -ENOMEM;
+
+       memset(dev, 0, sizeof(struct superhyway_device));
+
+       dev->id.id = mod_id;
+       sprintf(dev->name, "SuperHyway device %04x", dev->id.id);
+
+       dev->vcr                = *((struct vcr_info *)(&vcr));
+       dev->resource.name      = dev->name;
+       dev->resource.start     = base;
+       dev->resource.end       = dev->resource.start + 0x01000000;
+       dev->dev.parent         = &superhyway_bus_device;
+       dev->dev.bus            = &superhyway_bus_type;
+       dev->dev.release        = superhyway_device_release;
+
+       sprintf(dev->dev.bus_id, "%02x", superhyway_devices);
+
+       superhyway_devices++;
+
+       return device_register(&dev->dev);
+}
+
+static int __init superhyway_init(void)
+{
+       device_register(&superhyway_bus_device);
+       return superhyway_scan_bus();
+}
+
+postcore_initcall(superhyway_init);
+
+static const struct superhyway_device_id *
+superhyway_match_id(const struct superhyway_device_id *ids,
+                   struct superhyway_device *dev)
+{
+       while (ids->id) {
+               if (ids->id == dev->id.id)
+                       return ids;
+
+               ids++;
+       }
+
+       return NULL;
+}
+
+static int superhyway_device_probe(struct device *dev)
+{
+       struct superhyway_device *shyway_dev = to_superhyway_device(dev);
+       struct superhyway_driver *shyway_drv = to_superhyway_driver(dev->driver);
+
+       if (shyway_drv && shyway_drv->probe) {
+               const struct superhyway_device_id *id;
+
+               id = superhyway_match_id(shyway_drv->id_table, shyway_dev);
+               if (id)
+                       return shyway_drv->probe(shyway_dev, id);
+       }
+
+       return -ENODEV;
+}
+
+static int superhyway_device_remove(struct device *dev)
+{
+       struct superhyway_device *shyway_dev = to_superhyway_device(dev);
+       struct superhyway_driver *shyway_drv = to_superhyway_driver(dev->driver);
+
+       if (shyway_drv && shyway_drv->remove) {
+               shyway_drv->remove(shyway_dev);
+               return 0;
+       }
+
+       return -ENODEV;
+}
+
+/**
+ * superhyway_register_driver - Register a new SuperHyway driver
+ * @drv: SuperHyway driver to register.
+ *
+ * This registers the passed in @drv. Any devices matching the id table will
+ * automatically be populated and handed off to the driver's specified probe
+ * routine.
+ */
+int superhyway_register_driver(struct superhyway_driver *drv)
+{
+       drv->drv.name   = drv->name;
+       drv->drv.bus    = &superhyway_bus_type;
+       drv->drv.probe  = superhyway_device_probe;
+       drv->drv.remove = superhyway_device_remove;
+
+       return driver_register(&drv->drv);
+}
+
+/**
+ * superhyway_unregister_driver - Unregister a SuperHyway driver
+ * @drv: SuperHyway driver to unregister.
+ *
+ * This cleans up after superhyway_register_driver(), and should be invoked in
+ * the exit path of any module drivers.
+ */
+void superhyway_unregister_driver(struct superhyway_driver *drv)
+{
+       driver_unregister(&drv->drv);
+}
+
+static int superhyway_bus_match(struct device *dev, struct device_driver *drv)
+{
+       struct superhyway_device *shyway_dev = to_superhyway_device(dev);
+       struct superhyway_driver *shyway_drv = to_superhyway_driver(drv);
+       const struct superhyway_device_id *ids = shyway_drv->id_table;
+
+       if (!ids)
+               return -EINVAL;
+       if (superhyway_match_id(ids, shyway_dev))
+               return 1;
+
+       return -ENODEV;
+}
+
+struct bus_type superhyway_bus_type = {
+       .name           = "superhyway",
+       .match          = superhyway_bus_match,
+#ifdef CONFIG_SYSFS
+       .dev_attrs      = superhyway_dev_attrs,
+#endif
+};
+
+static int __init superhyway_bus_init(void)
+{
+       return bus_register(&superhyway_bus_type);
+}
+
+static void __exit superhyway_bus_exit(void)
+{
+       device_unregister(&superhyway_bus_device);
+       bus_unregister(&superhyway_bus_type);
+}
+
+core_initcall(superhyway_bus_init);
+module_exit(superhyway_bus_exit);
+
+EXPORT_SYMBOL(superhyway_bus_type);
+EXPORT_SYMBOL(superhyway_add_device);
+EXPORT_SYMBOL(superhyway_register_driver);
+EXPORT_SYMBOL(superhyway_unregister_driver);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/misc/sisusbvga/Kconfig b/drivers/usb/misc/sisusbvga/Kconfig
new file mode 100644 (file)
index 0000000..3957e14
--- /dev/null
@@ -0,0 +1,14 @@
+
+config USB_SISUSBVGA
+       tristate "USB 2.0 SVGA dongle support (Net2280/SiS315)"
+       depends on USB && USB_EHCI_HCD
+        ---help---
+         Say Y here if you intend to attach a USB2VGA dongle based on a
+         Net2280 and a SiS315 chip. 
+         
+         Note that this device requires a USB 2.0 host controller. It will not 
+         work with USB 1.x controllers.
+
+         To compile this driver as a module, choose M here: the module will be
+         called sisusb.  If unsure, say N.
+
diff --git a/drivers/usb/misc/sisusbvga/Makefile b/drivers/usb/misc/sisusbvga/Makefile
new file mode 100644 (file)
index 0000000..76f1643
--- /dev/null
@@ -0,0 +1,6 @@
+#
+# Makefile for the sisusb driver (if driver is inside kernel tree).
+#
+
+obj-$(CONFIG_USB_SISUSBVGA) += sisusb.o
+
diff --git a/drivers/usb/mon/Kconfig b/drivers/usb/mon/Kconfig
new file mode 100644 (file)
index 0000000..4e6152a
--- /dev/null
@@ -0,0 +1,22 @@
+#
+# USB Monitor configuration
+#
+
+# In normal life, it makes little sense to have usbmon as a module, and in fact
+# it is harmful, because there is no way to autoload the module.
+# The 'm' option is allowed for hackers who debug the usbmon itself,
+# and for those who have usbcore as a module.
+config USB_MON
+       tristate "USB Monitor"
+       depends on USB
+       default y
+       help
+         If you say Y here, a component which captures the USB traffic
+         between peripheral-specific drivers and HC drivers will be built.
+         The USB_MON is similar in spirit and may be compatible with Dave
+         Harding's USBMon.
+
+         This is somewhat experimental at this time, but it should be safe,
+         as long as you aren't building this as a module and then removing it.
+
+         If unsure, say Y. Do not say M.
diff --git a/drivers/usb/mon/Makefile b/drivers/usb/mon/Makefile
new file mode 100644 (file)
index 0000000..3cff8d4
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# Makefile for USB Core files and filesystem
+#
+
+usbmon-objs    := mon_main.o mon_stat.o mon_text.o
+
+obj-$(CONFIG_USB_MON)  += usbmon.o
diff --git a/drivers/video/geode/display_gx1.c b/drivers/video/geode/display_gx1.c
new file mode 100644 (file)
index 0000000..f498387
--- /dev/null
@@ -0,0 +1,214 @@
+/*
+ * drivers/video/geode/display_gx1.c
+ *   -- Geode GX1 display controller
+ *
+ * Copyright (C) 2005 Arcom Control Systems Ltd.
+ *
+ * Based on AMD's original 2.4 driver:
+ *   Copyright (C) 2004 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#include <linux/spinlock.h>
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <asm/div64.h>
+#include <asm/delay.h>
+
+#include "geodefb.h"
+#include "display_gx1.h"
+
+static spinlock_t gx1_conf_reg_lock = SPIN_LOCK_UNLOCKED;
+
+static u8 gx1_read_conf_reg(u8 reg)
+{
+       u8 val, ccr3;
+       unsigned long flags;
+
+       spin_lock_irqsave(&gx1_conf_reg_lock, flags);
+
+       outb(CONFIG_CCR3, 0x22);
+       ccr3 = inb(0x23);
+       outb(CONFIG_CCR3, 0x22);
+       outb(ccr3 | CONFIG_CCR3_MAPEN, 0x23);
+       outb(reg, 0x22);
+       val = inb(0x23);
+       outb(CONFIG_CCR3, 0x22);
+       outb(ccr3, 0x23);
+
+       spin_unlock_irqrestore(&gx1_conf_reg_lock, flags);
+
+       return val;
+}
+
+unsigned gx1_gx_base(void)
+{
+       return (gx1_read_conf_reg(CONFIG_GCR) & 0x03) << 30;
+}
+
+int gx1_frame_buffer_size(void)
+{
+       void __iomem *mc_regs;
+       u32 bank_cfg;
+       int d;
+       unsigned dram_size = 0, fb_base;
+
+       mc_regs = ioremap(gx1_gx_base() + 0x8400, 0x100);
+       if (!mc_regs)
+               return -ENOMEM;
+
+
+       /* Calculate the total size of both DIMM0 and DIMM1. */
+       bank_cfg = readl(mc_regs + MC_BANK_CFG);
+
+       for (d = 0; d < 2; d++) {
+               if ((bank_cfg & MC_BCFG_DIMM0_PG_SZ_MASK) != MC_BCFG_DIMM0_PG_SZ_NO_DIMM)
+                       dram_size += 0x400000 << ((bank_cfg & MC_BCFG_DIMM0_SZ_MASK) >> 8);
+               bank_cfg >>= 16; /* look at DIMM1 next */
+       }
+
+       fb_base = (readl(mc_regs + MC_GBASE_ADD) & MC_GADD_GBADD_MASK) << 19;
+
+       iounmap(mc_regs);
+
+       return dram_size - fb_base;
+}
+
+static void gx1_set_mode(struct fb_info *info)
+{
+       struct geodefb_par *par = info->par;
+       u32 gcfg, tcfg, ocfg, dclk_div, val;
+       int hactive, hblankstart, hsyncstart, hsyncend, hblankend, htotal;
+       int vactive, vblankstart, vsyncstart, vsyncend, vblankend, vtotal;
+
+       /* Unlock the display controller registers. */
+       readl(par->dc_regs + DC_UNLOCK);
+       writel(DC_UNLOCK_CODE, par->dc_regs + DC_UNLOCK);
+
+       gcfg = readl(par->dc_regs + DC_GENERAL_CFG);
+       tcfg = readl(par->dc_regs + DC_TIMING_CFG);
+
+       /* Blank the display and disable the timing generator. */
+       tcfg &= ~(DC_TCFG_BLKE | DC_TCFG_TGEN);
+       writel(tcfg, par->dc_regs + DC_TIMING_CFG);
+
+       /* Wait for pending memory requests before disabling the FIFO load. */
+       udelay(100);
+
+       /* Disable FIFO load and compression. */
+       gcfg &= ~(DC_GCFG_DFLE | DC_GCFG_CMPE | DC_GCFG_DECE);
+       writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
+
+       /* Setup DCLK and its divisor. */
+       gcfg &= ~DC_GCFG_DCLK_MASK;
+       writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
+
+       par->vid_ops->set_dclk(info);
+
+       dclk_div = DC_GCFG_DCLK_DIV_1; /* FIXME: may need to divide DCLK by 2 sometimes? */
+       gcfg |= dclk_div;
+       writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
+
+       /* Wait for the clock generatation to settle.  This is needed since
+        * some of the register writes that follow require that clock to be
+        * present. */
+       udelay(1000); /* FIXME: seems a little long */
+
+       /*
+        * Setup new mode.
+        */
+
+       /* Clear all unused feature bits. */
+       gcfg = DC_GCFG_VRDY | dclk_div;
+
+       /* Set FIFO priority (default 6/5) and enable. */
+       /* FIXME: increase fifo priority for 1280x1024 modes? */
+       gcfg |= (6 << DC_GCFG_DFHPEL_POS) | (5 << DC_GCFG_DFHPSL_POS) | DC_GCFG_DFLE;
+
+       /* FIXME: Set pixel and line double bits if necessary. */
+
+       /* Framebuffer start offset. */
+       writel(0, par->dc_regs + DC_FB_ST_OFFSET);
+
+       /* Line delta and line buffer length. */
+       writel(info->fix.line_length >> 2, par->dc_regs + DC_LINE_DELTA);
+       writel(((info->var.xres * info->var.bits_per_pixel/8) >> 3) + 2,
+              par->dc_regs + DC_BUF_SIZE);
+
+       /* Output configuration. Enable panel data, set pixel format. */
+       ocfg = DC_OCFG_PCKE | DC_OCFG_PDEL | DC_OCFG_PDEH;
+       if (info->var.bits_per_pixel == 8) ocfg |= DC_OCFG_8BPP;
+
+       /* Enable timing generator, sync and FP data. */
+       tcfg = DC_TCFG_FPPE | DC_TCFG_HSYE | DC_TCFG_VSYE | DC_TCFG_BLKE
+               | DC_TCFG_TGEN;
+
+       /* Horizontal and vertical timings. */
+       hactive = info->var.xres;
+       hblankstart = hactive;
+       hsyncstart = hblankstart + info->var.right_margin;
+       hsyncend =  hsyncstart + info->var.hsync_len;
+       hblankend = hsyncend + info->var.left_margin;
+       htotal = hblankend;
+
+       vactive = info->var.yres;
+       vblankstart = vactive;
+       vsyncstart = vblankstart + info->var.lower_margin;
+       vsyncend =  vsyncstart + info->var.vsync_len;
+       vblankend = vsyncend + info->var.upper_margin;
+       vtotal = vblankend;
+
+       val = (hactive - 1) | ((htotal - 1) << 16);
+       writel(val, par->dc_regs + DC_H_TIMING_1);
+       val = (hblankstart - 1) | ((hblankend - 1) << 16);
+       writel(val, par->dc_regs + DC_H_TIMING_2);
+       val = (hsyncstart - 1) | ((hsyncend - 1) << 16);
+       writel(val, par->dc_regs + DC_H_TIMING_3);
+       writel(val, par->dc_regs + DC_FP_H_TIMING);
+       val = (vactive - 1) | ((vtotal - 1) << 16);
+       writel(val, par->dc_regs + DC_V_TIMING_1);
+       val = (vblankstart - 1) | ((vblankend - 1) << 16);
+       writel(val, par->dc_regs + DC_V_TIMING_2);
+       val = (vsyncstart - 1) | ((vsyncend - 1) << 16);
+       writel(val, par->dc_regs + DC_V_TIMING_3);
+       val = (vsyncstart - 2) | ((vsyncend - 2) << 16);
+       writel(val, par->dc_regs + DC_FP_V_TIMING);
+
+       /* Write final register values. */
+       writel(ocfg, par->dc_regs + DC_OUTPUT_CFG);
+       writel(tcfg, par->dc_regs + DC_TIMING_CFG);
+       udelay(1000); /* delay after TIMING_CFG. FIXME: perhaps a little long */
+       writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
+
+       par->vid_ops->configure_display(info);
+
+       /* Relock display controller registers */
+       writel(0, par->dc_regs + DC_UNLOCK);
+
+       /* FIXME: write line_length and bpp to Graphics Pipeline GP_BLT_STATUS
+        * register. */
+}
+
+static void gx1_set_hw_palette_reg(struct fb_info *info, unsigned regno,
+                                  unsigned red, unsigned green, unsigned blue)
+{
+       struct geodefb_par *par = info->par;
+       int val;
+
+       /* Hardware palette is in RGB 6-6-6 format. */
+       val  = (red   <<  2) & 0x3f000;
+       val |= (green >>  4) & 0x00fc0;
+       val |= (blue  >> 10) & 0x0003f;
+
+       writel(regno, par->dc_regs + DC_PAL_ADDRESS);
+       writel(val, par->dc_regs + DC_PAL_DATA);
+}
+
+struct geode_dc_ops gx1_dc_ops = {
+       .set_mode        = gx1_set_mode,
+       .set_palette_reg = gx1_set_hw_palette_reg,
+};
diff --git a/drivers/video/geode/display_gx1.h b/drivers/video/geode/display_gx1.h
new file mode 100644 (file)
index 0000000..671c055
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * drivers/video/geode/display_gx1.h
+ *   -- Geode GX1 display controller
+ *
+ * Copyright (C) 2005 Arcom Control Systems Ltd.
+ *
+ * Based on AMD's original 2.4 driver:
+ *   Copyright (C) 2004 Advanced Micro Devices, Inc.
+ *
+ * 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.
+ */
+#ifndef __DISPLAY_GX1_H__
+#define __DISPLAY_GX1_H__
+
+unsigned gx1_gx_base(void);
+int gx1_frame_buffer_size(void);
+
+extern struct geode_dc_ops gx1_dc_ops;
+
+/* GX1 configuration I/O registers */
+
+#define CONFIG_CCR3 0xc3
+#  define CONFIG_CCR3_MAPEN 0x10
+#define CONFIG_GCR  0xb8
+
+/* Memory controller registers */
+
+#define MC_BANK_CFG            0x08
+#  define MC_BCFG_DIMM0_SZ_MASK                0x00000700
+#  define MC_BCFG_DIMM0_PG_SZ_MASK     0x00000070
+#  define MC_BCFG_DIMM0_PG_SZ_NO_DIMM  0x00000070
+
+#define MC_GBASE_ADD           0x14
+#  define MC_GADD_GBADD_MASK           0x000003ff
+
+/* Display controller registers */
+
+#define DC_PAL_ADDRESS         0x70
+#define DC_PAL_DATA            0x74
+
+#define DC_UNLOCK              0x00
+#  define DC_UNLOCK_CODE               0x00004758
+
+#define DC_GENERAL_CFG         0x04
+#  define DC_GCFG_DFLE                 0x00000001
+#  define DC_GCFG_CURE                 0x00000002
+#  define DC_GCFG_VCLK_DIV             0x00000004
+#  define DC_GCFG_PLNO                 0x00000004
+#  define DC_GCFG_PPC                  0x00000008
+#  define DC_GCFG_CMPE                 0x00000010
+#  define DC_GCFG_DECE                 0x00000020
+#  define DC_GCFG_DCLK_MASK            0x000000C0
+#  define DC_GCFG_DCLK_DIV_1           0x00000080
+#  define DC_GCFG_DFHPSL_MASK          0x00000F00
+#  define DC_GCFG_DFHPSL_POS                    8
+#  define DC_GCFG_DFHPEL_MASK          0x0000F000
+#  define DC_GCFG_DFHPEL_POS                   12
+#  define DC_GCFG_CIM_MASK             0x00030000
+#  define DC_GCFG_CIM_POS                      16
+#  define DC_GCFG_FDTY                 0x00040000
+#  define DC_GCFG_RTPM                 0x00080000
+#  define DC_GCFG_DAC_RS_MASK          0x00700000
+#  define DC_GCFG_DAC_RS_POS                   20
+#  define DC_GCFG_CKWR                 0x00800000
+#  define DC_GCFG_LDBL                 0x01000000
+#  define DC_GCFG_DIAG                 0x02000000
+#  define DC_GCFG_CH4S                 0x04000000
+#  define DC_GCFG_SSLC                 0x08000000
+#  define DC_GCFG_VIDE                 0x10000000
+#  define DC_GCFG_VRDY                 0x20000000
+#  define DC_GCFG_DPCK                 0x40000000
+#  define DC_GCFG_DDCK                 0x80000000
+
+#define DC_TIMING_CFG          0x08
+#  define DC_TCFG_FPPE                 0x00000001
+#  define DC_TCFG_HSYE                 0x00000002
+#  define DC_TCFG_VSYE                 0x00000004
+#  define DC_TCFG_BLKE                 0x00000008
+#  define DC_TCFG_DDCK                 0x00000010
+#  define DC_TCFG_TGEN                 0x00000020
+#  define DC_TCFG_VIEN                 0x00000040
+#  define DC_TCFG_BLNK                 0x00000080
+#  define DC_TCFG_CHSP                 0x00000100
+#  define DC_TCFG_CVSP                 0x00000200
+#  define DC_TCFG_FHSP                 0x00000400
+#  define DC_TCFG_FVSP                 0x00000800
+#  define DC_TCFG_FCEN                 0x00001000
+#  define DC_TCFG_CDCE                 0x00002000
+#  define DC_TCFG_PLNR                 0x00002000
+#  define DC_TCFG_INTL                 0x00004000
+#  define DC_TCFG_PXDB                 0x00008000
+#  define DC_TCFG_BKRT                 0x00010000
+#  define DC_TCFG_PSD_MASK             0x000E0000
+#  define DC_TCFG_PSD_POS                      17
+#  define DC_TCFG_DDCI                 0x08000000
+#  define DC_TCFG_SENS                 0x10000000
+#  define DC_TCFG_DNA                  0x20000000
+#  define DC_TCFG_VNA                  0x40000000
+#  define DC_TCFG_VINT                 0x80000000
+
+#define DC_OUTPUT_CFG          0x0C
+#  define DC_OCFG_8BPP                 0x00000001
+#  define DC_OCFG_555                  0x00000002
+#  define DC_OCFG_PCKE                 0x00000004
+#  define DC_OCFG_FRME                 0x00000008
+#  define DC_OCFG_DITE                 0x00000010
+#  define DC_OCFG_2PXE                 0x00000020
+#  define DC_OCFG_2XCK                 0x00000040
+#  define DC_OCFG_2IND                 0x00000080
+#  define DC_OCFG_34ADD                        0x00000100
+#  define DC_OCFG_FRMS                 0x00000200
+#  define DC_OCFG_CKSL                 0x00000400
+#  define DC_OCFG_PRMP                 0x00000800
+#  define DC_OCFG_PDEL                 0x00001000
+#  define DC_OCFG_PDEH                 0x00002000
+#  define DC_OCFG_CFRW                 0x00004000
+#  define DC_OCFG_DIAG                 0x00008000
+
+#define DC_FB_ST_OFFSET                0x10
+#define DC_CB_ST_OFFSET                0x14
+#define DC_CURS_ST_OFFSET      0x18
+#define DC_ICON_ST_OFFSET      0x1C
+#define DC_VID_ST_OFFSET       0x20
+#define DC_LINE_DELTA          0x24
+#define DC_BUF_SIZE            0x28
+
+#define DC_H_TIMING_1          0x30
+#define DC_H_TIMING_2          0x34
+#define DC_H_TIMING_3          0x38
+#define DC_FP_H_TIMING         0x3C
+
+#define DC_V_TIMING_1          0x40
+#define DC_V_TIMING_2          0x44
+#define DC_V_TIMING_3          0x48
+#define DC_FP_V_TIMING         0x4C
+
+#define DC_CURSOR_X            0x50
+#define DC_ICON_X              0x54
+#define DC_V_LINE_CNT          0x54
+#define DC_CURSOR_Y            0x58
+#define DC_ICON_Y              0x5C
+#define DC_SS_LINE_CMP         0x5C
+#define DC_CURSOR_COLOR                0x60
+#define DC_ICON_COLOR          0x64
+#define DC_BORDER_COLOR                0x68
+#define DC_PAL_ADDRESS         0x70
+#define DC_PAL_DATA            0x74
+#define DC_DFIFO_DIAG          0x78
+#define DC_CFIFO_DIAG          0x7C
+
+#endif /* !__DISPLAY_GX1_H__ */
diff --git a/drivers/video/geode/geodefb.h b/drivers/video/geode/geodefb.h
new file mode 100644 (file)
index 0000000..b7bac0a
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * drivers/video/geode/geodefb.h
+ *   -- Geode framebuffer driver
+ *
+ * Copyright (C) 2005 Arcom Control Systems Ltd.
+ *
+ * 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.
+ */
+#ifndef __GEODEFB_H__
+#define __GEODEFB_H__
+
+struct geodefb_info;
+
+struct geode_dc_ops {
+       void (*set_mode)(struct fb_info *);
+       void (*set_palette_reg)(struct fb_info *, unsigned, unsigned, unsigned, unsigned);
+};
+
+struct geode_vid_ops {
+       void (*set_dclk)(struct fb_info *);
+       void (*configure_display)(struct fb_info *);
+       int  (*blank_display)(struct fb_info *, int blank_mode);
+};
+
+struct geodefb_par {
+       int enable_crt;
+       int panel_x; /* dimensions of an attached flat panel, non-zero => enable panel */
+       int panel_y;
+       struct pci_dev *vid_dev;
+       void __iomem *dc_regs;
+       void __iomem *vid_regs;
+       struct geode_dc_ops  *dc_ops;
+       struct geode_vid_ops *vid_ops;
+};
+
+#endif /* !__GEODEFB_H__ */
diff --git a/drivers/video/geode/video_cs5530.c b/drivers/video/geode/video_cs5530.c
new file mode 100644 (file)
index 0000000..d3764ac
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+ * drivers/video/geode/video_cs5530.c
+ *   -- CS5530 video device
+ *
+ * Copyright (C) 2005 Arcom Control Systems Ltd.
+ *
+ * Based on AMD's original 2.4 driver:
+ *   Copyright (C) 2004 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <asm/delay.h>
+
+#include "geodefb.h"
+#include "video_cs5530.h"
+
+/*
+ * CS5530 PLL table. This maps pixclocks to the appropriate PLL register
+ * value.
+ */
+struct cs5530_pll_entry {
+       long pixclock; /* ps */
+       u32 pll_value;
+};
+
+static const struct cs5530_pll_entry cs5530_pll_table[] = {
+       { 39721, 0x31C45801, }, /*  25.1750 MHz */
+       { 35308, 0x20E36802, }, /*  28.3220 */
+       { 31746, 0x33915801, }, /*  31.5000 */
+       { 27777, 0x31EC4801, }, /*  36.0000 */
+       { 26666, 0x21E22801, }, /*  37.5000 */
+       { 25000, 0x33088801, }, /*  40.0000 */
+       { 22271, 0x33E22801, }, /*  44.9000 */
+       { 20202, 0x336C4801, }, /*  49.5000 */
+       { 20000, 0x23088801, }, /*  50.0000 */
+       { 19860, 0x23088801, }, /*  50.3500 */
+       { 18518, 0x3708A801, }, /*  54.0000 */
+       { 17777, 0x23E36802, }, /*  56.2500 */
+       { 17733, 0x23E36802, }, /*  56.3916 */
+       { 17653, 0x23E36802, }, /*  56.6444 */
+       { 16949, 0x37C45801, }, /*  59.0000 */
+       { 15873, 0x23EC4801, }, /*  63.0000 */
+       { 15384, 0x37911801, }, /*  65.0000 */
+       { 14814, 0x37963803, }, /*  67.5000 */
+       { 14124, 0x37058803, }, /*  70.8000 */
+       { 13888, 0x3710C805, }, /*  72.0000 */
+       { 13333, 0x37E22801, }, /*  75.0000 */
+       { 12698, 0x27915801, }, /*  78.7500 */
+       { 12500, 0x37D8D802, }, /*  80.0000 */
+       { 11135, 0x27588802, }, /*  89.8000 */
+       { 10582, 0x27EC4802, }, /*  94.5000 */
+       { 10101, 0x27AC6803, }, /*  99.0000 */
+       { 10000, 0x27088801, }, /* 100.0000 */
+       {  9259, 0x2710C805, }, /* 108.0000 */
+       {  8888, 0x27E36802, }, /* 112.5000 */
+       {  7692, 0x27C58803, }, /* 130.0000 */
+       {  7407, 0x27316803, }, /* 135.0000 */
+       {  6349, 0x2F915801, }, /* 157.5000 */
+       {  6172, 0x2F08A801, }, /* 162.0000 */
+       {  5714, 0x2FB11802, }, /* 175.0000 */
+       {  5291, 0x2FEC4802, }, /* 189.0000 */
+       {  4950, 0x2F963803, }, /* 202.0000 */
+       {  4310, 0x2FB1B802, }, /* 232.0000 */
+};
+
+#define NUM_CS5530_FREQUENCIES sizeof(cs5530_pll_table)/sizeof(struct cs5530_pll_entry)
+
+static void cs5530_set_dclk_frequency(struct fb_info *info)
+{
+       struct geodefb_par *par = info->par;
+       int i;
+       u32 value;
+       long min, diff;
+
+       /* Search the table for the closest pixclock. */
+       value = cs5530_pll_table[0].pll_value;
+       min = cs5530_pll_table[0].pixclock - info->var.pixclock;
+       if (min < 0) min = -min;
+       for (i = 1; i < NUM_CS5530_FREQUENCIES; i++) {
+               diff = cs5530_pll_table[i].pixclock - info->var.pixclock;
+               if (diff < 0L) diff = -diff;
+               if (diff < min) {
+                       min = diff;
+                       value = cs5530_pll_table[i].pll_value;
+               }
+       }
+
+       writel(value, par->vid_regs + CS5530_DOT_CLK_CONFIG);
+       writel(value | 0x80000100, par->vid_regs + CS5530_DOT_CLK_CONFIG); /* set reset and bypass */
+       udelay(500); /* wait for PLL to settle */
+       writel(value & 0x7FFFFFFF, par->vid_regs + CS5530_DOT_CLK_CONFIG); /* clear reset */
+       writel(value & 0x7FFFFEFF, par->vid_regs + CS5530_DOT_CLK_CONFIG); /* clear bypass */
+}
+
+static void cs5530_configure_display(struct fb_info *info)
+{
+       struct geodefb_par *par = info->par;
+       u32 dcfg;
+
+       dcfg = readl(par->vid_regs + CS5530_DISPLAY_CONFIG);
+
+       /* Clear bits from existing mode. */
+       dcfg &= ~(CS5530_DCFG_CRT_SYNC_SKW_MASK | CS5530_DCFG_PWR_SEQ_DLY_MASK
+                 | CS5530_DCFG_CRT_HSYNC_POL   | CS5530_DCFG_CRT_VSYNC_POL
+                 | CS5530_DCFG_FP_PWR_EN       | CS5530_DCFG_FP_DATA_EN
+                 | CS5530_DCFG_DAC_PWR_EN      | CS5530_DCFG_VSYNC_EN
+                 | CS5530_DCFG_HSYNC_EN);
+
+       /* Set default sync skew and power sequence delays.  */
+       dcfg |= (CS5530_DCFG_CRT_SYNC_SKW_INIT | CS5530_DCFG_PWR_SEQ_DLY_INIT
+                | CS5530_DCFG_GV_PAL_BYP);
+
+       /* Enable DACs, hsync and vsync for CRTs */
+       if (par->enable_crt) {
+               dcfg |= CS5530_DCFG_DAC_PWR_EN;
+               dcfg |= CS5530_DCFG_HSYNC_EN | CS5530_DCFG_VSYNC_EN;
+       }
+       /* Enable panel power and data if using a flat panel. */
+       if (par->panel_x > 0) {
+               dcfg |= CS5530_DCFG_FP_PWR_EN;
+               dcfg |= CS5530_DCFG_FP_DATA_EN;
+       }
+
+       /* Sync polarities. */
+       if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
+               dcfg |= CS5530_DCFG_CRT_HSYNC_POL;
+       if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
+               dcfg |= CS5530_DCFG_CRT_VSYNC_POL;
+
+       writel(dcfg, par->vid_regs + CS5530_DISPLAY_CONFIG);
+}
+
+static int cs5530_blank_display(struct fb_info *info, int blank_mode)
+{
+       struct geodefb_par *par = info->par;
+       u32 dcfg;
+       int blank, hsync, vsync;
+
+       switch (blank_mode) {
+       case FB_BLANK_UNBLANK:
+               blank = 0; hsync = 1; vsync = 1;
+               break;
+       case FB_BLANK_NORMAL:
+               blank = 1; hsync = 1; vsync = 1;
+               break;
+       case FB_BLANK_VSYNC_SUSPEND:
+               blank = 1; hsync = 1; vsync = 0;
+               break;
+       case FB_BLANK_HSYNC_SUSPEND:
+               blank = 1; hsync = 0; vsync = 1;
+               break;
+       case FB_BLANK_POWERDOWN:
+               blank = 1; hsync = 0; vsync = 0;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       dcfg = readl(par->vid_regs + CS5530_DISPLAY_CONFIG);
+
+       dcfg &= ~(CS5530_DCFG_DAC_BL_EN | CS5530_DCFG_DAC_PWR_EN
+                 | CS5530_DCFG_HSYNC_EN | CS5530_DCFG_VSYNC_EN
+                 | CS5530_DCFG_FP_DATA_EN | CS5530_DCFG_FP_PWR_EN);
+
+       if (par->enable_crt) {
+               if (!blank)
+                       dcfg |= CS5530_DCFG_DAC_BL_EN | CS5530_DCFG_DAC_PWR_EN;
+               if (hsync)
+                       dcfg |= CS5530_DCFG_HSYNC_EN;
+               if (vsync)
+                       dcfg |= CS5530_DCFG_VSYNC_EN;
+       }
+       if (par->panel_x > 0) {
+               if (!blank)
+                       dcfg |= CS5530_DCFG_FP_DATA_EN;
+               if (hsync && vsync)
+                       dcfg |= CS5530_DCFG_FP_PWR_EN;
+       }
+
+       writel(dcfg, par->vid_regs + CS5530_DISPLAY_CONFIG);
+
+       return 0;
+}
+
+struct geode_vid_ops cs5530_vid_ops = {
+       .set_dclk          = cs5530_set_dclk_frequency,
+       .configure_display = cs5530_configure_display,
+       .blank_display     = cs5530_blank_display,
+};
diff --git a/drivers/video/geode/video_cs5530.h b/drivers/video/geode/video_cs5530.h
new file mode 100644 (file)
index 0000000..56cecca
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * drivers/video/geode/video_cs5530.h
+ *   -- CS5530 video device
+ *
+ * Copyright (C) 2005 Arcom Control Systems Ltd.
+ *
+ * Based on AMD's original 2.4 driver:
+ *   Copyright (C) 2004 Advanced Micro Devices, Inc.
+ *
+ * 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.
+ */
+#ifndef __VIDEO_CS5530_H__
+#define __VIDEO_CS5530_H__
+
+extern struct geode_vid_ops cs5530_vid_ops;
+
+/* CS5530 Video device registers */
+
+#define CS5530_VIDEO_CONFIG    0x0000
+#  define CS5530_VCFG_VID_EN                   0x00000001
+#  define CS5530_VCFG_VID_REG_UPDATE           0x00000002
+#  define CS5530_VCFG_VID_INP_FORMAT           0x0000000C
+#  define CS5530_VCFG_8_BIT_4_2_0              0x00000004
+#  define CS5530_VCFG_16_BIT_4_2_0             0x00000008
+#  define CS5530_VCFG_GV_SEL                   0x00000010
+#  define CS5530_VCFG_CSC_BYPASS               0x00000020
+#  define CS5530_VCFG_X_FILTER_EN              0x00000040
+#  define CS5530_VCFG_Y_FILTER_EN              0x00000080
+#  define CS5530_VCFG_LINE_SIZE_LOWER_MASK     0x0000FF00
+#  define CS5530_VCFG_INIT_READ_MASK           0x01FF0000
+#  define CS5530_VCFG_EARLY_VID_RDY            0x02000000
+#  define CS5530_VCFG_LINE_SIZE_UPPER          0x08000000
+#  define CS5530_VCFG_4_2_0_MODE               0x10000000
+#  define CS5530_VCFG_16_BIT_EN                        0x20000000
+#  define CS5530_VCFG_HIGH_SPD_INT             0x40000000
+
+#define CS5530_DISPLAY_CONFIG  0x0004
+#  define CS5530_DCFG_DIS_EN                   0x00000001
+#  define CS5530_DCFG_HSYNC_EN                 0x00000002
+#  define CS5530_DCFG_VSYNC_EN                 0x00000004
+#  define CS5530_DCFG_DAC_BL_EN                        0x00000008
+#  define CS5530_DCFG_DAC_PWR_EN               0x00000020
+#  define CS5530_DCFG_FP_PWR_EN                        0x00000040
+#  define CS5530_DCFG_FP_DATA_EN               0x00000080
+#  define CS5530_DCFG_CRT_HSYNC_POL            0x00000100
+#  define CS5530_DCFG_CRT_VSYNC_POL            0x00000200
+#  define CS5530_DCFG_FP_HSYNC_POL             0x00000400
+#  define CS5530_DCFG_FP_VSYNC_POL             0x00000800
+#  define CS5530_DCFG_XGA_FP                   0x00001000
+#  define CS5530_DCFG_FP_DITH_EN               0x00002000
+#  define CS5530_DCFG_CRT_SYNC_SKW_MASK                0x0001C000
+#  define CS5530_DCFG_CRT_SYNC_SKW_INIT                0x00010000
+#  define CS5530_DCFG_PWR_SEQ_DLY_MASK         0x000E0000
+#  define CS5530_DCFG_PWR_SEQ_DLY_INIT         0x00080000
+#  define CS5530_DCFG_VG_CK                    0x00100000
+#  define CS5530_DCFG_GV_PAL_BYP               0x00200000
+#  define CS5530_DCFG_DDC_SCL                  0x00400000
+#  define CS5530_DCFG_DDC_SDA                  0x00800000
+#  define CS5530_DCFG_DDC_OE                   0x01000000
+#  define CS5530_DCFG_16_BIT_EN                        0x02000000
+
+#define CS5530_VIDEO_X_POS     0x0008
+#define CS5530_VIDEO_Y_POS     0x000C
+#define CS5530_VIDEO_SCALE     0x0010
+#define CS5530_VIDEO_COLOR_KEY 0x0014
+#define CS5530_VIDEO_COLOR_MASK 0x0018
+#define CS5530_PALETTE_ADDRESS 0x001C
+#define CS5530_PALETTE_DATA    0x0020
+#define CS5530_DOT_CLK_CONFIG  0x0024
+#define CS5530_CRCSIG_TFT_TV   0x0028
+
+#endif /* !__VIDEO_CS5530_H__ */
diff --git a/drivers/video/imxfb.h b/drivers/video/imxfb.h
new file mode 100644 (file)
index 0000000..128c3ee
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * linux/drivers/video/imxfb.h
+ *
+ *  Freescale i.MX Frame Buffer device driver
+ *
+ *  Copyright (C) 2004 S.Hauer, Pengutronix
+ *
+ *  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 imxfb_rgb {
+       struct fb_bitfield      red;
+       struct fb_bitfield      green;
+       struct fb_bitfield      blue;
+       struct fb_bitfield      transp;
+};
+
+#define RGB_16 (0)
+#define RGB_8  (1)
+#define NR_RGB 2
+
+struct imxfb_info {
+       struct device           *dev;
+       struct imxfb_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;
+       u_int                   palette_size;
+
+       dma_addr_t              dbar1;
+       dma_addr_t              dbar2;
+
+       u_int                   pcr;
+       u_int                   pwmr;
+       u_int                   lscr1;
+       u_int                   cmap_inverse:1,
+                               cmap_static:1,
+                               unused:30;
+
+       void (*lcd_power)(int);
+       void (*backlight_power)(int);
+};
+
+#define IMX_NAME       "IMX"
+
+/*
+ * Minimum X and Y resolutions
+ */
+#define MIN_XRES       64
+#define MIN_YRES       64
+
diff --git a/drivers/video/nvidia/nv_dma.h b/drivers/video/nvidia/nv_dma.h
new file mode 100644 (file)
index 0000000..a7ed1c0
--- /dev/null
@@ -0,0 +1,188 @@
+
+ /***************************************************************************\
+|*                                                                           *|
+|*       Copyright 2003 NVIDIA, Corporation.  All rights reserved.           *|
+|*                                                                           *|
+|*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
+|*     international laws.  Users and possessors of this source code are     *|
+|*     hereby granted a nonexclusive,  royalty-free copyright license to     *|
+|*     use this code in individual and commercial software.                  *|
+|*                                                                           *|
+|*     Any use of this source code must include,  in the user documenta-     *|
+|*     tion and  internal comments to the code,  notices to the end user     *|
+|*     as follows:                                                           *|
+|*                                                                           *|
+|*       Copyright 2003 NVIDIA, Corporation.  All rights reserved.           *|
+|*                                                                           *|
+|*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
+|*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
+|*     WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  NVIDIA, CORPOR-     *|
+|*     ATION DISCLAIMS ALL WARRANTIES  WITH REGARD  TO THIS SOURCE CODE,     *|
+|*     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE-     *|
+|*     MENT,  AND FITNESS  FOR A PARTICULAR PURPOSE.   IN NO EVENT SHALL     *|
+|*     NVIDIA, CORPORATION  BE LIABLE FOR ANY SPECIAL,  INDIRECT,  INCI-     *|
+|*     DENTAL, OR CONSEQUENTIAL DAMAGES,  OR ANY DAMAGES  WHATSOEVER RE-     *|
+|*     SULTING FROM LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION     *|
+|*     OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  ARISING OUT OF     *|
+|*     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.     *|
+|*                                                                           *|
+|*     U.S. Government  End  Users.   This source code  is a "commercial     *|
+|*     item,"  as that  term is  defined at  48 C.F.R. 2.101 (OCT 1995),     *|
+|*     consisting  of "commercial  computer  software"  and  "commercial     *|
+|*     computer  software  documentation,"  as such  terms  are  used in     *|
+|*     48 C.F.R. 12.212 (SEPT 1995)  and is provided to the U.S. Govern-     *|
+|*     ment only as  a commercial end item.   Consistent with  48 C.F.R.     *|
+|*     12.212 and  48 C.F.R. 227.7202-1 through  227.7202-4 (JUNE 1995),     *|
+|*     all U.S. Government End Users  acquire the source code  with only     *|
+|*     those rights set forth herein.                                        *|
+|*                                                                           *|
+ \***************************************************************************/
+
+/*
+ * GPL Licensing Note - According to Mark Vojkovich, author of the Xorg/
+ * XFree86 'nv' driver, this source code is provided under MIT-style licensing
+ * where the source code is provided "as is" without warranty of any kind.
+ * The only usage restriction is for the copyright notices to be retained
+ * whenever code is used.
+ *
+ * Antonino Daplas <adaplas@pol.net> 2005-03-11
+ */
+
+#define SURFACE_FORMAT                                              0x00000300
+#define SURFACE_FORMAT_DEPTH8                                       0x00000001
+#define SURFACE_FORMAT_DEPTH15                                      0x00000002
+#define SURFACE_FORMAT_DEPTH16                                      0x00000004
+#define SURFACE_FORMAT_DEPTH24                                      0x00000006
+#define SURFACE_PITCH                                               0x00000304
+#define SURFACE_PITCH_SRC                                           15:0
+#define SURFACE_PITCH_DST                                           31:16
+#define SURFACE_OFFSET_SRC                                          0x00000308
+#define SURFACE_OFFSET_DST                                          0x0000030C
+
+#define ROP_SET                                                     0x00002300
+
+#define PATTERN_FORMAT                                              0x00004300
+#define PATTERN_FORMAT_DEPTH8                                       0x00000003
+#define PATTERN_FORMAT_DEPTH16                                      0x00000001
+#define PATTERN_FORMAT_DEPTH24                                      0x00000003
+#define PATTERN_COLOR_0                                             0x00004310
+#define PATTERN_COLOR_1                                             0x00004314
+#define PATTERN_PATTERN_0                                           0x00004318
+#define PATTERN_PATTERN_1                                           0x0000431C
+
+#define CLIP_POINT                                                  0x00006300
+#define CLIP_POINT_X                                                15:0
+#define CLIP_POINT_Y                                                31:16
+#define CLIP_SIZE                                                   0x00006304
+#define CLIP_SIZE_WIDTH                                             15:0
+#define CLIP_SIZE_HEIGHT                                            31:16
+
+#define LINE_FORMAT                                                 0x00008300
+#define LINE_FORMAT_DEPTH8                                          0x00000003
+#define LINE_FORMAT_DEPTH16                                         0x00000001
+#define LINE_FORMAT_DEPTH24                                         0x00000003
+#define LINE_COLOR                                                  0x00008304
+#define LINE_MAX_LINES                                              16
+#define LINE_LINES(i)                                               0x00008400\
+                                                                    +(i)*8
+#define LINE_LINES_POINT0_X                                         15:0
+#define LINE_LINES_POINT0_Y                                         31:16
+#define LINE_LINES_POINT1_X                                         47:32
+#define LINE_LINES_POINT1_Y                                         63:48
+
+#define BLIT_POINT_SRC                                              0x0000A300
+#define BLIT_POINT_SRC_X                                            15:0
+#define BLIT_POINT_SRC_Y                                            31:16
+#define BLIT_POINT_DST                                              0x0000A304
+#define BLIT_POINT_DST_X                                            15:0
+#define BLIT_POINT_DST_Y                                            31:16
+#define BLIT_SIZE                                                   0x0000A308
+#define BLIT_SIZE_WIDTH                                             15:0
+#define BLIT_SIZE_HEIGHT                                            31:16
+
+#define RECT_FORMAT                                                 0x0000C300
+#define RECT_FORMAT_DEPTH8                                          0x00000003
+#define RECT_FORMAT_DEPTH16                                         0x00000001
+#define RECT_FORMAT_DEPTH24                                         0x00000003
+#define RECT_SOLID_COLOR                                            0x0000C3FC
+#define RECT_SOLID_RECTS_MAX_RECTS                                  32
+#define RECT_SOLID_RECTS(i)                                         0x0000C400\
+                                                                    +(i)*8
+#define RECT_SOLID_RECTS_Y                                          15:0
+#define RECT_SOLID_RECTS_X                                          31:16
+#define RECT_SOLID_RECTS_HEIGHT                                     47:32
+#define RECT_SOLID_RECTS_WIDTH                                      63:48
+
+#define RECT_EXPAND_ONE_COLOR_CLIP                                  0x0000C7EC
+#define RECT_EXPAND_ONE_COLOR_CLIP_POINT0_X                         15:0
+#define RECT_EXPAND_ONE_COLOR_CLIP_POINT0_Y                         31:16
+#define RECT_EXPAND_ONE_COLOR_CLIP_POINT1_X                         47:32
+#define RECT_EXPAND_ONE_COLOR_CLIP_POINT1_Y                         63:48
+#define RECT_EXPAND_ONE_COLOR_COLOR                                 0x0000C7F4
+#define RECT_EXPAND_ONE_COLOR_SIZE                                  0x0000C7F8
+#define RECT_EXPAND_ONE_COLOR_SIZE_WIDTH                            15:0
+#define RECT_EXPAND_ONE_COLOR_SIZE_HEIGHT                           31:16
+#define RECT_EXPAND_ONE_COLOR_POINT                                 0x0000C7FC
+#define RECT_EXPAND_ONE_COLOR_POINT_X                               15:0
+#define RECT_EXPAND_ONE_COLOR_POINT_Y                               31:16
+#define RECT_EXPAND_ONE_COLOR_DATA_MAX_DWORDS                       128
+#define RECT_EXPAND_ONE_COLOR_DATA(i)                               0x0000C800\
+                                                                    +(i)*4
+
+#define RECT_EXPAND_TWO_COLOR_CLIP                                  0x0000CBE4
+#define RECT_EXPAND_TWO_COLOR_CLIP_POINT0_X                         15:0
+#define RECT_EXPAND_TWO_COLOR_CLIP_POINT0_Y                         31:16
+#define RECT_EXPAND_TWO_COLOR_CLIP_POINT1_X                         47:32
+#define RECT_EXPAND_TWO_COLOR_CLIP_POINT1_Y                         63:48
+#define RECT_EXPAND_TWO_COLOR_COLOR_0                               0x0000CBEC
+#define RECT_EXPAND_TWO_COLOR_COLOR_1                               0x0000CBF0
+#define RECT_EXPAND_TWO_COLOR_SIZE_IN                               0x0000CBF4
+#define RECT_EXPAND_TWO_COLOR_SIZE_IN_WIDTH                         15:0
+#define RECT_EXPAND_TWO_COLOR_SIZE_IN_HEIGHT                        31:16
+#define RECT_EXPAND_TWO_COLOR_SIZE_OUT                              0x0000CBF8
+#define RECT_EXPAND_TWO_COLOR_SIZE_OUT_WIDTH                        15:0
+#define RECT_EXPAND_TWO_COLOR_SIZE_OUT_HEIGHT                       31:16
+#define RECT_EXPAND_TWO_COLOR_POINT                                 0x0000CBFC
+#define RECT_EXPAND_TWO_COLOR_POINT_X                               15:0
+#define RECT_EXPAND_TWO_COLOR_POINT_Y                               31:16
+#define RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS                       128
+#define RECT_EXPAND_TWO_COLOR_DATA(i)                               0x0000CC00\
+                                                                    +(i)*4
+
+#define STRETCH_BLIT_FORMAT                                         0x0000E300
+#define STRETCH_BLIT_FORMAT_DEPTH8                                  0x00000004
+#define STRETCH_BLIT_FORMAT_DEPTH16                                 0x00000007
+#define STRETCH_BLIT_FORMAT_DEPTH24                                 0x00000004
+#define STRETCH_BLIT_FORMAT_X8R8G8B8                                0x00000004
+#define STRETCH_BLIT_FORMAT_YUYV                                    0x00000005
+#define STRETCH_BLIT_FORMAT_UYVY                                    0x00000006
+#define STRETCH_BLIT_CLIP_POINT                                     0x0000E308
+#define STRETCH_BLIT_CLIP_POINT_X                                   15:0
+#define STRETCH_BLIT_CLIP_POINT_Y                                   31:16
+#define STRETCH_BLIT_CLIP_POINT                                     0x0000E308
+#define STRETCH_BLIT_CLIP_SIZE                                      0x0000E30C
+#define STRETCH_BLIT_CLIP_SIZE_WIDTH                                15:0
+#define STRETCH_BLIT_CLIP_SIZE_HEIGHT                               31:16
+#define STRETCH_BLIT_DST_POINT                                      0x0000E310
+#define STRETCH_BLIT_DST_POINT_X                                    15:0
+#define STRETCH_BLIT_DST_POINT_Y                                    31:16
+#define STRETCH_BLIT_DST_SIZE                                       0x0000E314
+#define STRETCH_BLIT_DST_SIZE_WIDTH                                 15:0
+#define STRETCH_BLIT_DST_SIZE_HEIGHT                                31:16
+#define STRETCH_BLIT_DU_DX                                          0x0000E318
+#define STRETCH_BLIT_DV_DY                                          0x0000E31C
+#define STRETCH_BLIT_SRC_SIZE                                       0x0000E400
+#define STRETCH_BLIT_SRC_SIZE_WIDTH                                 15:0
+#define STRETCH_BLIT_SRC_SIZE_HEIGHT                                31:16
+#define STRETCH_BLIT_SRC_FORMAT                                     0x0000E404
+#define STRETCH_BLIT_SRC_FORMAT_PITCH                               15:0
+#define STRETCH_BLIT_SRC_FORMAT_ORIGIN                              23:16
+#define STRETCH_BLIT_SRC_FORMAT_ORIGIN_CENTER                       0x00000001
+#define STRETCH_BLIT_SRC_FORMAT_ORIGIN_CORNER                       0x00000002
+#define STRETCH_BLIT_SRC_FORMAT_FILTER                              31:24
+#define STRETCH_BLIT_SRC_FORMAT_FILTER_POINT_SAMPLE                 0x00000000
+#define STRETCH_BLIT_SRC_FORMAT_FILTER_BILINEAR                     0x00000001
+#define STRETCH_BLIT_SRC_OFFSET                                     0x0000E408
+#define STRETCH_BLIT_SRC_POINT                                      0x0000E40C
+#define STRETCH_BLIT_SRC_POINT_U                                    15:0
+#define STRETCH_BLIT_SRC_POINT_V                                    31:16
diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile
new file mode 100644 (file)
index 0000000..7bb4798
--- /dev/null
@@ -0,0 +1,13 @@
+
+
+obj-y  += console/
+obj-y  += evtchn/
+obj-y  += balloon/
+
+obj-$(CONFIG_XEN_PRIVILEGED_GUEST)     += privcmd/
+obj-$(CONFIG_XEN_BLKDEV_BACKEND)       += blkback/
+obj-$(CONFIG_XEN_NETDEV_BACKEND)       += netback/
+obj-$(CONFIG_XEN_BLKDEV_FRONTEND)      += blkfront/
+obj-$(CONFIG_XEN_NETDEV_FRONTEND)      += netfront/
+obj-$(CONFIG_XEN_BLKDEV_TAP)           += blktap/
+
diff --git a/drivers/xen/balloon/Makefile b/drivers/xen/balloon/Makefile
new file mode 100644 (file)
index 0000000..0e3a348
--- /dev/null
@@ -0,0 +1,2 @@
+
+obj-y += balloon.o
diff --git a/drivers/xen/balloon/balloon.c b/drivers/xen/balloon/balloon.c
new file mode 100644 (file)
index 0000000..649f64c
--- /dev/null
@@ -0,0 +1,438 @@
+/******************************************************************************
+ * balloon.c
+ *
+ * Xen balloon driver - enables returning/claiming memory to/from Xen.
+ *
+ * Copyright (c) 2003, B Dragovic
+ * Copyright (c) 2003-2004, M Williamson, K Fraser
+ * 
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/smp_lock.h>
+#include <linux/pagemap.h>
+#include <linux/bootmem.h>
+#include <linux/highmem.h>
+#include <linux/vmalloc.h>
+#include <asm-xen/xen_proc.h>
+#include <asm-xen/hypervisor.h>
+#include <asm-xen/ctrl_if.h>
+#include <asm-xen/balloon.h>
+#include <asm/pgalloc.h>
+#include <asm/pgtable.h>
+#include <asm/uaccess.h>
+#include <asm/tlb.h>
+#include <linux/list.h>
+
+static struct proc_dir_entry *balloon_pde;
+
+static DECLARE_MUTEX(balloon_mutex);
+spinlock_t balloon_lock = SPIN_LOCK_UNLOCKED;
+
+/* We aim for 'current allocation' == 'target allocation'. */
+static unsigned long current_pages;
+static unsigned long target_pages;
+
+/* We may hit the hard limit in Xen. If we do then we remember it. */
+static unsigned long hard_limit;
+
+/*
+ * Drivers may alter the memory reservation independently, but they must
+ * inform the balloon driver so that we can avoid hitting the hard limit.
+ */
+static unsigned long driver_pages;
+
+/* List of ballooned pages, threaded through the mem_map array. */
+static LIST_HEAD(ballooned_pages);
+static unsigned long balloon_low, balloon_high;
+
+/* Main work function, always executed in process context. */
+static void balloon_process(void *unused);
+static DECLARE_WORK(balloon_worker, balloon_process, NULL);
+static struct timer_list balloon_timer;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+/* Use the private and mapping fields of struct page as a list. */
+#define PAGE_TO_LIST(p) ( (struct list_head *)&p->private )
+#define LIST_TO_PAGE(l) ( list_entry( ((unsigned long *)l),   \
+                                     struct page, private ) )
+#define UNLIST_PAGE(p)  do { list_del(PAGE_TO_LIST(p));       \
+                             p->mapping = NULL;               \
+                             p->private = 0; } while(0)
+#else
+/* There's a dedicated list field in struct page we can use.    */
+#define PAGE_TO_LIST(p) ( &p->list )
+#define LIST_TO_PAGE(l) ( list_entry(l, struct page, list) )
+#define UNLIST_PAGE(p)  ( list_del(&p->list) )
+#define pte_offset_kernel pte_offset
+#define pud_t pgd_t
+#define pud_offset(d, va) d
+#define pud_none(d) 0
+#define pud_bad(d) 0
+#define subsys_initcall(_fn) __initcall(_fn)
+#define pfn_to_page(_pfn) (mem_map + (_pfn))
+#endif
+
+#define IPRINTK(fmt, args...) \
+    printk(KERN_INFO "xen_mem: " fmt, ##args)
+#define WPRINTK(fmt, args...) \
+    printk(KERN_WARNING "xen_mem: " fmt, ##args)
+
+/* balloon_append: add the given page to the balloon. */
+static void balloon_append(struct page *page)
+{
+    /* Low memory is re-populated first, so highmem pages go at list tail. */
+    if ( PageHighMem(page) )
+    {
+        list_add_tail(PAGE_TO_LIST(page), &ballooned_pages);
+        balloon_high++;
+    }
+    else
+    {
+        list_add(PAGE_TO_LIST(page), &ballooned_pages);
+        balloon_low++;
+    }
+}
+
+/* balloon_retrieve: rescue a page from the balloon, if it is not empty. */
+static struct page *balloon_retrieve(void)
+{
+    struct page *page;
+
+    if ( list_empty(&ballooned_pages) )
+        return NULL;
+
+    page = LIST_TO_PAGE(ballooned_pages.next);
+    UNLIST_PAGE(page);
+
+    if ( PageHighMem(page) )
+        balloon_high--;
+    else
+        balloon_low--;
+
+    return page;
+}
+
+static void balloon_alarm(unsigned long unused)
+{
+    schedule_work(&balloon_worker);
+}
+
+static unsigned long current_target(void)
+{
+    unsigned long target = min(target_pages, hard_limit);
+    if ( target > (current_pages + balloon_low + balloon_high) )
+        target = current_pages + balloon_low + balloon_high;
+    return target;
+}
+
+/*
+ * We avoid multiple worker processes conflicting via the balloon mutex.
+ * We may of course race updates of the target counts (which are protected
+ * by the balloon lock), or with changes to the Xen hard limit, but we will
+ * recover from these in time.
+ */
+static void balloon_process(void *unused)
+{
+    unsigned long *mfn_list, pfn, i, flags;
+    struct page   *page;
+    long           credit, debt, rc;
+    void          *v;
+
+    down(&balloon_mutex);
+
+ retry:
+    mfn_list = NULL;
+
+    if ( (credit = current_target() - current_pages) > 0 )
+    {
+        mfn_list = (unsigned long *)vmalloc(credit * sizeof(*mfn_list));
+        if ( mfn_list == NULL )
+            goto out;
+
+        balloon_lock(flags);
+        rc = HYPERVISOR_dom_mem_op(
+            MEMOP_increase_reservation, mfn_list, credit, 0);
+        balloon_unlock(flags);
+        if ( rc < credit )
+        {
+            /* We hit the Xen hard limit: reprobe. */
+            if ( HYPERVISOR_dom_mem_op(
+                MEMOP_decrease_reservation, mfn_list, rc, 0) != rc )
+                BUG();
+            hard_limit = current_pages + rc - driver_pages;
+            vfree(mfn_list);
+            goto retry;
+        }
+
+        for ( i = 0; i < credit; i++ )
+        {
+            if ( (page = balloon_retrieve()) == NULL )
+                BUG();
+
+            pfn = page - mem_map;
+            if ( phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY )
+                BUG();
+
+            /* Update P->M and M->P tables. */
+            phys_to_machine_mapping[pfn] = mfn_list[i];
+            xen_machphys_update(mfn_list[i], pfn);
+            
+            /* Link back into the page tables if it's not a highmem page. */
+            if ( pfn < max_low_pfn )
+            {
+                HYPERVISOR_update_va_mapping(
+                    (unsigned long)__va(pfn << PAGE_SHIFT),
+                    __pte_ma((mfn_list[i] << PAGE_SHIFT) |
+                             pgprot_val(PAGE_KERNEL)),
+                    0);
+            }
+
+            /* Finally, relinquish the memory back to the system allocator. */
+            ClearPageReserved(page);
+            set_page_count(page, 1);
+            __free_page(page);
+        }
+
+        current_pages += credit;
+    }
+    else if ( credit < 0 )
+    {
+        debt = -credit;
+
+        mfn_list = (unsigned long *)vmalloc(debt * sizeof(*mfn_list));
+        if ( mfn_list == NULL )
+            goto out;
+
+        for ( i = 0; i < debt; i++ )
+        {
+            if ( (page = alloc_page(GFP_HIGHUSER)) == NULL )
+            {
+                debt = i;
+                break;
+            }
+
+            pfn = page - mem_map;
+            mfn_list[i] = phys_to_machine_mapping[pfn];
+
+            if ( !PageHighMem(page) )
+            {
+                v = phys_to_virt(pfn << PAGE_SHIFT);
+                scrub_pages(v, 1);
+                HYPERVISOR_update_va_mapping(
+                    (unsigned long)v, __pte_ma(0), 0);
+            }
+#ifdef CONFIG_XEN_SCRUB_PAGES
+            else
+            {
+                v = kmap(page);
+                scrub_pages(v, 1);
+                kunmap(page);
+            }
+#endif
+        }
+
+        /* Ensure that ballooned highmem pages don't have cached mappings. */
+        kmap_flush_unused();
+        flush_tlb_all();
+
+        /* No more mappings: invalidate pages in P2M and add to balloon. */
+        for ( i = 0; i < debt; i++ )
+        {
+            pfn = mfn_to_pfn(mfn_list[i]);
+            phys_to_machine_mapping[pfn] = INVALID_P2M_ENTRY;
+            balloon_append(pfn_to_page(pfn));
+        }
+
+        if ( HYPERVISOR_dom_mem_op(
+            MEMOP_decrease_reservation, mfn_list, debt, 0) != debt )
+            BUG();
+
+        current_pages -= debt;
+    }
+
+ out:
+    if ( mfn_list != NULL )
+        vfree(mfn_list);
+
+    /* Schedule more work if there is some still to be done. */
+    if ( current_target() != current_pages )
+        mod_timer(&balloon_timer, jiffies + HZ);
+
+    up(&balloon_mutex);
+}
+
+/* Resets the Xen limit, sets new target, and kicks off processing. */
+static void set_new_target(unsigned long target)
+{
+    /* No need for lock. Not read-modify-write updates. */
+    hard_limit   = ~0UL;
+    target_pages = target;
+    schedule_work(&balloon_worker);
+}
+
+static void balloon_ctrlif_rx(ctrl_msg_t *msg, unsigned long id)
+{
+    switch ( msg->subtype )
+    {
+    case CMSG_MEM_REQUEST_SET:
+    {
+        mem_request_t *req = (mem_request_t *)&msg->msg[0];
+        set_new_target(req->target);
+        req->status = 0;
+    }
+    break;        
+
+    default:
+        msg->length = 0;
+        break;
+    }
+
+    ctrl_if_send_response(msg);
+}
+
+static int balloon_write(struct file *file, const char __user *buffer,
+                         unsigned long count, void *data)
+{
+    char memstring[64], *endchar;
+    unsigned long long target_bytes;
+
+    if ( !capable(CAP_SYS_ADMIN) )
+        return -EPERM;
+
+    if ( count <= 1 )
+        return -EBADMSG; /* runt */
+    if ( count > sizeof(memstring) )
+        return -EFBIG;   /* too long */
+
+    if ( copy_from_user(memstring, buffer, count) )
+        return -EFAULT;
+    memstring[sizeof(memstring)-1] = '\0';
+
+    target_bytes = memparse(memstring, &endchar);
+    set_new_target(target_bytes >> PAGE_SHIFT);
+
+    return count;
+}
+
+static int balloon_read(char *page, char **start, off_t off,
+                        int count, int *eof, void *data)
+{
+    int len;
+
+#define K(_p) ((_p)<<(PAGE_SHIFT-10))
+    len = sprintf(
+        page,
+        "Current allocation: %8lu kB\n"
+        "Requested target:   %8lu kB\n"
+        "Low-mem balloon:    %8lu kB\n"
+        "High-mem balloon:   %8lu kB\n"
+        "Xen hard limit:     ",
+        K(current_pages), K(target_pages), K(balloon_low), K(balloon_high));
+
+    if ( hard_limit != ~0UL )
+        len += sprintf(
+            page + len, 
+            "%8lu kB (inc. %8lu kB driver headroom)\n",
+            K(hard_limit), K(driver_pages));
+    else
+        len += sprintf(
+            page + len,
+            "     ??? kB\n");
+
+    *eof = 1;
+    return len;
+}
+
+static int __init balloon_init(void)
+{
+    unsigned long pfn;
+    struct page *page;
+
+    IPRINTK("Initialising balloon driver.\n");
+
+    current_pages = min(xen_start_info.nr_pages, max_pfn);
+    target_pages  = current_pages;
+    balloon_low   = 0;
+    balloon_high  = 0;
+    driver_pages  = 0UL;
+    hard_limit    = ~0UL;
+
+    init_timer(&balloon_timer);
+    balloon_timer.data = 0;
+    balloon_timer.function = balloon_alarm;
+    
+    if ( (balloon_pde = create_xen_proc_entry("balloon", 0644)) == NULL )
+    {
+        WPRINTK("Unable to create /proc/xen/balloon.\n");
+        return -1;
+    }
+
+    balloon_pde->read_proc  = balloon_read;
+    balloon_pde->write_proc = balloon_write;
+
+    (void)ctrl_if_register_receiver(CMSG_MEM_REQUEST, balloon_ctrlif_rx, 0);
+
+    /* Initialise the balloon with excess memory space. */
+    for ( pfn = xen_start_info.nr_pages; pfn < max_pfn; pfn++ )
+    {
+        page = &mem_map[pfn];
+        if ( !PageReserved(page) )
+            balloon_append(page);
+    }
+
+    return 0;
+}
+
+subsys_initcall(balloon_init);
+
+void balloon_update_driver_allowance(long delta)
+{
+    unsigned long flags;
+    balloon_lock(flags);
+    driver_pages += delta; /* non-atomic update */
+    balloon_unlock(flags);
+}
+
+void balloon_put_pages(unsigned long *mfn_list, unsigned long nr_mfns)
+{
+    unsigned long flags;
+
+    balloon_lock(flags);
+    if ( HYPERVISOR_dom_mem_op(MEMOP_decrease_reservation, 
+                               mfn_list, nr_mfns, 0) != nr_mfns )
+        BUG();
+    current_pages -= nr_mfns; /* non-atomic update */
+    balloon_unlock(flags);
+
+    schedule_work(&balloon_worker);
+}
+
+EXPORT_SYMBOL(balloon_update_driver_allowance);
+EXPORT_SYMBOL(balloon_put_pages);
diff --git a/drivers/xen/blkback/Makefile b/drivers/xen/blkback/Makefile
new file mode 100644 (file)
index 0000000..a27fe65
--- /dev/null
@@ -0,0 +1,2 @@
+
+obj-y  := blkback.o control.o interface.o vbd.o
diff --git a/drivers/xen/blkback/blkback.c b/drivers/xen/blkback/blkback.c
new file mode 100644 (file)
index 0000000..2554f99
--- /dev/null
@@ -0,0 +1,751 @@
+/******************************************************************************
+ * arch/xen/drivers/blkif/backend/main.c
+ * 
+ * Back-end of the driver for virtual block devices. This portion of the
+ * driver exports a 'unified' block-device interface that can be accessed
+ * by any operating system that implements a compatible front end. A 
+ * reference front-end implementation can be found in:
+ *  arch/xen/drivers/blkif/frontend
+ * 
+ * Copyright (c) 2003-2004, Keir Fraser & Steve Hand
+ * Copyright (c) 2005, Christopher Clark
+ */
+
+#include "common.h"
+#include <asm-xen/evtchn.h>
+#ifdef CONFIG_XEN_BLKDEV_GRANT
+#include <asm-xen/xen-public/grant_table.h>
+#endif
+
+/*
+ * These are rather arbitrary. They are fairly large because adjacent requests
+ * pulled from a communication ring are quite likely to end up being part of
+ * the same scatter/gather request at the disc.
+ * 
+ * ** TRY INCREASING 'MAX_PENDING_REQS' IF WRITE SPEEDS SEEM TOO LOW **
+ * This will increase the chances of being able to write whole tracks.
+ * 64 should be enough to keep us competitive with Linux.
+ */
+#define MAX_PENDING_REQS 64
+#define BATCH_PER_DOMAIN 16
+
+static unsigned long mmap_vstart;
+#define MMAP_PAGES                                              \
+    (MAX_PENDING_REQS * BLKIF_MAX_SEGMENTS_PER_REQUEST)
+#define MMAP_VADDR(_req,_seg)                                   \
+    (mmap_vstart +                                              \
+     ((_req) * BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE) +    \
+     ((_seg) * PAGE_SIZE))
+
+/*
+ * Each outstanding request that we've passed to the lower device layers has a 
+ * 'pending_req' allocated to it. Each buffer_head that completes decrements 
+ * the pendcnt towards zero. When it hits zero, the specified domain has a 
+ * response queued for it, with the saved 'id' passed back.
+ */
+typedef struct {
+    blkif_t       *blkif;
+    unsigned long  id;
+    int            nr_pages;
+    atomic_t       pendcnt;
+    unsigned short operation;
+    int            status;
+} pending_req_t;
+
+/*
+ * We can't allocate pending_req's in order, since they may complete out of 
+ * order. We therefore maintain an allocation ring. This ring also indicates 
+ * when enough work has been passed down -- at that point the allocation ring 
+ * will be empty.
+ */
+static pending_req_t pending_reqs[MAX_PENDING_REQS];
+static unsigned char pending_ring[MAX_PENDING_REQS];
+static spinlock_t pend_prod_lock = SPIN_LOCK_UNLOCKED;
+/* NB. We use a different index type to differentiate from shared blk rings. */
+typedef unsigned int PEND_RING_IDX;
+#define MASK_PEND_IDX(_i) ((_i)&(MAX_PENDING_REQS-1))
+static PEND_RING_IDX pending_prod, pending_cons;
+#define NR_PENDING_REQS (MAX_PENDING_REQS - pending_prod + pending_cons)
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+static kmem_cache_t *buffer_head_cachep;
+#else
+static request_queue_t *plugged_queue;
+static inline void flush_plugged_queue(void)
+{
+    request_queue_t *q = plugged_queue;
+    if ( q != NULL )
+    {
+        if ( q->unplug_fn != NULL )
+            q->unplug_fn(q);
+        blk_put_queue(q);
+        plugged_queue = NULL;
+    }
+}
+#endif
+
+#ifdef CONFIG_XEN_BLKDEV_GRANT
+/* When using grant tables to map a frame for device access then the
+ * handle returned must be used to unmap the frame. This is needed to
+ * drop the ref count on the frame.
+ */
+static u16 pending_grant_handles[MMAP_PAGES];
+#define pending_handle(_idx, _i) \
+    (pending_grant_handles[((_idx) * BLKIF_MAX_SEGMENTS_PER_REQUEST) + (_i)])
+#define BLKBACK_INVALID_HANDLE (0xFFFF)
+#endif
+
+#ifdef CONFIG_XEN_BLKDEV_TAP_BE
+/*
+ * If the tap driver is used, we may get pages belonging to either the tap
+ * or (more likely) the real frontend.  The backend must specify which domain
+ * a given page belongs to in update_va_mapping though.  For the moment, 
+ * the tap rewrites the ID field of the request to contain the request index
+ * and the id of the real front end domain.
+ */
+#define BLKTAP_COOKIE 0xbeadfeed
+static inline domid_t ID_TO_DOM(unsigned long id) { return (id >> 16); }
+#endif
+
+static int do_block_io_op(blkif_t *blkif, int max_to_do);
+static void dispatch_probe(blkif_t *blkif, blkif_request_t *req);
+static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req);
+static void make_response(blkif_t *blkif, unsigned long id, 
+                          unsigned short op, int st);
+
+static void fast_flush_area(int idx, int nr_pages)
+{
+#ifdef CONFIG_XEN_BLKDEV_GRANT
+    gnttab_op_t       aop[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+    unsigned int      i, invcount = 0;
+    u16               handle;
+
+    for ( i = 0; i < nr_pages; i++ )
+    {
+        if ( BLKBACK_INVALID_HANDLE != ( handle = pending_handle(idx, i) ) )
+        {
+            aop[i].u.unmap_grant_ref.host_virt_addr = MMAP_VADDR(idx, i);
+            aop[i].u.unmap_grant_ref.dev_bus_addr   = 0;
+            aop[i].u.unmap_grant_ref.handle         = handle;
+            pending_handle(idx, i) = BLKBACK_INVALID_HANDLE;
+            invcount++;
+        }
+    }
+    if ( unlikely(HYPERVISOR_grant_table_op(
+                    GNTTABOP_unmap_grant_ref, aop, invcount)))
+        BUG();
+#else
+
+    multicall_entry_t mcl[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+    int               i;
+
+    for ( i = 0; i < nr_pages; i++ )
+    {
+        mcl[i].op = __HYPERVISOR_update_va_mapping;
+        mcl[i].args[0] = MMAP_VADDR(idx, i);
+        mcl[i].args[1] = 0;
+        mcl[i].args[2] = 0;
+    }
+
+    mcl[nr_pages-1].args[2] = UVMF_TLB_FLUSH|UVMF_ALL;
+    if ( unlikely(HYPERVISOR_multicall(mcl, nr_pages) != 0) )
+        BUG();
+#endif
+}
+
+
+/******************************************************************
+ * BLOCK-DEVICE SCHEDULER LIST MAINTENANCE
+ */
+
+static struct list_head blkio_schedule_list;
+static spinlock_t blkio_schedule_list_lock;
+
+static int __on_blkdev_list(blkif_t *blkif)
+{
+    return blkif->blkdev_list.next != NULL;
+}
+
+static void remove_from_blkdev_list(blkif_t *blkif)
+{
+    unsigned long flags;
+    if ( !__on_blkdev_list(blkif) ) return;
+    spin_lock_irqsave(&blkio_schedule_list_lock, flags);
+    if ( __on_blkdev_list(blkif) )
+    {
+        list_del(&blkif->blkdev_list);
+        blkif->blkdev_list.next = NULL;
+        blkif_put(blkif);
+    }
+    spin_unlock_irqrestore(&blkio_schedule_list_lock, flags);
+}
+
+static void add_to_blkdev_list_tail(blkif_t *blkif)
+{
+    unsigned long flags;
+    if ( __on_blkdev_list(blkif) ) return;
+    spin_lock_irqsave(&blkio_schedule_list_lock, flags);
+    if ( !__on_blkdev_list(blkif) && (blkif->status == CONNECTED) )
+    {
+        list_add_tail(&blkif->blkdev_list, &blkio_schedule_list);
+        blkif_get(blkif);
+    }
+    spin_unlock_irqrestore(&blkio_schedule_list_lock, flags);
+}
+
+
+/******************************************************************
+ * SCHEDULER FUNCTIONS
+ */
+
+static DECLARE_WAIT_QUEUE_HEAD(blkio_schedule_wait);
+
+static int blkio_schedule(void *arg)
+{
+    DECLARE_WAITQUEUE(wq, current);
+
+    blkif_t          *blkif;
+    struct list_head *ent;
+
+    daemonize(
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+        "xenblkd"
+#endif
+        );
+
+    for ( ; ; )
+    {
+        /* Wait for work to do. */
+        add_wait_queue(&blkio_schedule_wait, &wq);
+        set_current_state(TASK_INTERRUPTIBLE);
+        if ( (NR_PENDING_REQS == MAX_PENDING_REQS) || 
+             list_empty(&blkio_schedule_list) )
+            schedule();
+        __set_current_state(TASK_RUNNING);
+        remove_wait_queue(&blkio_schedule_wait, &wq);
+
+        /* Queue up a batch of requests. */
+        while ( (NR_PENDING_REQS < MAX_PENDING_REQS) &&
+                !list_empty(&blkio_schedule_list) )
+        {
+            ent = blkio_schedule_list.next;
+            blkif = list_entry(ent, blkif_t, blkdev_list);
+            blkif_get(blkif);
+            remove_from_blkdev_list(blkif);
+            if ( do_block_io_op(blkif, BATCH_PER_DOMAIN) )
+                add_to_blkdev_list_tail(blkif);
+            blkif_put(blkif);
+        }
+
+        /* Push the batch through to disc. */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+        run_task_queue(&tq_disk);
+#else
+        flush_plugged_queue();
+#endif
+    }
+}
+
+static void maybe_trigger_blkio_schedule(void)
+{
+    /*
+     * Needed so that two processes, who together make the following predicate
+     * true, don't both read stale values and evaluate the predicate
+     * incorrectly. Incredibly unlikely to stall the scheduler on x86, but...
+     */
+    smp_mb();
+
+    if ( (NR_PENDING_REQS < (MAX_PENDING_REQS/2)) &&
+         !list_empty(&blkio_schedule_list) )
+        wake_up(&blkio_schedule_wait);
+}
+
+
+
+/******************************************************************
+ * COMPLETION CALLBACK -- Called as bh->b_end_io()
+ */
+
+static void __end_block_io_op(pending_req_t *pending_req, int uptodate)
+{
+    unsigned long flags;
+
+    /* An error fails the entire request. */
+    if ( !uptodate )
+    {
+        DPRINTK("Buffer not up-to-date at end of operation\n");
+        pending_req->status = BLKIF_RSP_ERROR;
+    }
+
+    if ( atomic_dec_and_test(&pending_req->pendcnt) )
+    {
+        int pending_idx = pending_req - pending_reqs;
+        fast_flush_area(pending_idx, pending_req->nr_pages);
+        make_response(pending_req->blkif, pending_req->id,
+                      pending_req->operation, pending_req->status);
+        blkif_put(pending_req->blkif);
+        spin_lock_irqsave(&pend_prod_lock, flags);
+        pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx;
+        spin_unlock_irqrestore(&pend_prod_lock, flags);
+        maybe_trigger_blkio_schedule();
+    }
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+static void end_block_io_op(struct buffer_head *bh, int uptodate)
+{
+    __end_block_io_op(bh->b_private, uptodate);
+    kmem_cache_free(buffer_head_cachep, bh);
+}
+#else
+static int end_block_io_op(struct bio *bio, unsigned int done, int error)
+{
+    if ( done || error )
+        __end_block_io_op(bio->bi_private, (done && !error));
+    bio_put(bio);
+    return error;
+}
+#endif
+
+
+/******************************************************************************
+ * NOTIFICATION FROM GUEST OS.
+ */
+
+irqreturn_t blkif_be_int(int irq, void *dev_id, struct pt_regs *regs)
+{
+    blkif_t *blkif = dev_id;
+    add_to_blkdev_list_tail(blkif);
+    maybe_trigger_blkio_schedule();
+    return IRQ_HANDLED;
+}
+
+
+
+/******************************************************************
+ * DOWNWARD CALLS -- These interface with the block-device layer proper.
+ */
+
+static int do_block_io_op(blkif_t *blkif, int max_to_do)
+{
+    blkif_back_ring_t *blk_ring = &blkif->blk_ring;
+    blkif_request_t *req;
+    RING_IDX i, rp;
+    int more_to_do = 0;
+
+    rp = blk_ring->sring->req_prod;
+    rmb(); /* Ensure we see queued requests up to 'rp'. */
+
+    for ( i = blk_ring->req_cons; 
+         (i != rp) && !RING_REQUEST_CONS_OVERFLOW(blk_ring, i);
+          i++ )
+    {
+        if ( (max_to_do-- == 0) || (NR_PENDING_REQS == MAX_PENDING_REQS) )
+        {
+            more_to_do = 1;
+            break;
+        }
+        
+        req = RING_GET_REQUEST(blk_ring, i);
+        switch ( req->operation )
+        {
+        case BLKIF_OP_READ:
+        case BLKIF_OP_WRITE:
+            dispatch_rw_block_io(blkif, req);
+            break;
+
+        case BLKIF_OP_PROBE:
+            dispatch_probe(blkif, req);
+            break;
+
+        default:
+            DPRINTK("error: unknown block io operation [%d]\n",
+                    req->operation);
+            make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR);
+            break;
+        }
+    }
+
+    blk_ring->req_cons = i;
+    return more_to_do;
+}
+
+static void dispatch_probe(blkif_t *blkif, blkif_request_t *req)
+{
+    int rsp = BLKIF_RSP_ERROR;
+    int pending_idx = pending_ring[MASK_PEND_IDX(pending_cons)];
+
+    /* We expect one buffer only. */
+    if ( unlikely(req->nr_segments != 1) )
+        goto out;
+
+    /* Make sure the buffer is page-sized. */
+    if ( (blkif_first_sect(req->frame_and_sects[0]) != 0) ||
+         (blkif_last_sect(req->frame_and_sects[0]) != 7) )
+        goto out;
+
+#ifdef CONFIG_XEN_BLKDEV_GRANT
+    {
+        gnttab_op_t     op;
+
+        op.u.map_grant_ref.host_virt_addr = MMAP_VADDR(pending_idx, 0);
+        op.u.map_grant_ref.flags = GNTMAP_host_map;
+        op.u.map_grant_ref.ref = blkif_gref_from_fas(req->frame_and_sects[0]);
+        op.u.map_grant_ref.dom = blkif->domid;
+
+        if ( unlikely(HYPERVISOR_grant_table_op(
+                        GNTTABOP_map_grant_ref, &op, 1)))
+            BUG();
+
+        if ( op.u.map_grant_ref.handle < 0 )
+            goto out;
+
+        pending_handle(pending_idx, 0) = op.u.map_grant_ref.handle;
+    }
+#else /* else CONFIG_XEN_BLKDEV_GRANT */
+
+#ifdef CONFIG_XEN_BLKDEV_TAP_BE
+    /* Grab the real frontend out of the probe message. */
+    if (req->frame_and_sects[1] == BLKTAP_COOKIE) 
+        blkif->is_blktap = 1;
+#endif
+
+
+#ifdef CONFIG_XEN_BLKDEV_TAP_BE
+    if ( HYPERVISOR_update_va_mapping_otherdomain(
+        MMAP_VADDR(pending_idx, 0),
+        (pte_t) { (req->frame_and_sects[0] & PAGE_MASK) | __PAGE_KERNEL },
+        0, (blkif->is_blktap ? ID_TO_DOM(req->id) : blkif->domid) ) )
+        
+        goto out;
+#else
+    if ( HYPERVISOR_update_va_mapping_otherdomain(
+        MMAP_VADDR(pending_idx, 0),
+        (pte_t) { (req->frame_and_sects[0] & PAGE_MASK) | __PAGE_KERNEL },
+        0, blkif->domid) ) 
+        
+        goto out;
+#endif
+#endif /* endif CONFIG_XEN_BLKDEV_GRANT */
+   
+    rsp = vbd_probe(blkif, (vdisk_t *)MMAP_VADDR(pending_idx, 0), 
+                    PAGE_SIZE / sizeof(vdisk_t));
+
+ out:
+    fast_flush_area(pending_idx, 1);
+    make_response(blkif, req->id, req->operation, rsp);
+}
+
+static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req)
+{
+    extern void ll_rw_block(int rw, int nr, struct buffer_head * bhs[]); 
+    int operation = (req->operation == BLKIF_OP_WRITE) ? WRITE : READ;
+    unsigned long fas = 0;
+    int i, pending_idx = pending_ring[MASK_PEND_IDX(pending_cons)];
+    pending_req_t *pending_req;
+#ifdef CONFIG_XEN_BLKDEV_GRANT
+    gnttab_op_t       aop[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+#else
+    unsigned long remap_prot;
+    multicall_entry_t mcl[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+#endif
+    struct phys_req preq;
+    struct { 
+        unsigned long buf; unsigned int nsec;
+    } seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+    unsigned int nseg;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+    struct buffer_head *bh;
+#else
+    struct bio *bio = NULL, *biolist[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+    int nbio = 0;
+    request_queue_t *q;
+#endif
+
+    /* Check that number of segments is sane. */
+    nseg = req->nr_segments;
+    if ( unlikely(nseg == 0) || 
+         unlikely(nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST) )
+    {
+        DPRINTK("Bad number of segments in request (%d)\n", nseg);
+        goto bad_descriptor;
+    }
+
+    preq.dev           = req->device;
+    preq.sector_number = req->sector_number;
+    preq.nr_sects      = 0;
+
+#ifdef CONFIG_XEN_BLKDEV_GRANT
+    for ( i = 0; i < nseg; i++ )
+    {
+        fas         = req->frame_and_sects[i];
+        seg[i].nsec = blkif_last_sect(fas) - blkif_first_sect(fas) + 1;
+
+        if ( seg[i].nsec <= 0 )
+            goto bad_descriptor;
+        preq.nr_sects += seg[i].nsec;
+
+        aop[i].u.map_grant_ref.host_virt_addr = MMAP_VADDR(pending_idx, i);
+
+        aop[i].u.map_grant_ref.dom = blkif->domid;
+        aop[i].u.map_grant_ref.ref = blkif_gref_from_fas(fas);
+        aop[i].u.map_grant_ref.flags = ( GNTMAP_host_map   |
+                                       ( ( operation == READ ) ?
+                                             0 : GNTMAP_readonly ) );
+    }
+
+    if ( unlikely(HYPERVISOR_grant_table_op(
+                    GNTTABOP_map_grant_ref, aop, nseg)))
+        BUG();
+
+    for ( i = 0; i < nseg; i++ )
+    {
+        if ( unlikely(aop[i].u.map_grant_ref.handle < 0) )
+        {
+            DPRINTK("invalid buffer -- could not remap it\n");
+            fast_flush_area(pending_idx, nseg);
+            goto bad_descriptor;
+        }
+
+        phys_to_machine_mapping[__pa(MMAP_VADDR(pending_idx, i))>>PAGE_SHIFT] =
+            FOREIGN_FRAME(aop[i].u.map_grant_ref.dev_bus_addr);
+
+        pending_handle(pending_idx, i) = aop[i].u.map_grant_ref.handle;
+    }
+#endif
+
+    for ( i = 0; i < nseg; i++ )
+    {
+        fas         = req->frame_and_sects[i];
+#ifdef CONFIG_XEN_BLKDEV_GRANT
+        seg[i].buf  = (aop[i].u.map_grant_ref.dev_bus_addr << PAGE_SHIFT) |
+                      (blkif_first_sect(fas) << 9);
+#else
+        seg[i].buf  = (fas & PAGE_MASK) | (blkif_first_sect(fas) << 9);
+        seg[i].nsec = blkif_last_sect(fas) - blkif_first_sect(fas) + 1;
+        if ( seg[i].nsec <= 0 )
+            goto bad_descriptor;
+        preq.nr_sects += seg[i].nsec;
+#endif
+    }
+
+    if ( vbd_translate(&preq, blkif, operation) != 0 )
+    {
+        DPRINTK("access denied: %s of [%llu,%llu] on dev=%04x\n", 
+                operation == READ ? "read" : "write", preq.sector_number,
+                preq.sector_number + preq.nr_sects, preq.dev); 
+        goto bad_descriptor;
+    }
+
+#ifndef CONFIG_XEN_BLKDEV_GRANT
+    if ( operation == READ )
+        remap_prot = _PAGE_PRESENT|_PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_RW;
+    else
+        remap_prot = _PAGE_PRESENT|_PAGE_DIRTY|_PAGE_ACCESSED;
+
+    for ( i = 0; i < nseg; i++ )
+    {
+        mcl[i].op = __HYPERVISOR_update_va_mapping_otherdomain;
+        mcl[i].args[0] = MMAP_VADDR(pending_idx, i);
+        mcl[i].args[1] = (seg[i].buf & PAGE_MASK) | remap_prot;
+        mcl[i].args[2] = 0;
+        mcl[i].args[3] = blkif->domid;
+#ifdef CONFIG_XEN_BLKDEV_TAP_BE
+        if ( blkif->is_blktap )
+            mcl[i].args[3] = ID_TO_DOM(req->id);
+#endif
+        phys_to_machine_mapping[__pa(MMAP_VADDR(pending_idx, i))>>PAGE_SHIFT] =
+            FOREIGN_FRAME(seg[i].buf >> PAGE_SHIFT);
+    }
+
+    BUG_ON(HYPERVISOR_multicall(mcl, nseg) != 0);
+
+    for ( i = 0; i < nseg; i++ )
+    {
+        if ( unlikely(mcl[i].args[5] != 0) )
+        {
+            DPRINTK("invalid buffer -- could not remap it\n");
+            fast_flush_area(pending_idx, nseg);
+            goto bad_descriptor;
+        }
+    }
+#endif /* end ifndef CONFIG_XEN_BLKDEV_GRANT */
+
+    pending_req = &pending_reqs[pending_idx];
+    pending_req->blkif     = blkif;
+    pending_req->id        = req->id;
+    pending_req->operation = operation;
+    pending_req->status    = BLKIF_RSP_OKAY;
+    pending_req->nr_pages  = nseg;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+
+    atomic_set(&pending_req->pendcnt, nseg);
+    pending_cons++;
+    blkif_get(blkif);
+
+    for ( i = 0; i < nseg; i++ )
+    {
+        bh = kmem_cache_alloc(buffer_head_cachep, GFP_KERNEL);
+        if ( unlikely(bh == NULL) )
+        {
+            __end_block_io_op(pending_req, 0);
+            continue;
+        }
+
+        memset(bh, 0, sizeof (struct buffer_head));
+
+        init_waitqueue_head(&bh->b_wait);
+        bh->b_size          = seg[i].nsec << 9;
+        bh->b_dev           = preq.dev;
+        bh->b_rdev          = preq.dev;
+        bh->b_rsector       = (unsigned long)preq.sector_number;
+        bh->b_data          = (char *)MMAP_VADDR(pending_idx, i) +
+            (seg[i].buf & ~PAGE_MASK);
+        bh->b_page          = virt_to_page(MMAP_VADDR(pending_idx, i));
+        bh->b_end_io        = end_block_io_op;
+        bh->b_private       = pending_req;
+
+        bh->b_state = (1 << BH_Mapped) | (1 << BH_Lock) | 
+            (1 << BH_Req) | (1 << BH_Launder);
+        if ( operation == WRITE )
+            bh->b_state |= (1 << BH_JBD) | (1 << BH_Req) | (1 << BH_Uptodate);
+
+        atomic_set(&bh->b_count, 1);
+
+        /* Dispatch a single request. We'll flush it to disc later. */
+        generic_make_request(operation, bh);
+
+        preq.sector_number += seg[i].nsec;
+    }
+
+#else
+
+    for ( i = 0; i < nseg; i++ )
+    {
+        while ( (bio == NULL) ||
+                (bio_add_page(bio,
+                              virt_to_page(MMAP_VADDR(pending_idx, i)),
+                              seg[i].nsec << 9,
+                              seg[i].buf & ~PAGE_MASK) == 0) )
+        {
+            bio = biolist[nbio++] = bio_alloc(GFP_KERNEL, nseg-i);
+            if ( unlikely(bio == NULL) )
+            {
+                for ( i = 0; i < (nbio-1); i++ )
+                    bio_put(biolist[i]);
+                fast_flush_area(pending_idx, nseg);
+                goto bad_descriptor;
+            }
+                
+            bio->bi_bdev    = preq.bdev;
+            bio->bi_private = pending_req;
+            bio->bi_end_io  = end_block_io_op;
+            bio->bi_sector  = preq.sector_number;
+        }
+
+        preq.sector_number += seg[i].nsec;
+    }
+
+    if ( (q = bdev_get_queue(bio->bi_bdev)) != plugged_queue )
+    {
+        flush_plugged_queue();
+        blk_get_queue(q);
+        plugged_queue = q;
+    }
+
+    atomic_set(&pending_req->pendcnt, nbio);
+    pending_cons++;
+    blkif_get(blkif);
+
+    for ( i = 0; i < nbio; i++ )
+        submit_bio(operation, biolist[i]);
+
+#endif
+
+    return;
+
+ bad_descriptor:
+    make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR);
+} 
+
+
+
+/******************************************************************
+ * MISCELLANEOUS SETUP / TEARDOWN / DEBUGGING
+ */
+
+
+static void make_response(blkif_t *blkif, unsigned long id, 
+                          unsigned short op, int st)
+{
+    blkif_response_t *resp;
+    unsigned long     flags;
+    blkif_back_ring_t *blk_ring = &blkif->blk_ring;
+
+    /* Place on the response ring for the relevant domain. */ 
+    spin_lock_irqsave(&blkif->blk_ring_lock, flags);
+    resp = RING_GET_RESPONSE(blk_ring, blk_ring->rsp_prod_pvt);
+    resp->id        = id;
+    resp->operation = op;
+    resp->status    = st;
+    wmb(); /* Ensure other side can see the response fields. */
+    blk_ring->rsp_prod_pvt++;
+    RING_PUSH_RESPONSES(blk_ring);
+    spin_unlock_irqrestore(&blkif->blk_ring_lock, flags);
+
+    /* Kick the relevant domain. */
+    notify_via_evtchn(blkif->evtchn);
+}
+
+void blkif_deschedule(blkif_t *blkif)
+{
+    remove_from_blkdev_list(blkif);
+}
+
+static int __init blkif_init(void)
+{
+    int i;
+
+    if ( !(xen_start_info.flags & SIF_INITDOMAIN) &&
+         !(xen_start_info.flags & SIF_BLK_BE_DOMAIN) )
+        return 0;
+
+    blkif_interface_init();
+
+    if ( (mmap_vstart = allocate_empty_lowmem_region(MMAP_PAGES)) == 0 )
+        BUG();
+
+    pending_cons = 0;
+    pending_prod = MAX_PENDING_REQS;
+    memset(pending_reqs, 0, sizeof(pending_reqs));
+    for ( i = 0; i < MAX_PENDING_REQS; i++ )
+        pending_ring[i] = i;
+    
+    spin_lock_init(&blkio_schedule_list_lock);
+    INIT_LIST_HEAD(&blkio_schedule_list);
+
+    if ( kernel_thread(blkio_schedule, 0, CLONE_FS | CLONE_FILES) < 0 )
+        BUG();
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+    buffer_head_cachep = kmem_cache_create(
+        "buffer_head_cache", sizeof(struct buffer_head),
+        0, SLAB_HWCACHE_ALIGN, NULL, NULL);
+#endif
+
+    blkif_ctrlif_init();
+    
+#ifdef CONFIG_XEN_BLKDEV_GRANT
+    memset( pending_grant_handles,  BLKBACK_INVALID_HANDLE, MMAP_PAGES );
+    printk(KERN_ALERT "Blkif backend is using grant tables.\n");
+#endif
+
+#ifdef CONFIG_XEN_BLKDEV_TAP_BE
+    printk(KERN_ALERT "NOTE: Blkif backend is running with tap support on!\n");
+#endif
+
+    return 0;
+}
+
+__initcall(blkif_init);
diff --git a/drivers/xen/blkback/common.h b/drivers/xen/blkback/common.h
new file mode 100644 (file)
index 0000000..a698e01
--- /dev/null
@@ -0,0 +1,104 @@
+
+#ifndef __BLKIF__BACKEND__COMMON_H__
+#define __BLKIF__BACKEND__COMMON_H__
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/rbtree.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/blkdev.h>
+#include <asm/io.h>
+#include <asm/setup.h>
+#include <asm/pgalloc.h>
+#include <asm-xen/ctrl_if.h>
+#include <asm-xen/hypervisor.h>
+#include <asm-xen/xen-public/io/blkif.h>
+#include <asm-xen/xen-public/io/ring.h>
+
+#if 0
+#define ASSERT(_p) \
+    if ( !(_p) ) { printk("Assertion '%s' failed, line %d, file %s", #_p , \
+    __LINE__, __FILE__); *(int*)0=0; }
+#define DPRINTK(_f, _a...) printk(KERN_ALERT "(file=%s, line=%d) " _f, \
+                           __FILE__ , __LINE__ , ## _a )
+#else
+#define ASSERT(_p) ((void)0)
+#define DPRINTK(_f, _a...) ((void)0)
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+typedef struct rb_root rb_root_t;
+typedef struct rb_node rb_node_t;
+#else
+struct block_device;
+#endif
+
+typedef struct blkif_st {
+    /* Unique identifier for this interface. */
+    domid_t           domid;
+    unsigned int      handle;
+    /* Physical parameters of the comms window. */
+    unsigned long     shmem_frame;
+    unsigned int      evtchn;
+    int               irq;
+    /* Comms information. */
+    blkif_back_ring_t blk_ring;
+    /* VBDs attached to this interface. */
+    rb_root_t         vbd_rb;        /* Mapping from 16-bit vdevices to VBDs.*/
+    spinlock_t        vbd_lock;      /* Protects VBD mapping. */
+    /* Private fields. */
+    enum { DISCONNECTED, DISCONNECTING, CONNECTED } status;
+    /*
+     * DISCONNECT response is deferred until pending requests are ack'ed.
+     * We therefore need to store the id from the original request.
+     */
+    u8               disconnect_rspid;
+#ifdef CONFIG_XEN_BLKDEV_TAP_BE
+    /* Is this a blktap frontend */
+    unsigned int     is_blktap;
+#endif
+    struct blkif_st *hash_next;
+    struct list_head blkdev_list;
+    spinlock_t       blk_ring_lock;
+    atomic_t         refcnt;
+
+    struct work_struct work;
+} blkif_t;
+
+void blkif_create(blkif_be_create_t *create);
+void blkif_destroy(blkif_be_destroy_t *destroy);
+void blkif_connect(blkif_be_connect_t *connect);
+int  blkif_disconnect(blkif_be_disconnect_t *disconnect, u8 rsp_id);
+void blkif_disconnect_complete(blkif_t *blkif);
+blkif_t *blkif_find_by_handle(domid_t domid, unsigned int handle);
+#define blkif_get(_b) (atomic_inc(&(_b)->refcnt))
+#define blkif_put(_b)                             \
+    do {                                          \
+        if ( atomic_dec_and_test(&(_b)->refcnt) ) \
+            blkif_disconnect_complete(_b);        \
+    } while (0)
+
+void vbd_create(blkif_be_vbd_create_t *create); 
+void vbd_destroy(blkif_be_vbd_destroy_t *delete); 
+int vbd_probe(blkif_t *blkif, vdisk_t *vbd_info, int max_vbds);
+void destroy_all_vbds(blkif_t *blkif);
+
+struct phys_req {
+    unsigned short       dev;
+    unsigned short       nr_sects;
+    struct block_device *bdev;
+    blkif_sector_t       sector_number;
+};
+
+int vbd_translate(struct phys_req *req, blkif_t *blkif, int operation); 
+
+void blkif_interface_init(void);
+void blkif_ctrlif_init(void);
+
+void blkif_deschedule(blkif_t *blkif);
+
+irqreturn_t blkif_be_int(int irq, void *dev_id, struct pt_regs *regs);
+
+#endif /* __BLKIF__BACKEND__COMMON_H__ */
diff --git a/drivers/xen/blkback/interface.c b/drivers/xen/blkback/interface.c
new file mode 100644 (file)
index 0000000..46d55d1
--- /dev/null
@@ -0,0 +1,249 @@
+/******************************************************************************
+ * arch/xen/drivers/blkif/backend/interface.c
+ * 
+ * Block-device interface management.
+ * 
+ * Copyright (c) 2004, Keir Fraser
+ */
+
+#include "common.h"
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+#endif
+
+#define BLKIF_HASHSZ 1024
+#define BLKIF_HASH(_d,_h) (((int)(_d)^(int)(_h))&(BLKIF_HASHSZ-1))
+
+static kmem_cache_t *blkif_cachep;
+static blkif_t      *blkif_hash[BLKIF_HASHSZ];
+
+blkif_t *blkif_find_by_handle(domid_t domid, unsigned int handle)
+{
+    blkif_t *blkif = blkif_hash[BLKIF_HASH(domid, handle)];
+    while ( (blkif != NULL) && 
+            ((blkif->domid != domid) || (blkif->handle != handle)) )
+        blkif = blkif->hash_next;
+    return blkif;
+}
+
+static void __blkif_disconnect_complete(void *arg)
+{
+    blkif_t              *blkif = (blkif_t *)arg;
+    ctrl_msg_t            cmsg;
+    blkif_be_disconnect_t disc;
+
+    /*
+     * These can't be done in blkif_disconnect() because at that point there
+     * may be outstanding requests at the disc whose asynchronous responses
+     * must still be notified to the remote driver.
+     */
+    unbind_evtchn_from_irq(blkif->evtchn);
+    vfree(blkif->blk_ring.sring);
+
+    /* Construct the deferred response message. */
+    cmsg.type         = CMSG_BLKIF_BE;
+    cmsg.subtype      = CMSG_BLKIF_BE_DISCONNECT;
+    cmsg.id           = blkif->disconnect_rspid;
+    cmsg.length       = sizeof(blkif_be_disconnect_t);
+    disc.domid        = blkif->domid;
+    disc.blkif_handle = blkif->handle;
+    disc.status       = BLKIF_BE_STATUS_OKAY;
+    memcpy(cmsg.msg, &disc, sizeof(disc));
+
+    /*
+     * Make sure message is constructed /before/ status change, because
+     * after the status change the 'blkif' structure could be deallocated at
+     * any time. Also make sure we send the response /after/ status change,
+     * as otherwise a subsequent CONNECT request could spuriously fail if
+     * another CPU doesn't see the status change yet.
+     */
+    mb();
+    if ( blkif->status != DISCONNECTING )
+        BUG();
+    blkif->status = DISCONNECTED;
+    mb();
+
+    /* Send the successful response. */
+    ctrl_if_send_response(&cmsg);
+}
+
+void blkif_disconnect_complete(blkif_t *blkif)
+{
+    INIT_WORK(&blkif->work, __blkif_disconnect_complete, (void *)blkif);
+    schedule_work(&blkif->work);
+}
+
+void blkif_create(blkif_be_create_t *create)
+{
+    domid_t       domid  = create->domid;
+    unsigned int  handle = create->blkif_handle;
+    blkif_t     **pblkif, *blkif;
+
+    if ( (blkif = kmem_cache_alloc(blkif_cachep, GFP_KERNEL)) == NULL )
+    {
+        DPRINTK("Could not create blkif: out of memory\n");
+        create->status = BLKIF_BE_STATUS_OUT_OF_MEMORY;
+        return;
+    }
+
+    memset(blkif, 0, sizeof(*blkif));
+    blkif->domid  = domid;
+    blkif->handle = handle;
+    blkif->status = DISCONNECTED;
+    spin_lock_init(&blkif->vbd_lock);
+    spin_lock_init(&blkif->blk_ring_lock);
+    atomic_set(&blkif->refcnt, 0);
+
+    pblkif = &blkif_hash[BLKIF_HASH(domid, handle)];
+    while ( *pblkif != NULL )
+    {
+        if ( ((*pblkif)->domid == domid) && ((*pblkif)->handle == handle) )
+        {
+            DPRINTK("Could not create blkif: already exists\n");
+            create->status = BLKIF_BE_STATUS_INTERFACE_EXISTS;
+            kmem_cache_free(blkif_cachep, blkif);
+            return;
+        }
+        pblkif = &(*pblkif)->hash_next;
+    }
+
+    blkif->hash_next = *pblkif;
+    *pblkif = blkif;
+
+    DPRINTK("Successfully created blkif\n");
+    create->status = BLKIF_BE_STATUS_OKAY;
+}
+
+void blkif_destroy(blkif_be_destroy_t *destroy)
+{
+    domid_t       domid  = destroy->domid;
+    unsigned int  handle = destroy->blkif_handle;
+    blkif_t     **pblkif, *blkif;
+
+    pblkif = &blkif_hash[BLKIF_HASH(domid, handle)];
+    while ( (blkif = *pblkif) != NULL )
+    {
+        if ( (blkif->domid == domid) && (blkif->handle == handle) )
+        {
+            if ( blkif->status != DISCONNECTED )
+                goto still_connected;
+            goto destroy;
+        }
+        pblkif = &blkif->hash_next;
+    }
+
+    destroy->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND;
+    return;
+
+ still_connected:
+    destroy->status = BLKIF_BE_STATUS_INTERFACE_CONNECTED;
+    return;
+
+ destroy:
+    *pblkif = blkif->hash_next;
+    destroy_all_vbds(blkif);
+    kmem_cache_free(blkif_cachep, blkif);
+    destroy->status = BLKIF_BE_STATUS_OKAY;
+}
+
+void blkif_connect(blkif_be_connect_t *connect)
+{
+    domid_t        domid  = connect->domid;
+    unsigned int   handle = connect->blkif_handle;
+    unsigned int   evtchn = connect->evtchn;
+    unsigned long  shmem_frame = connect->shmem_frame;
+    struct vm_struct *vma;
+    pgprot_t       prot;
+    int            error;
+    blkif_t       *blkif;
+    blkif_sring_t *sring;
+
+    blkif = blkif_find_by_handle(domid, handle);
+    if ( unlikely(blkif == NULL) )
+    {
+        DPRINTK("blkif_connect attempted for non-existent blkif (%u,%u)\n", 
+                connect->domid, connect->blkif_handle); 
+        connect->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND;
+        return;
+    }
+
+    if ( (vma = get_vm_area(PAGE_SIZE, VM_IOREMAP)) == NULL )
+    {
+        connect->status = BLKIF_BE_STATUS_OUT_OF_MEMORY;
+        return;
+    }
+
+    prot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED);
+    error = direct_remap_area_pages(&init_mm, VMALLOC_VMADDR(vma->addr),
+                                    shmem_frame<<PAGE_SHIFT, PAGE_SIZE,
+                                    prot, domid);
+    if ( error != 0 )
+    {
+        if ( error == -ENOMEM )
+            connect->status = BLKIF_BE_STATUS_OUT_OF_MEMORY;
+        else if ( error == -EFAULT )
+            connect->status = BLKIF_BE_STATUS_MAPPING_ERROR;
+        else
+            connect->status = BLKIF_BE_STATUS_ERROR;
+        vfree(vma->addr);
+        return;
+    }
+
+    if ( blkif->status != DISCONNECTED )
+    {
+        connect->status = BLKIF_BE_STATUS_INTERFACE_CONNECTED;
+        vfree(vma->addr);
+        return;
+    }
+    sring = (blkif_sring_t *)vma->addr;
+    SHARED_RING_INIT(sring);
+    BACK_RING_INIT(&blkif->blk_ring, sring, PAGE_SIZE);
+    
+    blkif->evtchn        = evtchn;
+    blkif->irq           = bind_evtchn_to_irq(evtchn);
+    blkif->shmem_frame   = shmem_frame;
+    blkif->status        = CONNECTED;
+    blkif_get(blkif);
+
+    request_irq(blkif->irq, blkif_be_int, 0, "blkif-backend", blkif);
+
+    connect->status = BLKIF_BE_STATUS_OKAY;
+}
+
+int blkif_disconnect(blkif_be_disconnect_t *disconnect, u8 rsp_id)
+{
+    domid_t       domid  = disconnect->domid;
+    unsigned int  handle = disconnect->blkif_handle;
+    blkif_t      *blkif;
+
+    blkif = blkif_find_by_handle(domid, handle);
+    if ( unlikely(blkif == NULL) )
+    {
+        DPRINTK("blkif_disconnect attempted for non-existent blkif"
+                " (%u,%u)\n", disconnect->domid, disconnect->blkif_handle); 
+        disconnect->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND;
+        return 1; /* Caller will send response error message. */
+    }
+
+    if ( blkif->status == CONNECTED )
+    {
+        blkif->status = DISCONNECTING;
+        blkif->disconnect_rspid = rsp_id;
+        wmb(); /* Let other CPUs see the status change. */
+        free_irq(blkif->irq, blkif);
+        blkif_deschedule(blkif);
+        blkif_put(blkif);
+        return 0; /* Caller should not send response message. */
+    }
+
+    disconnect->status = BLKIF_BE_STATUS_OKAY;
+    return 1;
+}
+
+void __init blkif_interface_init(void)
+{
+    blkif_cachep = kmem_cache_create("blkif_cache", sizeof(blkif_t), 
+                                     0, 0, NULL, NULL);
+    memset(blkif_hash, 0, sizeof(blkif_hash));
+}
diff --git a/drivers/xen/blkback/vbd.c b/drivers/xen/blkback/vbd.c
new file mode 100644 (file)
index 0000000..f5ee589
--- /dev/null
@@ -0,0 +1,287 @@
+/******************************************************************************
+ * blkback/vbd.c
+ * 
+ * Routines for managing virtual block devices (VBDs).
+ * 
+ * NOTE: vbd_lock protects updates to the rb_tree against concurrent lookups 
+ * in vbd_translate.  All other lookups are implicitly protected because the 
+ * only caller (the control message dispatch routine) serializes the calls.
+ * 
+ * Copyright (c) 2003-2005, Keir Fraser & Steve Hand
+ */
+
+#include "common.h"
+
+struct vbd { 
+    blkif_vdev_t   vdevice;     /* what the domain refers to this vbd as */
+    unsigned char  readonly;    /* Non-zero -> read-only */
+    unsigned char  type;        /* VDISK_TYPE_xxx */
+    blkif_pdev_t   pdevice;     /* phys device that this vbd maps to */
+    struct block_device *bdev;
+    rb_node_t      rb;          /* for linking into R-B tree lookup struct */
+}; 
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+static inline dev_t vbd_map_devnum(blkif_pdev_t cookie)
+{ return MKDEV(cookie>>8, cookie&0xff); }
+#define vbd_sz(_v)   ((_v)->bdev->bd_part ? \
+    (_v)->bdev->bd_part->nr_sects : (_v)->bdev->bd_disk->capacity)
+#define bdev_put(_b) blkdev_put(_b)
+#else
+#define vbd_sz(_v)   (blk_size[MAJOR((_v)->pdevice)][MINOR((_v)->pdevice)]*2)
+#define bdev_put(_b) ((void)0)
+#endif
+
+void vbd_create(blkif_be_vbd_create_t *create) 
+{
+    struct vbd  *vbd; 
+    rb_node_t  **rb_p, *rb_parent = NULL;
+    blkif_t     *blkif;
+    blkif_vdev_t vdevice = create->vdevice;
+
+    blkif = blkif_find_by_handle(create->domid, create->blkif_handle);
+    if ( unlikely(blkif == NULL) )
+    {
+        DPRINTK("vbd_create attempted for non-existent blkif (%u,%u)\n", 
+                create->domid, create->blkif_handle); 
+        create->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND;
+        return;
+    }
+
+    rb_p = &blkif->vbd_rb.rb_node;
+    while ( *rb_p != NULL )
+    {
+        rb_parent = *rb_p;
+        vbd = rb_entry(rb_parent, struct vbd, rb);
+        if ( vdevice < vbd->vdevice )
+        {
+            rb_p = &rb_parent->rb_left;
+        }
+        else if ( vdevice > vbd->vdevice )
+        {
+            rb_p = &rb_parent->rb_right;
+        }
+        else
+        {
+            DPRINTK("vbd_create attempted for already existing vbd\n");
+            create->status = BLKIF_BE_STATUS_VBD_EXISTS;
+            return;
+        }
+    }
+
+    if ( unlikely((vbd = kmalloc(sizeof(struct vbd), GFP_KERNEL)) == NULL) )
+    {
+        DPRINTK("vbd_create: out of memory\n");
+        create->status = BLKIF_BE_STATUS_OUT_OF_MEMORY;
+        return;
+    }
+
+    vbd->vdevice  = vdevice; 
+    vbd->readonly = create->readonly;
+    vbd->type     = VDISK_TYPE_DISK | VDISK_FLAG_VIRT;
+
+    /* Mask to 16-bit for compatibility with old tools */
+    vbd->pdevice  = create->pdevice & 0xffff;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    vbd->bdev = open_by_devnum(
+        vbd_map_devnum(vbd->pdevice),
+        vbd->readonly ? FMODE_READ : FMODE_WRITE);
+    if ( IS_ERR(vbd->bdev) )
+    {
+        DPRINTK("vbd_creat: device %08x doesn't exist.\n", vbd->pdevice);
+        create->status = BLKIF_BE_STATUS_PHYSDEV_NOT_FOUND;
+        return;
+    }
+
+    if ( (vbd->bdev->bd_disk == NULL) )
+    {
+        DPRINTK("vbd_creat: device %08x doesn't exist.\n", vbd->pdevice);
+        create->status = BLKIF_BE_STATUS_PHYSDEV_NOT_FOUND;
+        bdev_put(vbd->bdev);
+        return;
+    }
+#else
+    if ( (blk_size[MAJOR(vbd->pdevice)] == NULL) || (vbd_sz(vbd) == 0) )
+    {
+        DPRINTK("vbd_creat: device %08x doesn't exist.\n", vbd->pdevice);
+        create->status = BLKIF_BE_STATUS_PHYSDEV_NOT_FOUND;
+        return;
+    }
+#endif
+
+    spin_lock(&blkif->vbd_lock);
+    rb_link_node(&vbd->rb, rb_parent, rb_p);
+    rb_insert_color(&vbd->rb, &blkif->vbd_rb);
+    spin_unlock(&blkif->vbd_lock);
+
+    DPRINTK("Successful creation of vdev=%04x (dom=%u)\n",
+            vdevice, create->domid);
+    create->status = BLKIF_BE_STATUS_OKAY;
+}
+
+
+void vbd_destroy(blkif_be_vbd_destroy_t *destroy) 
+{
+    blkif_t           *blkif;
+    struct vbd        *vbd;
+    rb_node_t         *rb;
+    blkif_vdev_t       vdevice = destroy->vdevice;
+
+    blkif = blkif_find_by_handle(destroy->domid, destroy->blkif_handle);
+    if ( unlikely(blkif == NULL) )
+    {
+        DPRINTK("vbd_destroy attempted for non-existent blkif (%u,%u)\n", 
+                destroy->domid, destroy->blkif_handle); 
+        destroy->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND;
+        return;
+    }
+
+    rb = blkif->vbd_rb.rb_node;
+    while ( rb != NULL )
+    {
+        vbd = rb_entry(rb, struct vbd, rb);
+        if ( vdevice < vbd->vdevice )
+            rb = rb->rb_left;
+        else if ( vdevice > vbd->vdevice )
+            rb = rb->rb_right;
+        else
+            goto found;
+    }
+
+    destroy->status = BLKIF_BE_STATUS_VBD_NOT_FOUND;
+    return;
+
+ found:
+    spin_lock(&blkif->vbd_lock);
+    rb_erase(rb, &blkif->vbd_rb);
+    spin_unlock(&blkif->vbd_lock);
+    bdev_put(vbd->bdev);
+    kfree(vbd);
+}
+
+
+void destroy_all_vbds(blkif_t *blkif)
+{
+    struct vbd *vbd;
+    rb_node_t  *rb;
+
+    spin_lock(&blkif->vbd_lock);
+
+    while ( (rb = blkif->vbd_rb.rb_node) != NULL )
+    {
+        vbd = rb_entry(rb, struct vbd, rb);
+        rb_erase(rb, &blkif->vbd_rb);
+        spin_unlock(&blkif->vbd_lock);
+        bdev_put(vbd->bdev);
+        kfree(vbd);
+        spin_lock(&blkif->vbd_lock);
+    }
+
+    spin_unlock(&blkif->vbd_lock);
+}
+
+
+static void vbd_probe_single(
+    blkif_t *blkif, vdisk_t *vbd_info, struct vbd *vbd)
+{
+    vbd_info->device   = vbd->vdevice; 
+    vbd_info->info     = vbd->type | (vbd->readonly ? VDISK_FLAG_RO : 0);
+    vbd_info->capacity = vbd_sz(vbd);
+}
+
+
+int vbd_probe(blkif_t *blkif, vdisk_t *vbd_info, int max_vbds)
+{
+    int        rc = 0, nr_vbds = 0;
+    rb_node_t *rb;
+
+    spin_lock(&blkif->vbd_lock);
+
+    if ( (rb = blkif->vbd_rb.rb_node) == NULL )
+        goto out;
+
+ new_subtree:
+    /* STEP 1. Find least node (it'll be left-most). */
+    while ( rb->rb_left != NULL )
+        rb = rb->rb_left;
+
+    for ( ; ; )
+    {
+        /* STEP 2. Dealt with left subtree. Now process current node. */
+        vbd_probe_single(blkif, &vbd_info[nr_vbds],
+                         rb_entry(rb, struct vbd, rb));
+        if ( ++nr_vbds == max_vbds )
+            goto out;
+
+        /* STEP 3. Process right subtree, if any. */
+        if ( rb->rb_right != NULL )
+        {
+            rb = rb->rb_right;
+            goto new_subtree;
+        }
+
+        /* STEP 4. Done both subtrees. Head back through ancesstors. */
+        for ( ; ; ) 
+        {
+            /* We're done when we get back to the root node. */
+            if ( rb->rb_parent == NULL )
+                goto out;
+            /* If we are left of parent, then parent is next to process. */
+            if ( rb->rb_parent->rb_left == rb )
+                break;
+            /* If we are right of parent, then we climb to grandparent. */
+            rb = rb->rb_parent;
+        }
+
+        rb = rb->rb_parent;
+    }
+
+ out:
+    spin_unlock(&blkif->vbd_lock);
+    return (rc == 0) ? nr_vbds : rc;  
+}
+
+
+int vbd_translate(struct phys_req *req, blkif_t *blkif, int operation)
+{
+    struct vbd *vbd;
+    rb_node_t  *rb;
+    int         rc = -EACCES;
+
+    /* Take the vbd_lock because another thread could be updating the tree. */
+    spin_lock(&blkif->vbd_lock);
+
+    rb = blkif->vbd_rb.rb_node;
+    while ( rb != NULL )
+    {
+        vbd = rb_entry(rb, struct vbd, rb);
+        if ( req->dev < vbd->vdevice )
+            rb = rb->rb_left;
+        else if ( req->dev > vbd->vdevice )
+            rb = rb->rb_right;
+        else
+            goto found;
+    }
+
+    DPRINTK("vbd_translate; domain %u attempted to access "
+            "non-existent VBD.\n", blkif->domid);
+    rc = -ENODEV;
+    goto out;
+
+ found:
+
+    if ( (operation == WRITE) && vbd->readonly )
+        goto out;
+
+    if ( unlikely((req->sector_number + req->nr_sects) > vbd_sz(vbd)) )
+        goto out;
+
+    req->dev  = vbd->pdevice;
+    req->bdev = vbd->bdev;
+    rc = 0;
+
+ out:
+    spin_unlock(&blkif->vbd_lock);
+    return rc;
+}
diff --git a/drivers/xen/blkfront/Kconfig b/drivers/xen/blkfront/Kconfig
new file mode 100644 (file)
index 0000000..edde837
--- /dev/null
@@ -0,0 +1,6 @@
+
+config XENBLOCK
+       tristate "Block device driver"
+       depends on ARCH_XEN
+       help
+         Block device driver for Xen
diff --git a/drivers/xen/blkfront/Makefile b/drivers/xen/blkfront/Makefile
new file mode 100644 (file)
index 0000000..5d1707d
--- /dev/null
@@ -0,0 +1,3 @@
+
+obj-y  := blkfront.o vbd.o
+
diff --git a/drivers/xen/blkfront/blkfront.c b/drivers/xen/blkfront/blkfront.c
new file mode 100644 (file)
index 0000000..311b839
--- /dev/null
@@ -0,0 +1,1480 @@
+/******************************************************************************
+ * blkfront.c
+ * 
+ * XenLinux virtual block-device driver.
+ * 
+ * Copyright (c) 2003-2004, Keir Fraser & Steve Hand
+ * Modifications by Mark A. Williamson are (c) Intel Research Cambridge
+ * Copyright (c) 2004, Christian Limpach
+ * Copyright (c) 2004, Andrew Warfield
+ * Copyright (c) 2005, Christopher Clark
+ * 
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#if 1
+#define ASSERT(_p) \
+    if ( !(_p) ) { printk("Assertion '%s' failed, line %d, file %s", #_p , \
+    __LINE__, __FILE__); *(int*)0=0; }
+#else
+#define ASSERT(_p)
+#endif
+
+#include <linux/version.h>
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+#include "block.h"
+#else
+#include "common.h"
+#include <linux/blk.h>
+#include <linux/tqueue.h>
+#endif
+
+#include <linux/cdrom.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <scsi/scsi.h>
+#include <asm-xen/ctrl_if.h>
+#include <asm-xen/evtchn.h>
+#ifdef CONFIG_XEN_BLKDEV_GRANT
+#include <asm-xen/xen-public/grant_table.h>
+#include <asm-xen/gnttab.h>
+#endif
+
+typedef unsigned char byte; /* from linux/ide.h */
+
+/* Control whether runtime update of vbds is enabled. */
+#define ENABLE_VBD_UPDATE 1
+
+#if ENABLE_VBD_UPDATE
+static void vbd_update(void);
+#else
+static void vbd_update(void){};
+#endif
+
+#define BLKIF_STATE_CLOSED       0
+#define BLKIF_STATE_DISCONNECTED 1
+#define BLKIF_STATE_CONNECTED    2
+
+#define WPRINTK(fmt, args...) printk(KERN_WARNING "xen_blk: " fmt, ##args)
+
+static int blkif_handle = 0;
+static unsigned int blkif_state = BLKIF_STATE_CLOSED;
+static unsigned int blkif_evtchn = 0;
+static unsigned int blkif_irq = 0;
+
+static int blkif_control_rsp_valid;
+static blkif_response_t blkif_control_rsp;
+
+static blkif_front_ring_t blk_ring;
+
+#define BLK_RING_SIZE __RING_SIZE((blkif_sring_t *)0, PAGE_SIZE)
+
+#ifdef CONFIG_XEN_BLKDEV_GRANT
+static domid_t rdomid = 0;
+static grant_ref_t gref_head, gref_terminal;
+#define MAXIMUM_OUTSTANDING_BLOCK_REQS \
+    (BLKIF_MAX_SEGMENTS_PER_REQUEST * BLKIF_RING_SIZE)
+#define GRANTREF_INVALID (1<<15)
+#endif
+
+static struct blk_shadow {
+    blkif_request_t req;
+    unsigned long request;
+    unsigned long frame[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+} blk_shadow[BLK_RING_SIZE];
+unsigned long blk_shadow_free;
+
+static int recovery = 0; /* Recovery in progress: protected by blkif_io_lock */
+
+static void kick_pending_request_queues(void);
+
+int __init xlblk_init(void);
+
+static void blkif_completion(struct blk_shadow *s);
+
+static inline int GET_ID_FROM_FREELIST(void)
+{
+    unsigned long free = blk_shadow_free;
+    BUG_ON(free > BLK_RING_SIZE);
+    blk_shadow_free = blk_shadow[free].req.id;
+    blk_shadow[free].req.id = 0x0fffffee; /* debug */
+    return free;
+}
+
+static inline void ADD_ID_TO_FREELIST(unsigned long id)
+{
+    blk_shadow[id].req.id  = blk_shadow_free;
+    blk_shadow[id].request = 0;
+    blk_shadow_free = id;
+}
+
+
+/************************  COMMON CODE  (inlined)  ************************/
+
+/* Kernel-specific definitions used in the common code */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+#define DISABLE_SCATTERGATHER() 
+#else
+static int sg_operation = -1;
+#define DISABLE_SCATTERGATHER() (sg_operation = -1)
+#endif
+
+static inline void pickle_request(struct blk_shadow *s, blkif_request_t *r)
+{
+#ifndef CONFIG_XEN_BLKDEV_GRANT
+    int i;
+#endif
+
+    s->req = *r;
+
+#ifndef CONFIG_XEN_BLKDEV_GRANT
+    for ( i = 0; i < r->nr_segments; i++ )
+        s->req.frame_and_sects[i] = machine_to_phys(r->frame_and_sects[i]);
+#endif
+}
+
+static inline void unpickle_request(blkif_request_t *r, struct blk_shadow *s)
+{
+#ifndef CONFIG_XEN_BLKDEV_GRANT
+    int i;
+#endif
+
+    *r = s->req;
+
+#ifndef CONFIG_XEN_BLKDEV_GRANT
+    for ( i = 0; i < s->req.nr_segments; i++ )
+        r->frame_and_sects[i] = phys_to_machine(s->req.frame_and_sects[i]);
+#endif
+}
+
+
+static inline void flush_requests(void)
+{
+    DISABLE_SCATTERGATHER();
+    RING_PUSH_REQUESTS(&blk_ring);
+    notify_via_evtchn(blkif_evtchn);
+}
+
+
+/**************************  KERNEL VERSION 2.6  **************************/
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+
+module_init(xlblk_init);
+
+#if ENABLE_VBD_UPDATE
+static void update_vbds_task(void *unused)
+{ 
+    xlvbd_update_vbds();
+}
+
+static void vbd_update(void)
+{
+    static DECLARE_WORK(update_tq, update_vbds_task, NULL);
+    schedule_work(&update_tq);
+}
+#endif /* ENABLE_VBD_UPDATE */
+
+static void kick_pending_request_queues(void)
+{
+    if ( (xlbd_blk_queue != NULL) &&
+         test_bit(QUEUE_FLAG_STOPPED, &xlbd_blk_queue->queue_flags) )
+    {
+        blk_start_queue(xlbd_blk_queue);
+        /* XXXcl call to request_fn should not be needed but
+         * we get stuck without...  needs investigating
+         */
+        xlbd_blk_queue->request_fn(xlbd_blk_queue);
+    }
+}
+
+
+int blkif_open(struct inode *inode, struct file *filep)
+{
+    struct gendisk *gd = inode->i_bdev->bd_disk;
+    struct xlbd_disk_info *di = (struct xlbd_disk_info *)gd->private_data;
+
+    /* Update of usage count is protected by per-device semaphore. */
+    di->mi->usage++;
+    
+    return 0;
+}
+
+
+int blkif_release(struct inode *inode, struct file *filep)
+{
+    struct gendisk *gd = inode->i_bdev->bd_disk;
+    struct xlbd_disk_info *di = (struct xlbd_disk_info *)gd->private_data;
+
+    /*
+     * When usage drops to zero it may allow more VBD updates to occur.
+     * Update of usage count is protected by a per-device semaphore.
+     */
+    if ( --di->mi->usage == 0 )
+        vbd_update();
+
+    return 0;
+}
+
+
+int blkif_ioctl(struct inode *inode, struct file *filep,
+                unsigned command, unsigned long argument)
+{
+    int i;
+
+    DPRINTK_IOCTL("command: 0x%x, argument: 0x%lx, dev: 0x%04x\n",
+                  command, (long)argument, inode->i_rdev); 
+  
+    switch ( command )
+    {
+    case HDIO_GETGEO:
+        /* return ENOSYS to use defaults */
+        return -ENOSYS;
+
+    case CDROMMULTISESSION:
+        DPRINTK("FIXME: support multisession CDs later\n");
+        for ( i = 0; i < sizeof(struct cdrom_multisession); i++ )
+            if ( put_user(0, (byte *)(argument + i)) ) return -EFAULT;
+        return 0;
+
+    default:
+        printk(KERN_ALERT "ioctl %08x not supported by Xen blkdev\n",
+               command);
+        return -ENOSYS;
+    }
+
+    return 0;
+}
+
+
+/*
+ * blkif_queue_request
+ *
+ * request block io 
+ * 
+ * id: for guest use only.
+ * operation: BLKIF_OP_{READ,WRITE,PROBE}
+ * buffer: buffer to read/write into. this should be a
+ *   virtual address in the guest os.
+ */
+static int blkif_queue_request(struct request *req)
+{
+    struct xlbd_disk_info *di =
+        (struct xlbd_disk_info *)req->rq_disk->private_data;
+    unsigned long buffer_ma;
+    blkif_request_t *ring_req;
+    struct bio *bio;
+    struct bio_vec *bvec;
+    int idx;
+    unsigned long id;
+    unsigned int fsect, lsect;
+#ifdef CONFIG_XEN_BLKDEV_GRANT
+    int ref;
+#endif
+
+    if ( unlikely(blkif_state != BLKIF_STATE_CONNECTED) )
+        return 1;
+
+    /* Fill out a communications ring structure. */
+    ring_req = RING_GET_REQUEST(&blk_ring, blk_ring.req_prod_pvt);
+    id = GET_ID_FROM_FREELIST();
+    blk_shadow[id].request = (unsigned long)req;
+
+    ring_req->id = id;
+    ring_req->operation = rq_data_dir(req) ? BLKIF_OP_WRITE :
+        BLKIF_OP_READ;
+    ring_req->sector_number = (blkif_sector_t)req->sector;
+    ring_req->device = di->xd_device;
+
+    ring_req->nr_segments = 0;
+    rq_for_each_bio(bio, req)
+    {
+        bio_for_each_segment(bvec, bio, idx)
+        {
+            if ( ring_req->nr_segments == BLKIF_MAX_SEGMENTS_PER_REQUEST )
+                BUG();
+            buffer_ma = page_to_phys(bvec->bv_page);
+            fsect = bvec->bv_offset >> 9;
+            lsect = fsect + (bvec->bv_len >> 9) - 1;
+#ifdef CONFIG_XEN_BLKDEV_GRANT
+            /* install a grant reference. */
+            ref = gnttab_claim_grant_reference(&gref_head, gref_terminal);
+            ASSERT( ref != -ENOSPC );
+
+            gnttab_grant_foreign_access_ref(
+                        ref,
+                        rdomid,
+                        buffer_ma >> PAGE_SHIFT,
+                        rq_data_dir(req) );
+
+            blk_shadow[id].frame[ring_req->nr_segments] =
+                buffer_ma >> PAGE_SHIFT;
+
+            ring_req->frame_and_sects[ring_req->nr_segments++] =
+                (((u32) ref) << 16) | (fsect << 3) | lsect;
+
+#else
+            ring_req->frame_and_sects[ring_req->nr_segments++] =
+                buffer_ma | (fsect << 3) | lsect;
+#endif
+        }
+    }
+
+    blk_ring.req_prod_pvt++;
+    
+    /* Keep a private copy so we can reissue requests when recovering. */
+    pickle_request(&blk_shadow[id], ring_req);
+
+    return 0;
+}
+
+
+/*
+ * do_blkif_request
+ *  read a block; request is in a request queue
+ */
+void do_blkif_request(request_queue_t *rq)
+{
+    struct request *req;
+    int queued;
+
+    DPRINTK("Entered do_blkif_request\n"); 
+
+    queued = 0;
+
+    while ( (req = elv_next_request(rq)) != NULL )
+    {
+        if ( !blk_fs_request(req) )
+        {
+            end_request(req, 0);
+            continue;
+        }
+
+        if ( RING_FULL(&blk_ring) )
+        {
+            blk_stop_queue(rq);
+            break;
+        }
+
+        DPRINTK("do_blk_req %p: cmd %p, sec %lx, (%u/%li) buffer:%p [%s]\n",
+                req, req->cmd, req->sector, req->current_nr_sectors,
+                req->nr_sectors, req->buffer,
+                rq_data_dir(req) ? "write" : "read");
+
+        blkdev_dequeue_request(req);
+        if ( blkif_queue_request(req) )
+        {
+            blk_stop_queue(rq);
+            break;
+        }
+
+        queued++;
+    }
+
+    if ( queued != 0 )
+        flush_requests();
+}
+
+
+static irqreturn_t blkif_int(int irq, void *dev_id, struct pt_regs *ptregs)
+{
+    struct request *req;
+    blkif_response_t *bret;
+    RING_IDX i, rp;
+    unsigned long flags; 
+    
+    spin_lock_irqsave(&blkif_io_lock, flags);     
+
+    if ( unlikely(blkif_state == BLKIF_STATE_CLOSED) || 
+         unlikely(recovery) )
+    {
+        spin_unlock_irqrestore(&blkif_io_lock, flags);
+        return IRQ_HANDLED;
+    }
+    
+    rp = blk_ring.sring->rsp_prod;
+    rmb(); /* Ensure we see queued responses up to 'rp'. */
+
+    for ( i = blk_ring.rsp_cons; i != rp; i++ )
+    {
+        unsigned long id;
+
+        bret = RING_GET_RESPONSE(&blk_ring, i);
+        id   = bret->id;
+        req  = (struct request *)blk_shadow[id].request;
+
+        blkif_completion(&blk_shadow[id]);
+
+        ADD_ID_TO_FREELIST(id);
+
+        switch ( bret->operation )
+        {
+        case BLKIF_OP_READ:
+        case BLKIF_OP_WRITE:
+            if ( unlikely(bret->status != BLKIF_RSP_OKAY) )
+                DPRINTK("Bad return from blkdev data request: %x\n",
+                        bret->status);
+
+            if ( unlikely(end_that_request_first
+                          (req, 
+                           (bret->status == BLKIF_RSP_OKAY),
+                           req->hard_nr_sectors)) )
+                BUG();
+            end_that_request_last(req);
+
+            break;
+        case BLKIF_OP_PROBE:
+            memcpy(&blkif_control_rsp, bret, sizeof(*bret));
+            blkif_control_rsp_valid = 1;
+            break;
+        default:
+            BUG();
+        }
+    }
+
+    blk_ring.rsp_cons = i;
+    
+    kick_pending_request_queues();
+
+    spin_unlock_irqrestore(&blkif_io_lock, flags);
+
+    return IRQ_HANDLED;
+}
+
+#else
+/**************************  KERNEL VERSION 2.4  **************************/
+
+static kdev_t        sg_dev;
+static unsigned long sg_next_sect;
+
+/*
+ * Request queues with outstanding work, but ring is currently full.
+ * We need no special lock here, as we always access this with the
+ * blkif_io_lock held. We only need a small maximum list.
+ */
+#define MAX_PENDING 8
+static request_queue_t *pending_queues[MAX_PENDING];
+static int nr_pending;
+
+
+#define blkif_io_lock io_request_lock
+
+/*============================================================================*/
+#if ENABLE_VBD_UPDATE
+
+/*
+ * blkif_update_int/update-vbds_task - handle VBD update events.
+ *  Schedule a task for keventd to run, which will update the VBDs and perform 
+ *  the corresponding updates to our view of VBD state.
+ */
+static void update_vbds_task(void *unused)
+{ 
+    xlvbd_update_vbds();
+}
+
+static void vbd_update(void)
+{
+    static struct tq_struct update_tq;
+    update_tq.routine = update_vbds_task;
+    schedule_task(&update_tq);
+}
+
+#endif /* ENABLE_VBD_UPDATE */
+/*============================================================================*/
+
+static void kick_pending_request_queues(void)
+{
+    /* We kick pending request queues if the ring is reasonably empty. */
+    if ( (nr_pending != 0) && 
+         (RING_PENDING_REQUESTS(&blk_ring) < (BLK_RING_SIZE >> 1)) )
+    {
+        /* Attempt to drain the queue, but bail if the ring becomes full. */
+        while ( (nr_pending != 0) && !RING_FULL(&blk_ring) )
+            do_blkif_request(pending_queues[--nr_pending]);
+    }
+}
+
+int blkif_open(struct inode *inode, struct file *filep)
+{
+    short xldev = inode->i_rdev; 
+    struct gendisk *gd = get_gendisk(xldev);
+    xl_disk_t *disk = xldev_to_xldisk(inode->i_rdev);
+    short minor = MINOR(xldev); 
+
+    if ( gd->part[minor].nr_sects == 0 )
+    { 
+        /*
+         * Device either doesn't exist, or has zero capacity; we use a few
+         * cheesy heuristics to return the relevant error code
+         */
+        if ( (gd->sizes[minor >> gd->minor_shift] != 0) ||
+             ((minor & (gd->max_p - 1)) != 0) )
+        { 
+            /*
+             * We have a real device, but no such partition, or we just have a
+             * partition number so guess this is the problem.
+             */
+            return -ENXIO;     /* no such device or address */
+        }
+        else if ( gd->flags[minor >> gd->minor_shift] & GENHD_FL_REMOVABLE )
+        {
+            /* This is a removable device => assume that media is missing. */ 
+            return -ENOMEDIUM; /* media not present (this is a guess) */
+        } 
+        else
+        { 
+            /* Just go for the general 'no such device' error. */
+            return -ENODEV;    /* no such device */
+        }
+    }
+    
+    /* Update of usage count is protected by per-device semaphore. */
+    disk->usage++;
+
+    return 0;
+}
+
+
+int blkif_release(struct inode *inode, struct file *filep)
+{
+    xl_disk_t *disk = xldev_to_xldisk(inode->i_rdev);
+
+    /*
+     * When usage drops to zero it may allow more VBD updates to occur.
+     * Update of usage count is protected by a per-device semaphore.
+     */
+    if ( --disk->usage == 0 ) {
+        vbd_update();
+    }
+
+    return 0;
+}
+
+
+int blkif_ioctl(struct inode *inode, struct file *filep,
+                unsigned command, unsigned long argument)
+{
+    kdev_t dev = inode->i_rdev;
+    struct hd_geometry *geo = (struct hd_geometry *)argument;
+    struct gendisk *gd;     
+    struct hd_struct *part; 
+    int i;
+    unsigned short cylinders;
+    byte heads, sectors;
+
+    /* NB. No need to check permissions. That is done for us. */
+    
+    DPRINTK_IOCTL("command: 0x%x, argument: 0x%lx, dev: 0x%04x\n",
+                  command, (long) argument, dev); 
+  
+    gd = get_gendisk(dev);
+    part = &gd->part[MINOR(dev)]; 
+
+    switch ( command )
+    {
+    case BLKGETSIZE:
+        DPRINTK_IOCTL("   BLKGETSIZE: %x %lx\n", BLKGETSIZE, part->nr_sects); 
+        return put_user(part->nr_sects, (unsigned long *) argument);
+
+    case BLKGETSIZE64:
+        DPRINTK_IOCTL("   BLKGETSIZE64: %x %llx\n", BLKGETSIZE64,
+                      (u64)part->nr_sects * 512);
+        return put_user((u64)part->nr_sects * 512, (u64 *) argument);
+
+    case BLKRRPART:                               /* re-read partition table */
+        DPRINTK_IOCTL("   BLKRRPART: %x\n", BLKRRPART);
+        return blkif_revalidate(dev);
+
+    case BLKSSZGET:
+        return hardsect_size[MAJOR(dev)][MINOR(dev)]; 
+
+    case BLKBSZGET:                                        /* get block size */
+        DPRINTK_IOCTL("   BLKBSZGET: %x\n", BLKBSZGET);
+        break;
+
+    case BLKBSZSET:                                        /* set block size */
+        DPRINTK_IOCTL("   BLKBSZSET: %x\n", BLKBSZSET);
+        break;
+
+    case BLKRASET:                                         /* set read-ahead */
+        DPRINTK_IOCTL("   BLKRASET: %x\n", BLKRASET);
+        break;
+
+    case BLKRAGET:                                         /* get read-ahead */
+        DPRINTK_IOCTL("   BLKRAFET: %x\n", BLKRAGET);
+        break;
+
+    case HDIO_GETGEO:
+        DPRINTK_IOCTL("   HDIO_GETGEO: %x\n", HDIO_GETGEO);
+        if (!argument) return -EINVAL;
+
+        /* We don't have real geometry info, but let's at least return
+           values consistent with the size of the device */
+
+        heads = 0xff;
+        sectors = 0x3f; 
+        cylinders = part->nr_sects / (heads * sectors);
+
+        if (put_user(0x00,  (unsigned long *) &geo->start)) return -EFAULT;
+        if (put_user(heads,  (byte *)&geo->heads)) return -EFAULT;
+        if (put_user(sectors,  (byte *)&geo->sectors)) return -EFAULT;
+        if (put_user(cylinders, (unsigned short *)&geo->cylinders)) return -EFAULT;
+
+        return 0;
+
+    case HDIO_GETGEO_BIG: 
+        DPRINTK_IOCTL("   HDIO_GETGEO_BIG: %x\n", HDIO_GETGEO_BIG);
+        if (!argument) return -EINVAL;
+
+        /* We don't have real geometry info, but let's at least return
+           values consistent with the size of the device */
+
+        heads = 0xff;
+        sectors = 0x3f; 
+        cylinders = part->nr_sects / (heads * sectors);
+
+        if (put_user(0x00,  (unsigned long *) &geo->start))  return -EFAULT;
+        if (put_user(heads,  (byte *)&geo->heads))   return -EFAULT;
+        if (put_user(sectors,  (byte *)&geo->sectors)) return -EFAULT;
+        if (put_user(cylinders, (unsigned int *) &geo->cylinders)) return -EFAULT;
+
+        return 0;
+
+    case CDROMMULTISESSION:
+        DPRINTK("FIXME: support multisession CDs later\n");
+        for ( i = 0; i < sizeof(struct cdrom_multisession); i++ )
+            if ( put_user(0, (byte *)(argument + i)) ) return -EFAULT;
+        return 0;
+
+    case SCSI_IOCTL_GET_BUS_NUMBER:
+        DPRINTK("FIXME: SCSI_IOCTL_GET_BUS_NUMBER ioctl in XL blkif");
+        return -ENOSYS;
+
+    default:
+        printk(KERN_ALERT "ioctl %08x not supported by XL blkif\n", command);
+        return -ENOSYS;
+    }
+    
+    return 0;
+}
+
+
+
+/* check media change: should probably do something here in some cases :-) */
+int blkif_check(kdev_t dev)
+{
+    DPRINTK("blkif_check\n");
+    return 0;
+}
+
+int blkif_revalidate(kdev_t dev)
+{
+    struct block_device *bd;
+    struct gendisk *gd;
+    xl_disk_t *disk;
+    unsigned long capacity;
+    int i, rc = 0;
+    
+    if ( (bd = bdget(dev)) == NULL )
+        return -EINVAL;
+
+    /*
+     * Update of partition info, and check of usage count, is protected
+     * by the per-block-device semaphore.
+     */
+    down(&bd->bd_sem);
+
+    if ( ((gd = get_gendisk(dev)) == NULL) ||
+         ((disk = xldev_to_xldisk(dev)) == NULL) ||
+         ((capacity = gd->part[MINOR(dev)].nr_sects) == 0) )
+    {
+        rc = -EINVAL;
+        goto out;
+    }
+
+    if ( disk->usage > 1 )
+    {
+        rc = -EBUSY;
+        goto out;
+    }
+
+    /* Only reread partition table if VBDs aren't mapped to partitions. */
+    if ( !(gd->flags[MINOR(dev) >> gd->minor_shift] & GENHD_FL_VIRT_PARTNS) )
+    {
+        for ( i = gd->max_p - 1; i >= 0; i-- )
+        {
+            invalidate_device(dev+i, 1);
+            gd->part[MINOR(dev+i)].start_sect = 0;
+            gd->part[MINOR(dev+i)].nr_sects   = 0;
+            gd->sizes[MINOR(dev+i)]           = 0;
+        }
+
+        grok_partitions(gd, MINOR(dev)>>gd->minor_shift, gd->max_p, capacity);
+    }
+
+ out:
+    up(&bd->bd_sem);
+    bdput(bd);
+    return rc;
+}
+
+
+/*
+ * blkif_queue_request
+ *
+ * request block io 
+ * 
+ * id: for guest use only.
+ * operation: BLKIF_OP_{READ,WRITE,PROBE}
+ * buffer: buffer to read/write into. this should be a
+ *   virtual address in the guest os.
+ */
+static int blkif_queue_request(unsigned long   id,
+                               int             operation,
+                               char *          buffer,
+                               unsigned long   sector_number,
+                               unsigned short  nr_sectors,
+                               kdev_t          device)
+{
+    unsigned long       buffer_ma = virt_to_bus(buffer);
+    unsigned long       xid;
+    struct gendisk     *gd;
+    blkif_request_t    *req;
+    struct buffer_head *bh;
+    unsigned int        fsect, lsect;
+#ifdef CONFIG_XEN_BLKDEV_GRANT
+    int ref;
+#endif
+
+    fsect = (buffer_ma & ~PAGE_MASK) >> 9;
+    lsect = fsect + nr_sectors - 1;
+
+    /* Buffer must be sector-aligned. Extent mustn't cross a page boundary. */
+    if ( unlikely((buffer_ma & ((1<<9)-1)) != 0) )
+        BUG();
+    if ( lsect > 7 )
+        BUG();
+
+    buffer_ma &= PAGE_MASK;
+
+    if ( unlikely(blkif_state != BLKIF_STATE_CONNECTED) )
+        return 1;
+
+    switch ( operation )
+    {
+
+    case BLKIF_OP_READ:
+    case BLKIF_OP_WRITE:
+        gd = get_gendisk(device); 
+
+        /*
+         * Update the sector_number we'll pass down as appropriate; note that
+         * we could sanity check that resulting sector will be in this
+         * partition, but this will happen in driver backend anyhow.
+         */
+        sector_number += gd->part[MINOR(device)].start_sect;
+
+        /*
+         * If this unit doesn't consist of virtual partitions then we clear 
+         * the partn bits from the device number.
+         */
+        if ( !(gd->flags[MINOR(device)>>gd->minor_shift] & 
+               GENHD_FL_VIRT_PARTNS) )
+            device &= ~(gd->max_p - 1);
+
+        if ( (sg_operation == operation) &&
+             (sg_dev == device) &&
+             (sg_next_sect == sector_number) )
+        {
+            req = RING_GET_REQUEST(&blk_ring, 
+                                   blk_ring.req_prod_pvt - 1);
+            bh = (struct buffer_head *)id;
+     
+            bh->b_reqnext = (struct buffer_head *)blk_shadow[req->id].request;
+            blk_shadow[req->id].request = (unsigned long)id;
+
+#ifdef CONFIG_XEN_BLKDEV_GRANT
+            /* install a grant reference. */
+            ref = gnttab_claim_grant_reference(&gref_head, gref_terminal);
+            ASSERT( ref != -ENOSPC );
+
+            gnttab_grant_foreign_access_ref(
+                        ref,
+                        rdomid,
+                        buffer_ma >> PAGE_SHIFT,
+                        ( operation == BLKIF_OP_WRITE ? 1 : 0 ) );
+
+            blk_shadow[id].frame[req->nr_segments] =
+                buffer_ma >> PAGE_SHIFT;
+
+            req->frame_and_sects[req->nr_segments] =
+                (((u32) ref ) << 16) | (fsect << 3) | lsect;
+#else
+            req->frame_and_sects[req->nr_segments] =
+                buffer_ma | (fsect << 3) | lsect;
+#endif
+            if ( ++req->nr_segments < BLKIF_MAX_SEGMENTS_PER_REQUEST )
+                sg_next_sect += nr_sectors;
+            else
+                DISABLE_SCATTERGATHER();
+
+            /* Update the copy of the request in the recovery ring. */
+            pickle_request(&blk_shadow[req->id], req );
+
+            return 0;
+        }
+        else if ( RING_FULL(&blk_ring) )
+        {
+            return 1;
+        }
+        else
+        {
+            sg_operation = operation;
+            sg_dev       = device;
+            sg_next_sect = sector_number + nr_sectors;
+        }
+        break;
+
+    default:
+        panic("unknown op %d\n", operation);
+    }
+
+    /* Fill out a communications ring structure. */
+    req = RING_GET_REQUEST(&blk_ring, blk_ring.req_prod_pvt);
+
+    xid = GET_ID_FROM_FREELIST();
+    blk_shadow[xid].request = (unsigned long)id;
+
+    req->id            = xid;
+    req->operation     = operation;
+    req->sector_number = (blkif_sector_t)sector_number;
+    req->device        = device; 
+    req->nr_segments   = 1;
+#ifdef CONFIG_XEN_BLKDEV_GRANT
+    /* install a grant reference. */
+    ref = gnttab_claim_grant_reference(&gref_head, gref_terminal);
+    ASSERT( ref != -ENOSPC );
+
+    gnttab_grant_foreign_access_ref(
+                ref,
+                rdomid,
+                buffer_ma >> PAGE_SHIFT,
+                ( operation == BLKIF_OP_WRITE ? 1 : 0 ) );
+
+    blk_shadow[xid].frame[0] = buffer_ma >> PAGE_SHIFT;
+
+    req->frame_and_sects[0] = (((u32) ref)<<16)  | (fsect<<3) | lsect;
+#else
+    req->frame_and_sects[0] = buffer_ma | (fsect<<3) | lsect;
+#endif
+
+    /* Keep a private copy so we can reissue requests when recovering. */    
+    pickle_request(&blk_shadow[xid], req);
+
+    blk_ring.req_prod_pvt++;
+    
+    return 0;
+}
+
+
+/*
+ * do_blkif_request
+ *  read a block; request is in a request queue
+ */
+void do_blkif_request(request_queue_t *rq)
+{
+    struct request *req;
+    struct buffer_head *bh, *next_bh;
+    int rw, nsect, full, queued = 0;
+
+    DPRINTK("Entered do_blkif_request\n"); 
+
+    while ( !rq->plugged && !list_empty(&rq->queue_head))
+    {
+        if ( (req = blkdev_entry_next_request(&rq->queue_head)) == NULL ) 
+            goto out;
+  
+        DPRINTK("do_blkif_request %p: cmd %i, sec %lx, (%li/%li) bh:%p\n",
+                req, req->cmd, req->sector,
+                req->current_nr_sectors, req->nr_sectors, req->bh);
+
+        rw = req->cmd;
+        if ( rw == READA )
+            rw = READ;
+        if ( unlikely((rw != READ) && (rw != WRITE)) )
+            panic("XenoLinux Virtual Block Device: bad cmd: %d\n", rw);
+
+        req->errors = 0;
+
+        bh = req->bh;
+        while ( bh != NULL )
+        {
+            next_bh = bh->b_reqnext;
+            bh->b_reqnext = NULL;
+
+            full = blkif_queue_request(
+                (unsigned long)bh,
+                (rw == READ) ? BLKIF_OP_READ : BLKIF_OP_WRITE, 
+                bh->b_data, bh->b_rsector, bh->b_size>>9, bh->b_rdev);
+
+            if ( full )
+            { 
+                bh->b_reqnext = next_bh;
+                pending_queues[nr_pending++] = rq;
+                if ( unlikely(nr_pending >= MAX_PENDING) )
+                    BUG();
+                goto out; 
+            }
+
+            queued++;
+
+            /* Dequeue the buffer head from the request. */
+            nsect = bh->b_size >> 9;
+            bh = req->bh = next_bh;
+            
+            if ( bh != NULL )
+            {
+                /* There's another buffer head to do. Update the request. */
+                req->hard_sector += nsect;
+                req->hard_nr_sectors -= nsect;
+                req->sector = req->hard_sector;
+                req->nr_sectors = req->hard_nr_sectors;
+                req->current_nr_sectors = bh->b_size >> 9;
+                req->buffer = bh->b_data;
+            }
+            else
+            {
+                /* That was the last buffer head. Finalise the request. */
+                if ( unlikely(end_that_request_first(req, 1, "XenBlk")) )
+                    BUG();
+                blkdev_dequeue_request(req);
+                end_that_request_last(req);
+            }
+        }
+    }
+
+ out:
+    if ( queued != 0 )
+        flush_requests();
+}
+
+
+static void blkif_int(int irq, void *dev_id, struct pt_regs *ptregs)
+{
+    RING_IDX i, rp; 
+    unsigned long flags; 
+    struct buffer_head *bh, *next_bh;
+    
+    spin_lock_irqsave(&io_request_lock, flags);     
+
+    if ( unlikely(blkif_state == BLKIF_STATE_CLOSED || recovery) )
+    {
+        spin_unlock_irqrestore(&io_request_lock, flags);
+        return;
+    }
+
+    rp = blk_ring.sring->rsp_prod;
+    rmb(); /* Ensure we see queued responses up to 'rp'. */
+
+    for ( i = blk_ring.rsp_cons; i != rp; i++ )
+    {
+        unsigned long id;
+        blkif_response_t *bret;
+        
+        bret = RING_GET_RESPONSE(&blk_ring, i);
+        id = bret->id;
+        bh = (struct buffer_head *)blk_shadow[id].request;
+
+        blkif_completion(&blk_shadow[id]);
+
+        ADD_ID_TO_FREELIST(id);
+
+        switch ( bret->operation )
+        {
+        case BLKIF_OP_READ:
+        case BLKIF_OP_WRITE:
+            if ( unlikely(bret->status != BLKIF_RSP_OKAY) )
+                DPRINTK("Bad return from blkdev data request: %lx\n",
+                        bret->status);
+            for ( ; bh != NULL; bh = next_bh )
+            {
+                next_bh = bh->b_reqnext;
+                bh->b_reqnext = NULL;
+                bh->b_end_io(bh, bret->status == BLKIF_RSP_OKAY);
+            }
+
+            break;
+        case BLKIF_OP_PROBE:
+            memcpy(&blkif_control_rsp, bret, sizeof(*bret));
+            blkif_control_rsp_valid = 1;
+            break;
+        default:
+            BUG();
+        }
+
+    }
+    blk_ring.rsp_cons = i;
+    
+    kick_pending_request_queues();
+
+    spin_unlock_irqrestore(&io_request_lock, flags);
+}
+
+#endif
+
+/*****************************  COMMON CODE  *******************************/
+
+#ifdef CONFIG_XEN_BLKDEV_GRANT
+void blkif_control_probe_send(blkif_request_t *req, blkif_response_t *rsp,
+                              unsigned long address)
+{
+    int ref = gnttab_claim_grant_reference(&gref_head, gref_terminal);
+    ASSERT( ref != -ENOSPC );
+
+    gnttab_grant_foreign_access_ref( ref, rdomid, address >> PAGE_SHIFT, 0 );
+
+    req->frame_and_sects[0] = (((u32) ref) << 16) | 7;
+
+    blkif_control_send(req, rsp);
+}
+#endif
+
+void blkif_control_send(blkif_request_t *req, blkif_response_t *rsp)
+{
+    unsigned long flags, id;
+    blkif_request_t *req_d;
+
+ retry:
+    while ( RING_FULL(&blk_ring) )
+    {
+        set_current_state(TASK_INTERRUPTIBLE);
+        schedule_timeout(1);
+    }
+
+    spin_lock_irqsave(&blkif_io_lock, flags);
+    if ( RING_FULL(&blk_ring) )
+    {
+        spin_unlock_irqrestore(&blkif_io_lock, flags);
+        goto retry;
+    }
+
+    DISABLE_SCATTERGATHER();
+    req_d = RING_GET_REQUEST(&blk_ring, blk_ring.req_prod_pvt);
+    *req_d = *req;    
+
+    id = GET_ID_FROM_FREELIST();
+    req_d->id = id;
+    blk_shadow[id].request = (unsigned long)req;
+
+    pickle_request(&blk_shadow[id], req);
+
+    blk_ring.req_prod_pvt++;
+    flush_requests();
+
+    spin_unlock_irqrestore(&blkif_io_lock, flags);
+
+    while ( !blkif_control_rsp_valid )
+    {
+        set_current_state(TASK_INTERRUPTIBLE);
+        schedule_timeout(1);
+    }
+
+    memcpy(rsp, &blkif_control_rsp, sizeof(*rsp));
+    blkif_control_rsp_valid = 0;
+}
+
+
+/* Send a driver status notification to the domain controller. */
+static void send_driver_status(int ok)
+{
+    ctrl_msg_t cmsg = {
+        .type    = CMSG_BLKIF_FE,
+        .subtype = CMSG_BLKIF_FE_DRIVER_STATUS,
+        .length  = sizeof(blkif_fe_driver_status_t),
+    };
+    blkif_fe_driver_status_t *msg = (void*)cmsg.msg;
+    
+    msg->status = (ok ? BLKIF_DRIVER_STATUS_UP : BLKIF_DRIVER_STATUS_DOWN);
+
+    ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
+}
+
+/* Tell the controller to bring up the interface. */
+static void blkif_send_interface_connect(void)
+{
+    ctrl_msg_t cmsg = {
+        .type    = CMSG_BLKIF_FE,
+        .subtype = CMSG_BLKIF_FE_INTERFACE_CONNECT,
+        .length  = sizeof(blkif_fe_interface_connect_t),
+    };
+    blkif_fe_interface_connect_t *msg = (void*)cmsg.msg;
+    
+    msg->handle      = 0;
+    msg->shmem_frame = (virt_to_machine(blk_ring.sring) >> PAGE_SHIFT);
+    
+    ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
+}
+
+static void blkif_free(void)
+{
+    /* Prevent new requests being issued until we fix things up. */
+    spin_lock_irq(&blkif_io_lock);
+    recovery = 1;
+    blkif_state = BLKIF_STATE_DISCONNECTED;
+    spin_unlock_irq(&blkif_io_lock);
+
+    /* Free resources associated with old device channel. */
+    if ( blk_ring.sring != NULL )
+    {
+        free_page((unsigned long)blk_ring.sring);
+        blk_ring.sring = NULL;
+    }
+    free_irq(blkif_irq, NULL);
+    blkif_irq = 0;
+    
+    unbind_evtchn_from_irq(blkif_evtchn);
+    blkif_evtchn = 0;
+}
+
+static void blkif_close(void)
+{
+}
+
+/* Move from CLOSED to DISCONNECTED state. */
+static void blkif_disconnect(void)
+{
+    blkif_sring_t *sring;
+    
+    if ( blk_ring.sring != NULL )
+        free_page((unsigned long)blk_ring.sring);
+    
+    sring = (blkif_sring_t *)__get_free_page(GFP_KERNEL);
+    SHARED_RING_INIT(sring);
+    FRONT_RING_INIT(&blk_ring, sring, PAGE_SIZE);
+    blkif_state  = BLKIF_STATE_DISCONNECTED;
+    blkif_send_interface_connect();
+}
+
+static void blkif_reset(void)
+{
+    blkif_free();
+    blkif_disconnect();
+}
+
+static void blkif_recover(void)
+{
+    int i;
+    blkif_request_t *req;
+    struct blk_shadow *copy;
+#ifdef CONFIG_XEN_BLKDEV_GRANT
+    int j;
+#endif
+
+    /* Stage 1: Make a safe copy of the shadow state. */
+    copy = (struct blk_shadow *)kmalloc(sizeof(blk_shadow), GFP_KERNEL);
+    BUG_ON(copy == NULL);
+    memcpy(copy, blk_shadow, sizeof(blk_shadow));
+
+    /* Stage 2: Set up free list. */
+    memset(&blk_shadow, 0, sizeof(blk_shadow));
+    for ( i = 0; i < BLK_RING_SIZE; i++ )
+        blk_shadow[i].req.id = i+1;
+    blk_shadow_free = blk_ring.req_prod_pvt;
+    blk_shadow[BLK_RING_SIZE-1].req.id = 0x0fffffff;
+
+    /* Stage 3: Find pending requests and requeue them. */
+    for ( i = 0; i < BLK_RING_SIZE; i++ )
+    {
+        /* Not in use? */
+        if ( copy[i].request == 0 )
+            continue;
+
+        /* Grab a request slot and unpickle shadow state into it. */
+        req = RING_GET_REQUEST(
+            &blk_ring, blk_ring.req_prod_pvt);
+        unpickle_request(req, &copy[i]);
+
+        /* We get a new request id, and must reset the shadow state. */
+        req->id = GET_ID_FROM_FREELIST();
+        memcpy(&blk_shadow[req->id], &copy[i], sizeof(copy[i]));
+
+#ifdef CONFIG_XEN_BLKDEV_GRANT
+        /* Rewrite any grant references invalidated by suspend/resume. */
+        for ( j = 0; j < req->nr_segments; j++ )
+        {
+            if ( req->frame_and_sects[j] & GRANTREF_INVALID )
+                gnttab_grant_foreign_access_ref(
+                    blkif_gref_from_fas(req->frame_and_sects[j]),
+                    rdomid,
+                    blk_shadow[req->id].frame[j],
+                    rq_data_dir((struct request *)
+                                blk_shadow[req->id].request));
+            req->frame_and_sects[j] &= ~GRANTREF_INVALID;
+        }
+        blk_shadow[req->id].req = *req;
+#endif
+
+        blk_ring.req_prod_pvt++;
+    }
+
+    kfree(copy);
+
+    recovery = 0;
+
+    /* blk_ring->req_prod will be set when we flush_requests().*/
+    wmb();
+
+    /* Kicks things back into life. */
+    flush_requests();
+
+    /* Now safe to left other people use the interface. */
+    blkif_state = BLKIF_STATE_CONNECTED;
+}
+
+static void blkif_connect(blkif_fe_interface_status_t *status)
+{
+    int err = 0;
+
+    blkif_evtchn = status->evtchn;
+    blkif_irq    = bind_evtchn_to_irq(blkif_evtchn);
+#ifdef CONFIG_XEN_BLKDEV_GRANT
+    rdomid       = status->domid;
+#endif
+
+    err = request_irq(blkif_irq, blkif_int, SA_SAMPLE_RANDOM, "blkif", NULL);
+    if ( err )
+    {
+        printk(KERN_ALERT "xen_blk: request_irq failed (err=%d)\n", err);
+        return;
+    }
+
+    if ( recovery ) 
+    {
+        blkif_recover();
+    } 
+    else 
+    {
+        /* Transition to connected in case we need to do 
+         *  a partition probe on a whole disk. */
+        blkif_state = BLKIF_STATE_CONNECTED;
+        
+        /* Probe for discs attached to the interface. */
+        xlvbd_init();
+    }
+    
+    /* Kick pending requests. */
+    spin_lock_irq(&blkif_io_lock);
+    kick_pending_request_queues();
+    spin_unlock_irq(&blkif_io_lock);
+}
+
+static void unexpected(blkif_fe_interface_status_t *status)
+{
+    DPRINTK(" Unexpected blkif status %u in state %u\n", 
+            status->status, blkif_state);
+}
+
+static void blkif_status(blkif_fe_interface_status_t *status)
+{
+    if ( status->handle != blkif_handle )
+    {
+        WPRINTK(" Invalid blkif: handle=%u\n", status->handle);
+        unexpected(status);
+        return;
+    }
+
+    switch ( status->status ) 
+    {
+    case BLKIF_INTERFACE_STATUS_CLOSED:
+        switch ( blkif_state )
+        {
+        case BLKIF_STATE_CLOSED:
+            unexpected(status);
+            break;
+        case BLKIF_STATE_DISCONNECTED:
+        case BLKIF_STATE_CONNECTED:
+            unexpected(status);
+            blkif_close();
+            break;
+        }
+        break;
+
+    case BLKIF_INTERFACE_STATUS_DISCONNECTED:
+        switch ( blkif_state )
+        {
+        case BLKIF_STATE_CLOSED:
+            blkif_disconnect();
+            break;
+        case BLKIF_STATE_DISCONNECTED:
+        case BLKIF_STATE_CONNECTED:
+            /* unexpected(status); */ /* occurs during suspend/resume */
+            blkif_reset();
+            break;
+        }
+        break;
+
+    case BLKIF_INTERFACE_STATUS_CONNECTED:
+        switch ( blkif_state )
+        {
+        case BLKIF_STATE_CLOSED:
+            unexpected(status);
+            blkif_disconnect();
+            blkif_connect(status);
+            break;
+        case BLKIF_STATE_DISCONNECTED:
+            blkif_connect(status);
+            break;
+        case BLKIF_STATE_CONNECTED:
+            unexpected(status);
+            blkif_connect(status);
+            break;
+        }
+        break;
+
+    case BLKIF_INTERFACE_STATUS_CHANGED:
+        switch ( blkif_state )
+        {
+        case BLKIF_STATE_CLOSED:
+        case BLKIF_STATE_DISCONNECTED:
+            unexpected(status);
+            break;
+        case BLKIF_STATE_CONNECTED:
+            vbd_update();
+            break;
+        }
+        break;
+
+    default:
+        WPRINTK(" Invalid blkif status: %d\n", status->status);
+        break;
+    }
+}
+
+
+static void blkif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id)
+{
+    switch ( msg->subtype )
+    {
+    case CMSG_BLKIF_FE_INTERFACE_STATUS:
+        blkif_status((blkif_fe_interface_status_t *)
+                     &msg->msg[0]);
+        break;
+    default:
+        msg->length = 0;
+        break;
+    }
+
+    ctrl_if_send_response(msg);
+}
+
+int wait_for_blkif(void)
+{
+    int err = 0;
+    int i;
+    send_driver_status(1);
+
+    /*
+     * We should read 'nr_interfaces' from response message and wait
+     * for notifications before proceeding. For now we assume that we
+     * will be notified of exactly one interface.
+     */
+    for ( i=0; (blkif_state != BLKIF_STATE_CONNECTED) && (i < 10*HZ); i++ )
+    {
+        set_current_state(TASK_INTERRUPTIBLE);
+        schedule_timeout(1);
+    }
+
+    if ( blkif_state != BLKIF_STATE_CONNECTED )
+    {
+        printk(KERN_INFO "xen_blk: Timeout connecting to device!\n");
+        err = -ENOSYS;
+    }
+    return err;
+}
+
+int __init xlblk_init(void)
+{
+    int i;
+
+#ifdef CONFIG_XEN_BLKDEV_GRANT
+    if ( 0 > gnttab_alloc_grant_references( MAXIMUM_OUTSTANDING_BLOCK_REQS,
+                                            &gref_head, &gref_terminal ))
+        return 1;
+    printk(KERN_ALERT "Blkif frontend is using grant tables.\n");
+#endif
+
+    if ( (xen_start_info.flags & SIF_INITDOMAIN) ||
+         (xen_start_info.flags & SIF_BLK_BE_DOMAIN) )
+        return 0;
+
+    printk(KERN_INFO "xen_blk: Initialising virtual block device driver\n");
+
+    blk_shadow_free = 0;
+    memset(blk_shadow, 0, sizeof(blk_shadow));
+    for ( i = 0; i < BLK_RING_SIZE; i++ )
+        blk_shadow[i].req.id = i+1;
+    blk_shadow[BLK_RING_SIZE-1].req.id = 0x0fffffff;
+
+    (void)ctrl_if_register_receiver(CMSG_BLKIF_FE, blkif_ctrlif_rx,
+                                    CALLBACK_IN_BLOCKING_CONTEXT);
+
+    wait_for_blkif();
+
+    return 0;
+}
+
+void blkdev_suspend(void)
+{
+}
+
+void blkdev_resume(void)
+{
+#ifdef CONFIG_XEN_BLKDEV_GRANT
+    int i, j;
+    for ( i = 0; i < BLK_RING_SIZE; i++ )
+        for ( j = 0; j < BLKIF_MAX_SEGMENTS_PER_REQUEST; j++ )
+            blk_shadow[i].req.frame_and_sects[j] |= GRANTREF_INVALID;
+#endif
+    send_driver_status(1);
+}
+
+static void blkif_completion(struct blk_shadow *s)
+{
+    int i;
+#ifdef CONFIG_XEN_BLKDEV_GRANT
+    for ( i = 0; i < s->req.nr_segments; i++ )
+        gnttab_release_grant_reference(
+            &gref_head, blkif_gref_from_fas(s->req.frame_and_sects[i]));
+#else
+    /* This is a hack to get the dirty logging bits set */
+    if ( s->req.operation == BLKIF_OP_READ )
+    {
+        for ( i = 0; i < s->req.nr_segments; i++ )
+        {
+            unsigned long pfn = s->req.frame_and_sects[i] >> PAGE_SHIFT;
+            unsigned long mfn = phys_to_machine_mapping[pfn];
+            xen_machphys_update(mfn, pfn);
+        }
+    }
+#endif
+}
diff --git a/drivers/xen/blkfront/block.h b/drivers/xen/blkfront/block.h
new file mode 100644 (file)
index 0000000..ede57ab
--- /dev/null
@@ -0,0 +1,117 @@
+/******************************************************************************
+ * block.h
+ * 
+ * Shared definitions between all levels of XenLinux Virtual block devices.
+ * 
+ * Copyright (c) 2003-2004, Keir Fraser & Steve Hand
+ * Modifications by Mark A. Williamson are (c) Intel Research Cambridge
+ * Copyright (c) 2004-2005, Christian Limpach
+ * 
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef __XEN_DRIVERS_BLOCK_H__
+#define __XEN_DRIVERS_BLOCK_H__
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/hdreg.h>
+#include <linux/blkdev.h>
+#include <linux/major.h>
+#include <linux/devfs_fs_kernel.h>
+#include <asm-xen/xen-public/xen.h>
+#include <asm-xen/xen-public/io/blkif.h>
+#include <asm-xen/xen-public/io/ring.h>
+#include <asm/io.h>
+#include <asm/atomic.h>
+#include <asm/uaccess.h>
+
+#if 0
+#define DPRINTK(_f, _a...) printk ( KERN_ALERT _f , ## _a )
+#else
+#define DPRINTK(_f, _a...) ((void)0)
+#endif
+
+#if 0
+#define DPRINTK_IOCTL(_f, _a...) printk ( KERN_ALERT _f , ## _a )
+#else
+#define DPRINTK_IOCTL(_f, _a...) ((void)0)
+#endif
+
+struct xlbd_type_info {
+    int partn_shift;
+    int partn_per_major;
+    int devs_per_major;
+    char *devname;
+    char *diskname;
+};
+
+/*
+ * We have one of these per vbd, whether ide, scsi or 'other'.  They
+ * hang in private_data off the gendisk structure. We may end up
+ * putting all kinds of interesting stuff here :-)
+ */
+struct xlbd_major_info {
+    int major;
+    int index;
+    int usage;
+    struct xlbd_type_info *type;
+};
+
+struct xlbd_disk_info {
+    int xd_device;
+    struct xlbd_major_info *mi;
+};
+
+typedef struct xen_block {
+    int usage;
+} xen_block_t;
+
+extern struct request_queue *xlbd_blk_queue;
+extern spinlock_t blkif_io_lock;
+
+extern int blkif_open(struct inode *inode, struct file *filep);
+extern int blkif_release(struct inode *inode, struct file *filep);
+extern int blkif_ioctl(struct inode *inode, struct file *filep,
+                       unsigned command, unsigned long argument);
+extern int blkif_check(dev_t dev);
+extern int blkif_revalidate(dev_t dev);
+extern void blkif_control_send(blkif_request_t *req, blkif_response_t *rsp);
+#ifdef CONFIG_XEN_BLKDEV_GRANT
+extern void blkif_control_probe_send(
+    blkif_request_t *req, blkif_response_t *rsp, unsigned long address);
+#endif
+extern void do_blkif_request (request_queue_t *rq); 
+
+extern void xlvbd_update_vbds(void);
+
+/* Virtual block-device subsystem. */
+extern int  xlvbd_init(void);
+extern void xlvbd_cleanup(void); 
+
+#endif /* __XEN_DRIVERS_BLOCK_H__ */
diff --git a/drivers/xen/blkfront/vbd.c b/drivers/xen/blkfront/vbd.c
new file mode 100644 (file)
index 0000000..b5f2b14
--- /dev/null
@@ -0,0 +1,507 @@
+/******************************************************************************
+ * vbd.c
+ * 
+ * XenLinux virtual block-device driver (xvd).
+ * 
+ * Copyright (c) 2003-2004, Keir Fraser & Steve Hand
+ * Modifications by Mark A. Williamson are (c) Intel Research Cambridge
+ * Copyright (c) 2004-2005, Christian Limpach
+ * 
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "block.h"
+#include <linux/blkdev.h>
+#include <linux/list.h>
+
+/*
+ * For convenience we distinguish between ide, scsi and 'other' (i.e.,
+ * potentially combinations of the two) in the naming scheme and in a few other
+ * places.
+ */
+
+#define NUM_IDE_MAJORS 10
+#define NUM_SCSI_MAJORS 9
+#define NUM_VBD_MAJORS 1
+
+struct lvdisk
+{
+    blkif_sector_t capacity; /*  0: Size in terms of 512-byte sectors.   */
+    blkif_vdev_t   device;   /*  8: Device number (opaque 16 bit value). */
+    u16            info; 
+    struct list_head list;
+};
+
+static struct xlbd_type_info xlbd_ide_type = {
+    .partn_shift = 6,
+    .partn_per_major = 2,
+    .devname = "ide",
+    .diskname = "hd",
+};
+
+static struct xlbd_type_info xlbd_scsi_type = {
+    .partn_shift = 4,
+    .partn_per_major = 16,
+    .devname = "sd",
+    .diskname = "sd",
+};
+
+static struct xlbd_type_info xlbd_vbd_type = {
+    .partn_shift = 4,
+    .partn_per_major = 16,
+    .devname = "xvd",
+    .diskname = "xvd",
+};
+
+static struct xlbd_major_info *major_info[NUM_IDE_MAJORS + NUM_SCSI_MAJORS +
+                                         NUM_VBD_MAJORS];
+
+#define XLBD_MAJOR_IDE_START    0
+#define XLBD_MAJOR_SCSI_START   (NUM_IDE_MAJORS)
+#define XLBD_MAJOR_VBD_START    (NUM_IDE_MAJORS + NUM_SCSI_MAJORS)
+
+#define XLBD_MAJOR_IDE_RANGE    XLBD_MAJOR_IDE_START ... XLBD_MAJOR_SCSI_START - 1
+#define XLBD_MAJOR_SCSI_RANGE   XLBD_MAJOR_SCSI_START ... XLBD_MAJOR_VBD_START - 1
+#define XLBD_MAJOR_VBD_RANGE    XLBD_MAJOR_VBD_START ... XLBD_MAJOR_VBD_START + NUM_VBD_MAJORS - 1
+
+/* Information about our VBDs. */
+#define MAX_VBDS 64
+struct list_head vbds_list;
+
+struct request_queue *xlbd_blk_queue = NULL;
+
+#define MAJOR_XEN(dev) ((dev)>>8)
+#define MINOR_XEN(dev) ((dev) & 0xff)
+
+static struct block_device_operations xlvbd_block_fops = 
+{
+    .owner  = THIS_MODULE,
+    .open  = blkif_open,
+    .release = blkif_release,
+    .ioctl  = blkif_ioctl,
+};
+
+spinlock_t blkif_io_lock = SPIN_LOCK_UNLOCKED;
+
+static struct lvdisk * xlvbd_device_alloc(void)
+{
+    struct lvdisk *ret;
+
+    ret = kmalloc(sizeof(struct lvdisk), GFP_KERNEL);
+    if ( ret ) {
+        memset(ret, '\0', sizeof(struct lvdisk));
+        INIT_LIST_HEAD(&ret->list);
+    }
+    return ret;
+}
+
+static void xlvbd_device_free(struct lvdisk *disk)
+{
+    list_del(&disk->list);
+    kfree(disk);
+}
+
+static vdisk_t * xlvbd_probe(int *ret)
+{
+    blkif_response_t rsp;
+    blkif_request_t req;
+    vdisk_t *disk_info = NULL;
+    unsigned long buf;
+    int nr;
+
+    buf = __get_free_page(GFP_KERNEL);
+    if ( !buf )
+        goto out;
+
+    memset(&req, 0, sizeof(req));
+    req.operation = BLKIF_OP_PROBE;
+    req.nr_segments = 1;
+#ifdef CONFIG_XEN_BLKDEV_GRANT
+    blkif_control_probe_send(&req, &rsp,
+                             (unsigned long)(virt_to_machine(buf)));
+#else
+    req.frame_and_sects[0] = virt_to_machine(buf) | 7;
+
+    blkif_control_send(&req, &rsp);
+#endif
+    if ( rsp.status <= 0 ) {
+        printk(KERN_ALERT "Could not probe disks (%d)\n", rsp.status);
+        goto out;
+    }
+    nr = rsp.status;
+    if ( nr > MAX_VBDS )
+        nr = MAX_VBDS;
+
+    disk_info = kmalloc(nr * sizeof(vdisk_t), GFP_KERNEL);
+    if ( disk_info )
+        memcpy(disk_info, (void *) buf, nr * sizeof(vdisk_t));
+    if ( ret )
+        *ret = nr;
+out:
+    free_page(buf);
+    return disk_info;
+}
+
+static struct xlbd_major_info *xlbd_alloc_major_info(int major, int minor, int index)
+{
+    struct xlbd_major_info *ptr;
+
+    ptr = kmalloc(sizeof(struct xlbd_major_info), GFP_KERNEL);
+    if ( !ptr )
+        return NULL;
+
+    memset(ptr, 0, sizeof(struct xlbd_major_info));
+
+    ptr->major = major;
+
+    switch (index) {
+    case XLBD_MAJOR_IDE_RANGE:
+        ptr->type = &xlbd_ide_type;
+        ptr->index = index - XLBD_MAJOR_IDE_START;
+        break;
+    case XLBD_MAJOR_SCSI_RANGE:
+        ptr->type = &xlbd_scsi_type;
+        ptr->index = index - XLBD_MAJOR_SCSI_START;
+        break;
+    case XLBD_MAJOR_VBD_RANGE:
+        ptr->type = &xlbd_vbd_type;
+        ptr->index = index - XLBD_MAJOR_VBD_START;
+        break;
+    }
+    
+    if ( register_blkdev(ptr->major, ptr->type->devname) ) {
+        printk(KERN_ALERT "XL VBD: can't get major %d with name %s\n",
+                    ptr->major, ptr->type->devname);
+        kfree(ptr);
+        return NULL;
+    }
+
+    devfs_mk_dir(ptr->type->devname);
+    major_info[index] = ptr;
+    return ptr;
+}
+
+static struct xlbd_major_info *xlbd_get_major_info(int device)
+{
+    int major, minor, index;
+
+    major = MAJOR_XEN(device);
+    minor = MINOR_XEN(device);
+
+    switch (major) {
+    case IDE0_MAJOR: index = 0; break;
+    case IDE1_MAJOR: index = 1; break;
+    case IDE2_MAJOR: index = 2; break;
+    case IDE3_MAJOR: index = 3; break;
+    case IDE4_MAJOR: index = 4; break;
+    case IDE5_MAJOR: index = 5; break;
+    case IDE6_MAJOR: index = 6; break;
+    case IDE7_MAJOR: index = 7; break;
+    case IDE8_MAJOR: index = 8; break;
+    case IDE9_MAJOR: index = 9; break;
+    case SCSI_DISK0_MAJOR: index = 10; break;
+    case SCSI_DISK1_MAJOR ... SCSI_DISK7_MAJOR:
+        index = 11 + major - SCSI_DISK1_MAJOR;
+        break;
+    case SCSI_CDROM_MAJOR: index = 18; break;
+    default: index = 19; break;
+    }
+
+    return major_info[index]
+        ? major_info[index]
+        : xlbd_alloc_major_info(major, minor, index);
+}
+
+static int xlvbd_blk_queue_alloc(struct xlbd_type_info *type)
+{
+    xlbd_blk_queue = blk_init_queue(do_blkif_request, &blkif_io_lock);
+    if ( !xlbd_blk_queue )
+        return -1;
+
+    elevator_init(xlbd_blk_queue, "noop");
+
+    /*
+    * Turn off barking 'headactive' mode. We dequeue
+    * buffer heads as soon as we pass them to back-end
+    * driver.
+    */
+    blk_queue_headactive(xlbd_blk_queue, 0);
+
+    /* Hard sector size and max sectors impersonate the equiv. hardware. */
+    blk_queue_hardsect_size(xlbd_blk_queue, 512);
+    blk_queue_max_sectors(xlbd_blk_queue, 512);
+
+    /* Each segment in a request is up to an aligned page in size. */
+    blk_queue_segment_boundary(xlbd_blk_queue, PAGE_SIZE - 1);
+    blk_queue_max_segment_size(xlbd_blk_queue, PAGE_SIZE);
+
+    /* Ensure a merged request will fit in a single I/O ring slot. */
+    blk_queue_max_phys_segments(xlbd_blk_queue, BLKIF_MAX_SEGMENTS_PER_REQUEST);
+    blk_queue_max_hw_segments(xlbd_blk_queue, BLKIF_MAX_SEGMENTS_PER_REQUEST);
+
+    /* Make sure buffer addresses are sector-aligned. */
+    blk_queue_dma_alignment(xlbd_blk_queue, 511);
+    return 0;
+}
+
+struct gendisk *xlvbd_alloc_gendisk(struct xlbd_major_info *mi, int minor,
+                    vdisk_t *disk)
+{
+    struct gendisk *gd;
+    struct xlbd_disk_info *di;
+    int nb_minors;
+
+    di = kmalloc(sizeof(struct xlbd_disk_info), GFP_KERNEL);
+    if ( !di )
+        goto out;
+    di->mi = mi;
+    di->xd_device = disk->device;
+
+    nb_minors = ((minor & ((1 << mi->type->partn_shift) - 1)) == 0)
+            ? mi->type->partn_per_major
+            : 1;
+
+    gd = alloc_disk(nb_minors);
+    if ( !gd )
+        goto out;
+
+    if ( nb_minors > 1 )
+        sprintf(gd->disk_name, "%s%c", mi->type->diskname,
+                'a' + mi->index * mi->type->partn_per_major +
+                    (minor >> mi->type->partn_shift));
+    else
+        sprintf(gd->disk_name, "%s%c%d", mi->type->diskname,
+                'a' + mi->index * mi->type->partn_per_major +
+                    (minor >> mi->type->partn_shift),
+                minor & ((1 << mi->type->partn_shift) - 1));
+
+    gd->major = mi->major;
+    gd->first_minor = minor;
+    gd->fops = &xlvbd_block_fops;
+    gd->private_data = di;
+    set_capacity(gd, disk->capacity);
+
+    if ( !xlbd_blk_queue )
+        if ( xlvbd_blk_queue_alloc(mi->type) )
+            goto out_gendisk;
+
+    gd->queue = xlbd_blk_queue;
+    add_disk(gd);
+    return gd;
+out_gendisk:
+    printk(KERN_ALERT "error gendisk\n");
+    del_gendisk(gd);
+out:
+    printk(KERN_ALERT "error out\n");
+    kfree(di);
+    return NULL;
+}
+
+static int xlvbd_device_add(struct list_head *list, vdisk_t *disk)
+{
+    struct lvdisk *new;
+    int minor;
+    dev_t device;
+    struct block_device *bd;
+    struct gendisk *gd;
+    struct xlbd_major_info *mi;
+
+    mi = xlbd_get_major_info(disk->device);
+    if ( !mi )
+        return -EPERM;
+
+    new = xlvbd_device_alloc();
+    if ( !new )
+        return -1;
+    new->capacity = disk->capacity;
+    new->device = disk->device;
+    new->info = disk->info;
+    
+    minor = MINOR_XEN(disk->device);
+    device = MKDEV(mi->major, minor);
+    
+    bd = bdget(device);
+    if ( !bd )
+        goto out;
+    
+    gd = xlvbd_alloc_gendisk(mi, minor, disk);
+    if ( !gd )
+        goto out_bd;
+
+    if ( VDISK_READONLY(disk->info) )
+        set_disk_ro(gd, 1);
+
+    switch (VDISK_TYPE(disk->info)) {
+    case VDISK_TYPE_CDROM:
+        gd->flags |= GENHD_FL_REMOVABLE | GENHD_FL_CD;
+        break;
+    case VDISK_TYPE_FLOPPY: 
+    case VDISK_TYPE_TAPE:
+        gd->flags |= GENHD_FL_REMOVABLE;
+        break;
+    case VDISK_TYPE_DISK:
+        break;
+    default:
+        printk(KERN_ALERT "XenLinux: unknown device type %d\n",
+                        VDISK_TYPE(disk->info));
+        break;
+    }    
+
+    list_add(&new->list, list);
+out_bd:
+    bdput(bd);
+out:
+    return 0;
+}
+
+static int xlvbd_device_del(struct lvdisk *disk)
+{
+    dev_t device;
+    struct block_device *bd;
+    struct gendisk *gd;
+    struct xlbd_disk_info *di;
+    int ret = 0, unused;
+
+    device = MKDEV(MAJOR_XEN(disk->device), MINOR_XEN(disk->device));
+
+    bd = bdget(device);
+    if ( !bd )
+        return -1;
+
+    gd = get_gendisk(device, &unused);
+    di = gd->private_data;
+
+    if ( di->mi->usage != 0 ) {
+        printk(KERN_ALERT "VBD removal failed: used [dev=%x]\n", device);
+        ret = -1;
+        goto out;
+    }
+
+    del_gendisk(gd);
+
+    xlvbd_device_free(disk);
+out:
+    bdput(bd);
+    return ret;
+}
+
+static int xlvbd_device_update(struct lvdisk *ldisk, vdisk_t *disk)
+{
+    dev_t device;
+    struct block_device *bd;
+    struct gendisk *gd;
+    int unused;
+
+    if ( ldisk->capacity == disk->capacity && ldisk->info == disk->info )
+        return 0;    
+
+    device = MKDEV(MAJOR_XEN(ldisk->device), MINOR_XEN(ldisk->device));
+
+    bd = bdget(device);
+    if ( !bd )
+        return -1;
+
+    gd = get_gendisk(device, &unused);
+    set_capacity(gd, disk->capacity);    
+    ldisk->capacity = disk->capacity;
+
+    bdput(bd);
+
+    return 0;
+}
+
+void xlvbd_refresh(void)
+{
+    vdisk_t *newdisks;
+    struct list_head *tmp, *tmp2;
+    struct lvdisk *disk;
+    int i, nr;
+
+    newdisks = xlvbd_probe(&nr);
+    if ( !newdisks ) {
+        printk(KERN_ALERT "failed to probe\n");
+        return;
+    }
+    
+    i = 0;
+    list_for_each_safe(tmp, tmp2, &vbds_list) {
+        disk = list_entry(tmp, struct lvdisk, list);
+        
+        for (i = 0; i < nr; i++) {
+            if ( !newdisks[i].device )
+                continue;
+            if ( disk->device == newdisks[i].device ) {
+                xlvbd_device_update(disk, &newdisks[i]);
+                newdisks[i].device = 0;
+                break;
+            }
+        }
+        if ( i == nr ) {
+            xlvbd_device_del(disk);
+            newdisks[i].device = 0;
+        }
+    }
+    for (i = 0; i < nr; i++)
+        if ( newdisks[i].device )
+            xlvbd_device_add(&vbds_list, &newdisks[i]);
+    kfree(newdisks);
+}
+
+/*
+ * xlvbd_update_vbds - reprobes the VBD status and performs updates driver
+ * state. The VBDs need to be updated in this way when the domain is
+ * initialised and also each time we receive an XLBLK_UPDATE event.
+ */
+void xlvbd_update_vbds(void)
+{
+    xlvbd_refresh();
+}
+
+/*
+ * Set up all the linux device goop for the virtual block devices
+ * (vbd's) that we know about. Note that although from the backend
+ * driver's p.o.v. VBDs are addressed simply an opaque 16-bit device
+ * number, the domain creation tools conventionally allocate these
+ * numbers to correspond to those used by 'real' linux -- this is just
+ * for convenience as it means e.g. that the same /etc/fstab can be
+ * used when booting with or without Xen.
+ */
+int xlvbd_init(void)
+{
+    int i, nr;
+    vdisk_t *disks;
+
+    INIT_LIST_HEAD(&vbds_list);
+
+    memset(major_info, 0, sizeof(major_info));
+    
+    disks = xlvbd_probe(&nr);
+    if ( !disks ) {
+        printk(KERN_ALERT "failed to probe\n");
+        return -1;
+    }
+
+    for (i = 0; i < nr; i++)
+        xlvbd_device_add(&vbds_list, &disks[i]);
+    kfree(disks);
+    return 0;
+}
diff --git a/drivers/xen/blktap/Makefile b/drivers/xen/blktap/Makefile
new file mode 100644 (file)
index 0000000..80b7ca0
--- /dev/null
@@ -0,0 +1,3 @@
+
+obj-y  := blktap_userdev.o blktap_datapath.o blktap_controlmsg.o blktap.o 
+
diff --git a/drivers/xen/blktap/blktap.c b/drivers/xen/blktap/blktap.c
new file mode 100644 (file)
index 0000000..a9a0067
--- /dev/null
@@ -0,0 +1,87 @@
+/******************************************************************************
+ * blktap.c
+ * 
+ * XenLinux virtual block-device tap.
+ * 
+ * Copyright (c) 2004, Andrew Warfield
+ *
+ * Based on the original split block driver:
+ * Copyright (c) 2003-2004, Keir Fraser & Steve Hand
+ * Modifications by Mark A. Williamson are (c) Intel Research Cambridge
+ * Copyright (c) 2004, Christian Limpach
+ * 
+ * Note that unlike the split block driver code, this driver has been developed
+ * strictly for Linux 2.6
+ */
+
+#include "blktap.h"
+
+int __init xlblktap_init(void)
+{
+    ctrl_msg_t               cmsg;
+    blkif_fe_driver_status_t fe_st;
+    blkif_be_driver_status_t be_st;
+
+    printk(KERN_INFO "Initialising Xen block tap device\n");
+
+    DPRINTK("   tap - Backend connection init:\n");
+
+
+    (void)ctrl_if_register_receiver(CMSG_BLKIF_FE, blkif_ctrlif_rx,
+                                    CALLBACK_IN_BLOCKING_CONTEXT);
+
+    /* Send a driver-UP notification to the domain controller. */
+    cmsg.type      = CMSG_BLKIF_FE;
+    cmsg.subtype   = CMSG_BLKIF_FE_DRIVER_STATUS;
+    cmsg.length    = sizeof(blkif_fe_driver_status_t);
+    fe_st.status   = BLKIF_DRIVER_STATUS_UP;
+    memcpy(cmsg.msg, &fe_st, sizeof(fe_st));
+    ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
+
+    DPRINTK("   tap - Frontend connection init:\n");
+    
+    active_reqs_init();
+    blkif_interface_init();
+    blkdev_schedule_init();
+    
+    (void)ctrl_if_register_receiver(CMSG_BLKIF_BE, blkif_ctrlif_rx, 
+                                    CALLBACK_IN_BLOCKING_CONTEXT);
+
+    /* Send a driver-UP notification to the domain controller. */
+    cmsg.type      = CMSG_BLKIF_BE;
+    cmsg.subtype   = CMSG_BLKIF_BE_DRIVER_STATUS;
+    cmsg.length    = sizeof(blkif_be_driver_status_t);
+    be_st.status   = BLKIF_DRIVER_STATUS_UP;
+    memcpy(cmsg.msg, &be_st, sizeof(be_st));
+    ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
+
+    DPRINTK("   tap - Userland channel init:\n");
+
+    blktap_init();
+
+    DPRINTK("Blkif tap device initialized.\n");
+
+    return 0;
+}
+
+#if 0 /* tap doesn't handle suspend/resume */
+void blkdev_suspend(void)
+{
+}
+
+void blkdev_resume(void)
+{
+    ctrl_msg_t               cmsg;
+    blkif_fe_driver_status_t st;    
+
+    /* Send a driver-UP notification to the domain controller. */
+    cmsg.type      = CMSG_BLKIF_FE;
+    cmsg.subtype   = CMSG_BLKIF_FE_DRIVER_STATUS;
+    cmsg.length    = sizeof(blkif_fe_driver_status_t);
+    st.status      = BLKIF_DRIVER_STATUS_UP;
+    memcpy(cmsg.msg, &st, sizeof(st));
+    ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
+}
+#endif
+
+__initcall(xlblktap_init);
diff --git a/drivers/xen/console/Makefile b/drivers/xen/console/Makefile
new file mode 100644 (file)
index 0000000..e4ffdef
--- /dev/null
@@ -0,0 +1,2 @@
+
+obj-y  := console.o
diff --git a/drivers/xen/console/console.c b/drivers/xen/console/console.c
new file mode 100644 (file)
index 0000000..142ca2b
--- /dev/null
@@ -0,0 +1,811 @@
+/******************************************************************************
+ * console.c
+ * 
+ * Virtual console driver.
+ * 
+ * Copyright (c) 2002-2004, K A Fraser.
+ * 
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial.h>
+#include <linux/major.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/bootmem.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm-xen/xen-public/event_channel.h>
+#include <asm-xen/hypervisor.h>
+#include <asm-xen/evtchn.h>
+#include <asm-xen/ctrl_if.h>
+
+/*
+ * Modes:
+ *  'xencons=off'  [XC_OFF]:     Console is disabled.
+ *  'xencons=tty'  [XC_TTY]:     Console attached to '/dev/tty[0-9]+'.
+ *  'xencons=ttyS' [XC_SERIAL]:  Console attached to '/dev/ttyS[0-9]+'.
+ *                 [XC_DEFAULT]: DOM0 -> XC_SERIAL ; all others -> XC_TTY.
+ * 
+ * NB. In mode XC_TTY, we create dummy consoles for tty2-63. This suppresses
+ * warnings from standard distro startup scripts.
+ */
+static enum { XC_OFF, XC_DEFAULT, XC_TTY, XC_SERIAL } xc_mode = XC_DEFAULT;
+static int xc_num = -1;
+
+static int __init xencons_setup(char *str)
+{
+    char *q;
+    int n;
+
+    if ( !strncmp(str, "ttyS", 4) )
+        xc_mode = XC_SERIAL;
+    else if ( !strncmp(str, "tty", 3) )
+        xc_mode = XC_TTY;
+    else if ( !strncmp(str, "off", 3) )
+        xc_mode = XC_OFF;
+
+    switch ( xc_mode )
+    {
+    case XC_SERIAL:
+        n = simple_strtol( str+4, &q, 10 );
+        if ( q > (str + 4) ) xc_num = n;
+        break;
+    case XC_TTY:
+        n = simple_strtol( str+3, &q, 10 );
+        if ( q > (str + 3) ) xc_num = n;
+        break;
+    default:
+        break;
+    }
+
+    return 1;
+}
+__setup("xencons=", xencons_setup);
+
+/* The kernel and user-land drivers share a common transmit buffer. */
+static unsigned int wbuf_size = 4096;
+#define WBUF_MASK(_i) ((_i)&(wbuf_size-1))
+static char *wbuf;
+static unsigned int wc, wp; /* write_cons, write_prod */
+
+static int __init xencons_bufsz_setup(char *str)
+{
+    unsigned int goal;
+    goal = simple_strtoul(str, NULL, 0);
+    while ( wbuf_size < goal )
+        wbuf_size <<= 1;
+    return 1;
+}
+__setup("xencons_bufsz=", xencons_bufsz_setup);
+
+/* This lock protects accesses to the common transmit buffer. */
+static spinlock_t xencons_lock = SPIN_LOCK_UNLOCKED;
+
+/* Common transmit-kick routine. */
+static void __xencons_tx_flush(void);
+
+/* This task is used to defer sending console data until there is space. */
+static void xencons_tx_flush_task_routine(void *data);
+
+static DECLARE_TQUEUE(xencons_tx_flush_task, 
+                      xencons_tx_flush_task_routine,
+                      NULL);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+static struct tty_driver *xencons_driver;
+#else
+static struct tty_driver xencons_driver;
+#endif
+
+
+/******************** Kernel console driver ********************************/
+
+static void kcons_write(
+    struct console *c, const char *s, unsigned int count)
+{
+    int           i;
+    unsigned long flags;
+
+    spin_lock_irqsave(&xencons_lock, flags);
+    
+    for ( i = 0; i < count; i++ )
+    {
+        if ( (wp - wc) >= (wbuf_size - 1) )
+            break;
+        if ( (wbuf[WBUF_MASK(wp++)] = s[i]) == '\n' )
+            wbuf[WBUF_MASK(wp++)] = '\r';
+    }
+
+    __xencons_tx_flush();
+
+    spin_unlock_irqrestore(&xencons_lock, flags);
+}
+
+static void kcons_write_dom0(
+    struct console *c, const char *s, unsigned int count)
+{
+    int rc;
+
+    while ( (count > 0) &&
+            ((rc = HYPERVISOR_console_io(
+                CONSOLEIO_write, count, (char *)s)) > 0) )
+    {
+        count -= rc;
+        s += rc;
+    }
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+static struct tty_driver *kcons_device(struct console *c, int *index)
+{
+    *index = c->index;
+    return xencons_driver;
+}
+#else
+static kdev_t kcons_device(struct console *c)
+{
+    return MKDEV(TTY_MAJOR, (xc_mode == XC_SERIAL) ? 64 : 1);
+}
+#endif
+
+static struct console kcons_info = {
+    device:  kcons_device,
+    flags:   CON_PRINTBUFFER,
+    index:   -1
+};
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+#define __RETCODE 0
+static int __init xen_console_init(void)
+#else
+#define __RETCODE
+void xen_console_init(void)
+#endif
+{
+    if ( xen_start_info.flags & SIF_INITDOMAIN )
+    {
+        if ( xc_mode == XC_DEFAULT )
+            xc_mode = XC_SERIAL;
+        kcons_info.write = kcons_write_dom0;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+        if ( xc_mode == XC_SERIAL )
+            kcons_info.flags |= CON_ENABLED;
+#endif
+    }
+    else
+    {
+        if ( xc_mode == XC_DEFAULT )
+            xc_mode = XC_TTY;
+        kcons_info.write = kcons_write;
+    }
+
+    switch ( xc_mode )
+    {
+    case XC_SERIAL:
+        strcpy(kcons_info.name, "ttyS");
+        if ( xc_num == -1 ) xc_num = 0;
+        break;
+
+    case XC_TTY:
+        strcpy(kcons_info.name, "tty");
+        if ( xc_num == -1 ) xc_num = 1;
+        break;
+
+    default:
+        return __RETCODE;
+    }
+
+    wbuf = alloc_bootmem(wbuf_size);
+
+    register_console(&kcons_info);
+
+    return __RETCODE;
+}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+console_initcall(xen_console_init);
+#endif
+
+/*** Useful function for console debugging -- goes straight to Xen. ***/
+asmlinkage int xprintk(const char *fmt, ...)
+{
+    va_list args;
+    int printk_len;
+    static char printk_buf[1024];
+    
+    /* Emit the output into the temporary buffer */
+    va_start(args, fmt);
+    printk_len = vsnprintf(printk_buf, sizeof(printk_buf), fmt, args);
+    va_end(args);
+
+    /* Send the processed output directly to Xen. */
+    kcons_write_dom0(NULL, printk_buf, printk_len);
+
+    return 0;
+}
+
+/*** Forcibly flush console data before dying. ***/
+void xencons_force_flush(void)
+{
+    ctrl_msg_t msg;
+    int        sz;
+
+    /* Emergency console is synchronous, so there's nothing to flush. */
+    if ( xen_start_info.flags & SIF_INITDOMAIN )
+        return;
+
+    /*
+     * We use dangerous control-interface functions that require a quiescent
+     * system and no interrupts. Try to ensure this with a global cli().
+     */
+    local_irq_disable(); /* XXXsmp */
+
+    /* Spin until console data is flushed through to the domain controller. */
+    while ( (wc != wp) && !ctrl_if_transmitter_empty() )
+    {
+        /* Interrupts are disabled -- we must manually reap responses. */
+        ctrl_if_discard_responses();
+
+        if ( (sz = wp - wc) == 0 )
+            continue;
+        if ( sz > sizeof(msg.msg) )
+            sz = sizeof(msg.msg);
+        if ( sz > (wbuf_size - WBUF_MASK(wc)) )
+            sz = wbuf_size - WBUF_MASK(wc);
+
+        msg.type    = CMSG_CONSOLE;
+        msg.subtype = CMSG_CONSOLE_DATA;
+        msg.length  = sz;
+        memcpy(msg.msg, &wbuf[WBUF_MASK(wc)], sz);
+            
+        if ( ctrl_if_send_message_noblock(&msg, NULL, 0) == 0 )
+            wc += sz;
+    }
+}
+
+
+/******************** User-space console driver (/dev/console) ************/
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+#define DRV(_d)         (_d)
+#define TTY_INDEX(_tty) ((_tty)->index)
+#else
+static int xencons_refcount;
+static struct tty_struct *xencons_table[MAX_NR_CONSOLES];
+#define DRV(_d)         (&(_d))
+#define TTY_INDEX(_tty) (MINOR((_tty)->device) - xencons_driver.minor_start)
+#endif
+
+static struct termios *xencons_termios[MAX_NR_CONSOLES];
+static struct termios *xencons_termios_locked[MAX_NR_CONSOLES];
+static struct tty_struct *xencons_tty;
+static int xencons_priv_irq;
+static char x_char;
+
+/* Non-privileged receive callback. */
+static void xencons_rx(ctrl_msg_t *msg, unsigned long id)
+{
+    int           i;
+    unsigned long flags;
+
+    spin_lock_irqsave(&xencons_lock, flags);
+    if ( xencons_tty != NULL )
+    {
+        for ( i = 0; i < msg->length; i++ )
+            tty_insert_flip_char(xencons_tty, msg->msg[i], 0);
+        tty_flip_buffer_push(xencons_tty);
+    }
+    spin_unlock_irqrestore(&xencons_lock, flags);
+
+    msg->length = 0;
+    ctrl_if_send_response(msg);
+}
+
+/* Privileged and non-privileged transmit worker. */
+static void __xencons_tx_flush(void)
+{
+    int        sz, work_done = 0;
+    ctrl_msg_t msg;
+
+    if ( xen_start_info.flags & SIF_INITDOMAIN )
+    {
+        if ( x_char )
+        {
+            kcons_write_dom0(NULL, &x_char, 1);
+            x_char = 0;
+            work_done = 1;
+        }
+
+        while ( wc != wp )
+        {
+            sz = wp - wc;
+            if ( sz > (wbuf_size - WBUF_MASK(wc)) )
+                sz = wbuf_size - WBUF_MASK(wc);
+            kcons_write_dom0(NULL, &wbuf[WBUF_MASK(wc)], sz);
+            wc += sz;
+            work_done = 1;
+        }
+    }
+    else
+    {
+        while ( x_char )
+        {
+            msg.type    = CMSG_CONSOLE;
+            msg.subtype = CMSG_CONSOLE_DATA;
+            msg.length  = 1;
+            msg.msg[0]  = x_char;
+
+            if ( ctrl_if_send_message_noblock(&msg, NULL, 0) == 0 )
+                x_char = 0;
+            else if ( ctrl_if_enqueue_space_callback(&xencons_tx_flush_task) )
+                break;
+
+            work_done = 1;
+        }
+
+        while ( wc != wp )
+        {
+            sz = wp - wc;
+            if ( sz > sizeof(msg.msg) )
+                sz = sizeof(msg.msg);
+            if ( sz > (wbuf_size - WBUF_MASK(wc)) )
+                sz = wbuf_size - WBUF_MASK(wc);
+
+            msg.type    = CMSG_CONSOLE;
+            msg.subtype = CMSG_CONSOLE_DATA;
+            msg.length  = sz;
+            memcpy(msg.msg, &wbuf[WBUF_MASK(wc)], sz);
+            
+            if ( ctrl_if_send_message_noblock(&msg, NULL, 0) == 0 )
+                wc += sz;
+            else if ( ctrl_if_enqueue_space_callback(&xencons_tx_flush_task) )
+                break;
+
+            work_done = 1;
+        }
+    }
+
+    if ( work_done && (xencons_tty != NULL) )
+    {
+        wake_up_interruptible(&xencons_tty->write_wait);
+        if ( (xencons_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+             (xencons_tty->ldisc.write_wakeup != NULL) )
+            (xencons_tty->ldisc.write_wakeup)(xencons_tty);
+    }
+}
+
+/* Non-privileged transmit kicker. */
+static void xencons_tx_flush_task_routine(void *data)
+{
+    unsigned long flags;
+    spin_lock_irqsave(&xencons_lock, flags);
+    __xencons_tx_flush();
+    spin_unlock_irqrestore(&xencons_lock, flags);
+}
+
+/* Privileged receive callback and transmit kicker. */
+static irqreturn_t xencons_priv_interrupt(int irq, void *dev_id,
+                                          struct pt_regs *regs)
+{
+    static char   rbuf[16];
+    int           i, l;
+    unsigned long flags;
+
+    spin_lock_irqsave(&xencons_lock, flags);
+
+    if ( xencons_tty != NULL )
+    {
+        /* Receive work. */
+        while ( (l = HYPERVISOR_console_io(CONSOLEIO_read, 16, rbuf)) > 0 )
+            for ( i = 0; i < l; i++ )
+                tty_insert_flip_char(xencons_tty, rbuf[i], 0);
+        if ( xencons_tty->flip.count != 0 )
+            tty_flip_buffer_push(xencons_tty);
+    }
+
+    /* Transmit work. */
+    __xencons_tx_flush();
+
+    spin_unlock_irqrestore(&xencons_lock, flags);
+
+    return IRQ_HANDLED;
+}
+
+static int xencons_write_room(struct tty_struct *tty)
+{
+    return wbuf_size - (wp - wc);
+}
+
+static int xencons_chars_in_buffer(struct tty_struct *tty)
+{
+    return wp - wc;
+}
+
+static void xencons_send_xchar(struct tty_struct *tty, char ch)
+{
+    unsigned long flags;
+
+    if ( TTY_INDEX(tty) != 0 )
+        return;
+
+    spin_lock_irqsave(&xencons_lock, flags);
+    x_char = ch;
+    __xencons_tx_flush();
+    spin_unlock_irqrestore(&xencons_lock, flags);
+}
+
+static void xencons_throttle(struct tty_struct *tty)
+{
+    if ( TTY_INDEX(tty) != 0 )
+        return;
+
+    if ( I_IXOFF(tty) )
+        xencons_send_xchar(tty, STOP_CHAR(tty));
+}
+
+static void xencons_unthrottle(struct tty_struct *tty)
+{
+    if ( TTY_INDEX(tty) != 0 )
+        return;
+
+    if ( I_IXOFF(tty) )
+    {
+        if ( x_char != 0 )
+            x_char = 0;
+        else
+            xencons_send_xchar(tty, START_CHAR(tty));
+    }
+}
+
+static void xencons_flush_buffer(struct tty_struct *tty)
+{
+    unsigned long flags;
+
+    if ( TTY_INDEX(tty) != 0 )
+        return;
+
+    spin_lock_irqsave(&xencons_lock, flags);
+    wc = wp = 0;
+    spin_unlock_irqrestore(&xencons_lock, flags);
+}
+
+static inline int __xencons_put_char(int ch)
+{
+    char _ch = (char)ch;
+    if ( (wp - wc) == wbuf_size )
+        return 0;
+    wbuf[WBUF_MASK(wp++)] = _ch;
+    return 1;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+static int xencons_write(
+    struct tty_struct *tty,
+    const unsigned char *buf,
+    int count)
+{
+    int i;
+    unsigned long flags;
+
+    if ( TTY_INDEX(tty) != 0 )
+        return count;
+
+    spin_lock_irqsave(&xencons_lock, flags);
+
+    for ( i = 0; i < count; i++ )
+        if ( !__xencons_put_char(buf[i]) )
+            break;
+
+    if ( i != 0 )
+        __xencons_tx_flush();
+
+    spin_unlock_irqrestore(&xencons_lock, flags);
+
+    return i;
+}
+#else
+static int xencons_write(
+    struct tty_struct *tty, 
+    int from_user,
+    const u_char *buf, 
+    int count)
+{
+    int i;
+    unsigned long flags;
+
+    if ( from_user && verify_area(VERIFY_READ, buf, count) )
+        return -EINVAL;
+
+    if ( TTY_INDEX(tty) != 0 )
+        return count;
+
+    spin_lock_irqsave(&xencons_lock, flags);
+
+    for ( i = 0; i < count; i++ )
+    {
+        char ch;
+        if ( from_user )
+            __get_user(ch, buf + i);
+        else
+            ch = buf[i];
+        if ( !__xencons_put_char(ch) )
+            break;
+    }
+
+    if ( i != 0 )
+        __xencons_tx_flush();
+
+    spin_unlock_irqrestore(&xencons_lock, flags);
+
+    return i;
+}
+#endif
+
+static void xencons_put_char(struct tty_struct *tty, u_char ch)
+{
+    unsigned long flags;
+
+    if ( TTY_INDEX(tty) != 0 )
+        return;
+
+    spin_lock_irqsave(&xencons_lock, flags);
+    (void)__xencons_put_char(ch);
+    spin_unlock_irqrestore(&xencons_lock, flags);
+}
+
+static void xencons_flush_chars(struct tty_struct *tty)
+{
+    unsigned long flags;
+
+    if ( TTY_INDEX(tty) != 0 )
+        return;
+
+    spin_lock_irqsave(&xencons_lock, flags);
+    __xencons_tx_flush();
+    spin_unlock_irqrestore(&xencons_lock, flags);    
+}
+
+static void xencons_wait_until_sent(struct tty_struct *tty, int timeout)
+{
+    unsigned long orig_jiffies = jiffies;
+
+    if ( TTY_INDEX(tty) != 0 )
+        return;
+
+    while ( DRV(tty->driver)->chars_in_buffer(tty) )
+    {
+        set_current_state(TASK_INTERRUPTIBLE);
+        schedule_timeout(1);
+        if ( signal_pending(current) )
+            break;
+        if ( (timeout != 0) && time_after(jiffies, orig_jiffies + timeout) )
+            break;
+    }
+    
+    set_current_state(TASK_RUNNING);
+}
+
+static int xencons_open(struct tty_struct *tty, struct file *filp)
+{
+    unsigned long flags;
+
+    if ( TTY_INDEX(tty) != 0 )
+        return 0;
+
+    spin_lock_irqsave(&xencons_lock, flags);
+    tty->driver_data = NULL;
+    if ( xencons_tty == NULL )
+        xencons_tty = tty;
+    __xencons_tx_flush();
+    spin_unlock_irqrestore(&xencons_lock, flags);    
+
+    return 0;
+}
+
+static void xencons_close(struct tty_struct *tty, struct file *filp)
+{
+    unsigned long flags;
+
+    if ( TTY_INDEX(tty) != 0 )
+        return;
+
+    if ( tty->count == 1 )
+    {
+        tty->closing = 1;
+        tty_wait_until_sent(tty, 0);
+        if ( DRV(tty->driver)->flush_buffer != NULL )
+            DRV(tty->driver)->flush_buffer(tty);
+        if ( tty->ldisc.flush_buffer != NULL )
+            tty->ldisc.flush_buffer(tty);
+        tty->closing = 0;
+        spin_lock_irqsave(&xencons_lock, flags);
+        xencons_tty = NULL;
+        spin_unlock_irqrestore(&xencons_lock, flags);    
+    }
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+static struct tty_operations xencons_ops = {
+    .open = xencons_open,
+    .close = xencons_close,
+    .write = xencons_write,
+    .write_room = xencons_write_room,
+    .put_char = xencons_put_char,
+    .flush_chars = xencons_flush_chars,
+    .chars_in_buffer = xencons_chars_in_buffer,
+    .send_xchar = xencons_send_xchar,
+    .flush_buffer = xencons_flush_buffer,
+    .throttle = xencons_throttle,
+    .unthrottle = xencons_unthrottle,
+    .wait_until_sent = xencons_wait_until_sent,
+};
+
+#ifdef CONFIG_XEN_PRIVILEGED_GUEST
+static const char *xennullcon_startup(void)
+{
+    return NULL;
+}
+
+static int xennullcon_dummy(void)
+{
+    return 0;
+}
+
+#define DUMMY (void *)xennullcon_dummy
+
+/*
+ *  The console `switch' structure for the dummy console
+ *
+ *  Most of the operations are dummies.
+ */
+
+const struct consw xennull_con = {
+    .owner =           THIS_MODULE,
+    .con_startup =     xennullcon_startup,
+    .con_init =                DUMMY,
+    .con_deinit =      DUMMY,
+    .con_clear =       DUMMY,
+    .con_putc =                DUMMY,
+    .con_putcs =       DUMMY,
+    .con_cursor =      DUMMY,
+    .con_scroll =      DUMMY,
+    .con_bmove =       DUMMY,
+    .con_switch =      DUMMY,
+    .con_blank =       DUMMY,
+    .con_font_set =    DUMMY,
+    .con_font_get =    DUMMY,
+    .con_font_default =        DUMMY,
+    .con_font_copy =   DUMMY,
+    .con_set_palette = DUMMY,
+    .con_scrolldelta = DUMMY,
+};
+#endif
+#endif
+
+static int __init xencons_init(void)
+{
+    int rc;
+
+    if ( xc_mode == XC_OFF )
+        return 0;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    xencons_driver = alloc_tty_driver((xc_mode == XC_SERIAL) ? 
+                                      1 : MAX_NR_CONSOLES);
+    if ( xencons_driver == NULL )
+        return -ENOMEM;
+#else
+    memset(&xencons_driver, 0, sizeof(struct tty_driver));
+    xencons_driver.magic       = TTY_DRIVER_MAGIC;
+    xencons_driver.refcount    = &xencons_refcount;
+    xencons_driver.table       = xencons_table;
+    xencons_driver.num         = (xc_mode == XC_SERIAL) ? 1 : MAX_NR_CONSOLES;
+#endif
+
+    DRV(xencons_driver)->major           = TTY_MAJOR;
+    DRV(xencons_driver)->type            = TTY_DRIVER_TYPE_SERIAL;
+    DRV(xencons_driver)->subtype         = SERIAL_TYPE_NORMAL;
+    DRV(xencons_driver)->init_termios    = tty_std_termios;
+    DRV(xencons_driver)->flags           = 
+        TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_NO_DEVFS;
+    DRV(xencons_driver)->termios         = xencons_termios;
+    DRV(xencons_driver)->termios_locked  = xencons_termios_locked;
+
+    if ( xc_mode == XC_SERIAL )
+    {
+        DRV(xencons_driver)->name        = "ttyS";
+        DRV(xencons_driver)->minor_start = 64 + xc_num;
+        DRV(xencons_driver)->name_base   = 0 + xc_num;
+    }
+    else
+    {
+        DRV(xencons_driver)->name        = "tty";
+        DRV(xencons_driver)->minor_start = xc_num;
+        DRV(xencons_driver)->name_base   = xc_num;
+    }
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    tty_set_operations(xencons_driver, &xencons_ops);
+#else
+    xencons_driver.open            = xencons_open;
+    xencons_driver.close           = xencons_close;
+    xencons_driver.write           = xencons_write;
+    xencons_driver.write_room      = xencons_write_room;
+    xencons_driver.put_char        = xencons_put_char;
+    xencons_driver.flush_chars     = xencons_flush_chars;
+    xencons_driver.chars_in_buffer = xencons_chars_in_buffer;
+    xencons_driver.send_xchar      = xencons_send_xchar;
+    xencons_driver.flush_buffer    = xencons_flush_buffer;
+    xencons_driver.throttle        = xencons_throttle;
+    xencons_driver.unthrottle      = xencons_unthrottle;
+    xencons_driver.wait_until_sent = xencons_wait_until_sent;
+#endif
+
+    if ( (rc = tty_register_driver(DRV(xencons_driver))) != 0 )
+    {
+        printk("WARNING: Failed to register Xen virtual "
+               "console driver as '%s%d'\n",
+               DRV(xencons_driver)->name, DRV(xencons_driver)->name_base);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+        put_tty_driver(xencons_driver);
+        xencons_driver = NULL;
+#endif
+        return rc;
+    }
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    tty_register_device(xencons_driver, 0, NULL);
+#endif
+
+    if ( xen_start_info.flags & SIF_INITDOMAIN )
+    {
+        xencons_priv_irq = bind_virq_to_irq(VIRQ_CONSOLE);
+        (void)request_irq(xencons_priv_irq,
+                          xencons_priv_interrupt, 0, "console", NULL);
+    }
+    else
+    {
+        (void)ctrl_if_register_receiver(CMSG_CONSOLE, xencons_rx, 0);
+    }
+
+    printk("Xen virtual console successfully installed as %s%d\n",
+           DRV(xencons_driver)->name,
+           DRV(xencons_driver)->name_base );
+    
+    return 0;
+}
+
+module_init(xencons_init);
diff --git a/drivers/xen/evtchn/Makefile b/drivers/xen/evtchn/Makefile
new file mode 100644 (file)
index 0000000..7b082a0
--- /dev/null
@@ -0,0 +1,2 @@
+
+obj-y  := evtchn.o
diff --git a/drivers/xen/evtchn/evtchn.c b/drivers/xen/evtchn/evtchn.c
new file mode 100644 (file)
index 0000000..f5da428
--- /dev/null
@@ -0,0 +1,430 @@
+/******************************************************************************
+ * evtchn.c
+ * 
+ * Xenolinux driver for receiving and demuxing event-channel signals.
+ * 
+ * Copyright (c) 2004, K A Fraser
+ * Multi-process extensions Copyright (c) 2004, Steven Smith
+ * 
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/errno.h>
+#include <linux/miscdevice.h>
+#include <linux/major.h>
+#include <linux/proc_fs.h>
+#include <linux/stat.h>
+#include <linux/poll.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#define XEN_EVTCHN_MASK_OPS
+#include <asm-xen/evtchn.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+#include <linux/devfs_fs_kernel.h>
+#define OLD_DEVFS
+#else
+#include <linux/gfp.h>
+#endif
+
+#ifdef OLD_DEVFS
+/* NB. This must be shared amongst drivers if more things go in /dev/xen */
+static devfs_handle_t xen_dev_dir;
+#endif
+
+struct per_user_data {
+    /* Notification ring, accessed via /dev/xen/evtchn. */
+#   define EVTCHN_RING_SIZE     2048  /* 2048 16-bit entries */
+#   define EVTCHN_RING_MASK(_i) ((_i)&(EVTCHN_RING_SIZE-1))
+    u16 *ring;
+    unsigned int ring_cons, ring_prod, ring_overflow;
+
+    /* Processes wait on this queue when ring is empty. */
+    wait_queue_head_t evtchn_wait;
+    struct fasync_struct *evtchn_async_queue;
+};
+
+/* Who's bound to each port? */
+static struct per_user_data *port_user[NR_EVENT_CHANNELS];
+static spinlock_t port_user_lock;
+
+void evtchn_device_upcall(int port)
+{
+    struct per_user_data *u;
+
+    spin_lock(&port_user_lock);
+
+    mask_evtchn(port);
+    clear_evtchn(port);
+
+    if ( (u = port_user[port]) != NULL )
+    {
+        if ( (u->ring_prod - u->ring_cons) < EVTCHN_RING_SIZE )
+        {
+            u->ring[EVTCHN_RING_MASK(u->ring_prod)] = (u16)port;
+            if ( u->ring_cons == u->ring_prod++ )
+            {
+                wake_up_interruptible(&u->evtchn_wait);
+                kill_fasync(&u->evtchn_async_queue, SIGIO, POLL_IN);
+            }
+        }
+        else
+        {
+            u->ring_overflow = 1;
+        }
+    }
+
+    spin_unlock(&port_user_lock);
+}
+
+static ssize_t evtchn_read(struct file *file, char *buf,
+                           size_t count, loff_t *ppos)
+{
+    int rc;
+    unsigned int c, p, bytes1 = 0, bytes2 = 0;
+    DECLARE_WAITQUEUE(wait, current);
+    struct per_user_data *u = file->private_data;
+
+    add_wait_queue(&u->evtchn_wait, &wait);
+
+    count &= ~1; /* even number of bytes */
+
+    if ( count == 0 )
+    {
+        rc = 0;
+        goto out;
+    }
+
+    if ( count > PAGE_SIZE )
+        count = PAGE_SIZE;
+
+    for ( ; ; )
+    {
+        set_current_state(TASK_INTERRUPTIBLE);
+
+        if ( (c = u->ring_cons) != (p = u->ring_prod) )
+            break;
+
+        if ( u->ring_overflow )
+        {
+            rc = -EFBIG;
+            goto out;
+        }
+
+        if ( file->f_flags & O_NONBLOCK )
+        {
+            rc = -EAGAIN;
+            goto out;
+        }
+
+        if ( signal_pending(current) )
+        {
+            rc = -ERESTARTSYS;
+            goto out;
+        }
+
+        schedule();
+    }
+
+    /* Byte lengths of two chunks. Chunk split (if any) is at ring wrap. */
+    if ( ((c ^ p) & EVTCHN_RING_SIZE) != 0 )
+    {
+        bytes1 = (EVTCHN_RING_SIZE - EVTCHN_RING_MASK(c)) * sizeof(u16);
+        bytes2 = EVTCHN_RING_MASK(p) * sizeof(u16);
+    }
+    else
+    {
+        bytes1 = (p - c) * sizeof(u16);
+        bytes2 = 0;
+    }
+
+    /* Truncate chunks according to caller's maximum byte count. */
+    if ( bytes1 > count )
+    {
+        bytes1 = count;
+        bytes2 = 0;
+    }
+    else if ( (bytes1 + bytes2) > count )
+    {
+        bytes2 = count - bytes1;
+    }
+
+    if ( copy_to_user(buf, &u->ring[EVTCHN_RING_MASK(c)], bytes1) ||
+         ((bytes2 != 0) && copy_to_user(&buf[bytes1], &u->ring[0], bytes2)) )
+    {
+        rc = -EFAULT;
+        goto out;
+    }
+
+    u->ring_cons += (bytes1 + bytes2) / sizeof(u16);
+
+    rc = bytes1 + bytes2;
+
+ out:
+    __set_current_state(TASK_RUNNING);
+    remove_wait_queue(&u->evtchn_wait, &wait);
+    return rc;
+}
+
+static ssize_t evtchn_write(struct file *file, const char *buf,
+                            size_t count, loff_t *ppos)
+{
+    int  rc, i;
+    u16 *kbuf = (u16 *)__get_free_page(GFP_KERNEL);
+    struct per_user_data *u = file->private_data;
+
+    if ( kbuf == NULL )
+        return -ENOMEM;
+
+    count &= ~1; /* even number of bytes */
+
+    if ( count == 0 )
+    {
+        rc = 0;
+        goto out;
+    }
+
+    if ( count > PAGE_SIZE )
+        count = PAGE_SIZE;
+
+    if ( copy_from_user(kbuf, buf, count) != 0 )
+    {
+        rc = -EFAULT;
+        goto out;
+    }
+
+    spin_lock_irq(&port_user_lock);
+    for ( i = 0; i < (count/2); i++ )
+        if ( (kbuf[i] < NR_EVENT_CHANNELS) && (port_user[kbuf[i]] == u) )
+            unmask_evtchn(kbuf[i]);
+    spin_unlock_irq(&port_user_lock);
+
+    rc = count;
+
+ out:
+    free_page((unsigned long)kbuf);
+    return rc;
+}
+
+static int evtchn_ioctl(struct inode *inode, struct file *file,
+                        unsigned int cmd, unsigned long arg)
+{
+    int rc = 0;
+    struct per_user_data *u = file->private_data;
+
+    spin_lock_irq(&port_user_lock);
+    
+    switch ( cmd )
+    {
+    case EVTCHN_RESET:
+        /* Initialise the ring to empty. Clear errors. */
+        u->ring_cons = u->ring_prod = u->ring_overflow = 0;
+        break;
+
+    case EVTCHN_BIND:
+        if ( arg >= NR_EVENT_CHANNELS )
+        {
+            rc = -EINVAL;
+        }
+        else if ( port_user[arg] != NULL )
+        {
+            rc = -EISCONN;
+        }
+        else
+        {
+            port_user[arg] = u;
+            unmask_evtchn(arg);
+        }
+        break;
+
+    case EVTCHN_UNBIND:
+        if ( arg >= NR_EVENT_CHANNELS )
+        {
+            rc = -EINVAL;
+        }
+        else if ( port_user[arg] != u )
+        {
+            rc = -ENOTCONN;
+        }
+        else
+        {
+            port_user[arg] = NULL;
+            mask_evtchn(arg);
+        }
+        break;
+
+    default:
+        rc = -ENOSYS;
+        break;
+    }
+
+    spin_unlock_irq(&port_user_lock);   
+
+    return rc;
+}
+
+static unsigned int evtchn_poll(struct file *file, poll_table *wait)
+{
+    unsigned int mask = POLLOUT | POLLWRNORM;
+    struct per_user_data *u = file->private_data;
+
+    poll_wait(file, &u->evtchn_wait, wait);
+    if ( u->ring_cons != u->ring_prod )
+        mask |= POLLIN | POLLRDNORM;
+    if ( u->ring_overflow )
+        mask = POLLERR;
+    return mask;
+}
+
+static int evtchn_fasync(int fd, struct file *filp, int on)
+{
+    struct per_user_data *u = filp->private_data;
+    return fasync_helper(fd, filp, on, &u->evtchn_async_queue);
+}
+
+static int evtchn_open(struct inode *inode, struct file *filp)
+{
+    struct per_user_data *u;
+
+    if ( (u = kmalloc(sizeof(*u), GFP_KERNEL)) == NULL )
+        return -ENOMEM;
+
+    memset(u, 0, sizeof(*u));
+    init_waitqueue_head(&u->evtchn_wait);
+
+    if ( (u->ring = (u16 *)__get_free_page(GFP_KERNEL)) == NULL )
+    {
+        kfree(u);
+        return -ENOMEM;
+    }
+
+    filp->private_data = u;
+
+    return 0;
+}
+
+static int evtchn_release(struct inode *inode, struct file *filp)
+{
+    int i;
+    struct per_user_data *u = filp->private_data;
+
+    spin_lock_irq(&port_user_lock);
+
+    free_page((unsigned long)u->ring);
+
+    for ( i = 0; i < NR_EVENT_CHANNELS; i++ )
+    {
+        if ( port_user[i] == u )
+        {
+            port_user[i] = NULL;
+            mask_evtchn(i);
+        }
+    }
+
+    spin_unlock_irq(&port_user_lock);
+
+    return 0;
+}
+
+static struct file_operations evtchn_fops = {
+    owner:    THIS_MODULE,
+    read:     evtchn_read,
+    write:    evtchn_write,
+    ioctl:    evtchn_ioctl,
+    poll:     evtchn_poll,
+    fasync:   evtchn_fasync,
+    open:     evtchn_open,
+    release:  evtchn_release
+};
+
+static struct miscdevice evtchn_miscdev = {
+    .minor        = EVTCHN_MINOR,
+    .name         = "evtchn",
+    .fops         = &evtchn_fops,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    .devfs_name   = "misc/evtchn",
+#endif
+};
+
+static int __init evtchn_init(void)
+{
+#ifdef OLD_DEVFS
+    devfs_handle_t symlink_handle;
+    int            pos;
+    char           link_dest[64];
+#endif
+    int err;
+
+    spin_lock_init(&port_user_lock);
+    memset(port_user, 0, sizeof(port_user));
+
+    /* (DEVFS) create '/dev/misc/evtchn'. */
+    err = misc_register(&evtchn_miscdev);
+    if ( err != 0 )
+    {
+        printk(KERN_ALERT "Could not register /dev/misc/evtchn\n");
+        return err;
+    }
+
+#ifdef OLD_DEVFS
+    /* (DEVFS) create directory '/dev/xen'. */
+    xen_dev_dir = devfs_mk_dir(NULL, "xen", NULL);
+
+    /* (DEVFS) &link_dest[pos] == '../misc/evtchn'. */
+    pos = devfs_generate_path(evtchn_miscdev.devfs_handle, 
+                              &link_dest[3], 
+                              sizeof(link_dest) - 3);
+    if ( pos >= 0 )
+        strncpy(&link_dest[pos], "../", 3);
+
+    /* (DEVFS) symlink '/dev/xen/evtchn' -> '../misc/evtchn'. */
+    (void)devfs_mk_symlink(xen_dev_dir, 
+                           "evtchn", 
+                           DEVFS_FL_DEFAULT, 
+                           &link_dest[pos],
+                           &symlink_handle, 
+                           NULL);
+
+    /* (DEVFS) automatically destroy the symlink with its destination. */
+    devfs_auto_unregister(evtchn_miscdev.devfs_handle, symlink_handle);
+#endif
+
+    printk("Event-channel device installed.\n");
+
+    return 0;
+}
+
+static void evtchn_cleanup(void)
+{
+    misc_deregister(&evtchn_miscdev);
+}
+
+module_init(evtchn_init);
+module_exit(evtchn_cleanup);
diff --git a/drivers/xen/netback/Makefile b/drivers/xen/netback/Makefile
new file mode 100644 (file)
index 0000000..3279442
--- /dev/null
@@ -0,0 +1,2 @@
+
+obj-y  := netback.o control.o interface.o
diff --git a/drivers/xen/netback/common.h b/drivers/xen/netback/common.h
new file mode 100644 (file)
index 0000000..dfb750e
--- /dev/null
@@ -0,0 +1,103 @@
+/******************************************************************************
+ * arch/xen/drivers/netif/backend/common.h
+ */
+
+#ifndef __NETIF__BACKEND__COMMON_H__
+#define __NETIF__BACKEND__COMMON_H__
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/ip.h>
+#include <linux/in.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <asm-xen/ctrl_if.h>
+#include <asm-xen/xen-public/io/netif.h>
+#include <asm/io.h>
+#include <asm/pgalloc.h>
+
+#if 0
+#define ASSERT(_p) \
+    if ( !(_p) ) { printk("Assertion '%s' failed, line %d, file %s", #_p , \
+    __LINE__, __FILE__); *(int*)0=0; }
+#define DPRINTK(_f, _a...) printk(KERN_ALERT "(file=%s, line=%d) " _f, \
+                           __FILE__ , __LINE__ , ## _a )
+#else
+#define ASSERT(_p) ((void)0)
+#define DPRINTK(_f, _a...) ((void)0)
+#endif
+
+typedef struct netif_st {
+    /* Unique identifier for this interface. */
+    domid_t          domid;
+    unsigned int     handle;
+
+    u8               fe_dev_addr[6];
+
+    /* Physical parameters of the comms window. */
+    unsigned long    tx_shmem_frame;
+    unsigned long    rx_shmem_frame;
+    unsigned int     evtchn;
+    int              irq;
+
+    /* The shared rings and indexes. */
+    netif_tx_interface_t *tx;
+    netif_rx_interface_t *rx;
+
+    /* Private indexes into shared ring. */
+    NETIF_RING_IDX rx_req_cons;
+    NETIF_RING_IDX rx_resp_prod; /* private version of shared variable */
+    NETIF_RING_IDX tx_req_cons;
+    NETIF_RING_IDX tx_resp_prod; /* private version of shared variable */
+
+    /* Transmit shaping: allow 'credit_bytes' every 'credit_usec'. */
+    unsigned long   credit_bytes;
+    unsigned long   credit_usec;
+    unsigned long   remaining_credit;
+    struct timer_list credit_timeout;
+
+    /* Miscellaneous private stuff. */
+    enum { DISCONNECTED, DISCONNECTING, CONNECTED } status;
+    int active;
+    /*
+     * DISCONNECT response is deferred until pending requests are ack'ed.
+     * We therefore need to store the id from the original request.
+     */
+    u8               disconnect_rspid;
+    struct netif_st *hash_next;
+    struct list_head list;  /* scheduling list */
+    atomic_t         refcnt;
+    struct net_device *dev;
+    struct net_device_stats stats;
+
+    struct work_struct work;
+} netif_t;
+
+void netif_create(netif_be_create_t *create);
+void netif_destroy(netif_be_destroy_t *destroy);
+void netif_creditlimit(netif_be_creditlimit_t *creditlimit);
+void netif_connect(netif_be_connect_t *connect);
+int  netif_disconnect(netif_be_disconnect_t *disconnect, u8 rsp_id);
+void netif_disconnect_complete(netif_t *netif);
+netif_t *netif_find_by_handle(domid_t domid, unsigned int handle);
+#define netif_get(_b) (atomic_inc(&(_b)->refcnt))
+#define netif_put(_b)                             \
+    do {                                          \
+        if ( atomic_dec_and_test(&(_b)->refcnt) ) \
+            netif_disconnect_complete(_b);        \
+    } while (0)
+
+void netif_interface_init(void);
+void netif_ctrlif_init(void);
+
+void netif_schedule_work(netif_t *netif);
+void netif_deschedule_work(netif_t *netif);
+
+int netif_be_start_xmit(struct sk_buff *skb, struct net_device *dev);
+struct net_device_stats *netif_be_get_stats(struct net_device *dev);
+irqreturn_t netif_be_int(int irq, void *dev_id, struct pt_regs *regs);
+
+#endif /* __NETIF__BACKEND__COMMON_H__ */
diff --git a/drivers/xen/netback/interface.c b/drivers/xen/netback/interface.c
new file mode 100644 (file)
index 0000000..f509a1b
--- /dev/null
@@ -0,0 +1,380 @@
+/******************************************************************************
+ * arch/xen/drivers/netif/backend/interface.c
+ * 
+ * Network-device interface management.
+ * 
+ * Copyright (c) 2004-2005, Keir Fraser
+ */
+
+#include "common.h"
+#include <linux/rtnetlink.h>
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+#endif
+
+#define NETIF_HASHSZ 1024
+#define NETIF_HASH(_d,_h) (((int)(_d)^(int)(_h))&(NETIF_HASHSZ-1))
+
+static netif_t *netif_hash[NETIF_HASHSZ];
+
+netif_t *netif_find_by_handle(domid_t domid, unsigned int handle)
+{
+    netif_t *netif = netif_hash[NETIF_HASH(domid, handle)];
+    while ( (netif != NULL) && 
+            ((netif->domid != domid) || (netif->handle != handle)) )
+        netif = netif->hash_next;
+    return netif;
+}
+
+static void __netif_up(netif_t *netif)
+{
+    struct net_device *dev = netif->dev;
+    spin_lock_bh(&dev->xmit_lock);
+    netif->active = 1;
+    spin_unlock_bh(&dev->xmit_lock);
+    (void)request_irq(netif->irq, netif_be_int, 0, dev->name, netif);
+    netif_schedule_work(netif);
+}
+
+static void __netif_down(netif_t *netif)
+{
+    struct net_device *dev = netif->dev;
+    spin_lock_bh(&dev->xmit_lock);
+    netif->active = 0;
+    spin_unlock_bh(&dev->xmit_lock);
+    free_irq(netif->irq, netif);
+    netif_deschedule_work(netif);
+}
+
+static int net_open(struct net_device *dev)
+{
+    netif_t *netif = netdev_priv(dev);
+    if ( netif->status == CONNECTED )
+        __netif_up(netif);
+    netif_start_queue(dev);
+    return 0;
+}
+
+static int net_close(struct net_device *dev)
+{
+    netif_t *netif = netdev_priv(dev);
+    netif_stop_queue(dev);
+    if ( netif->status == CONNECTED )
+        __netif_down(netif);
+    return 0;
+}
+
+static void __netif_disconnect_complete(void *arg)
+{
+    netif_t              *netif = (netif_t *)arg;
+    ctrl_msg_t            cmsg;
+    netif_be_disconnect_t disc;
+
+    /*
+     * These can't be done in netif_disconnect() because at that point there
+     * may be outstanding requests in the network stack whose asynchronous
+     * responses must still be notified to the remote driver.
+     */
+    unbind_evtchn_from_irq(netif->evtchn);
+    vfree(netif->tx); /* Frees netif->rx as well. */
+
+    /* Construct the deferred response message. */
+    cmsg.type         = CMSG_NETIF_BE;
+    cmsg.subtype      = CMSG_NETIF_BE_DISCONNECT;
+    cmsg.id           = netif->disconnect_rspid;
+    cmsg.length       = sizeof(netif_be_disconnect_t);
+    disc.domid        = netif->domid;
+    disc.netif_handle = netif->handle;
+    disc.status       = NETIF_BE_STATUS_OKAY;
+    memcpy(cmsg.msg, &disc, sizeof(disc));
+
+    /*
+     * Make sure message is constructed /before/ status change, because
+     * after the status change the 'netif' structure could be deallocated at
+     * any time. Also make sure we send the response /after/ status change,
+     * as otherwise a subsequent CONNECT request could spuriously fail if
+     * another CPU doesn't see the status change yet.
+     */
+    mb();
+    if ( netif->status != DISCONNECTING )
+        BUG();
+    netif->status = DISCONNECTED;
+    mb();
+
+    /* Send the successful response. */
+    ctrl_if_send_response(&cmsg);
+}
+
+void netif_disconnect_complete(netif_t *netif)
+{
+    INIT_WORK(&netif->work, __netif_disconnect_complete, (void *)netif);
+    schedule_work(&netif->work);
+}
+
+void netif_create(netif_be_create_t *create)
+{
+    int                err = 0;
+    domid_t            domid  = create->domid;
+    unsigned int       handle = create->netif_handle;
+    struct net_device *dev;
+    netif_t          **pnetif, *netif;
+    char               name[IFNAMSIZ] = {};
+
+    snprintf(name, IFNAMSIZ - 1, "vif%u.%u", domid, handle);
+    dev = alloc_netdev(sizeof(netif_t), name, ether_setup);
+    if ( dev == NULL )
+    {
+        DPRINTK("Could not create netif: out of memory\n");
+        create->status = NETIF_BE_STATUS_OUT_OF_MEMORY;
+        return;
+    }
+
+    netif = netdev_priv(dev);
+    memset(netif, 0, sizeof(*netif));
+    netif->domid  = domid;
+    netif->handle = handle;
+    netif->status = DISCONNECTED;
+    atomic_set(&netif->refcnt, 0);
+    netif->dev = dev;
+
+    netif->credit_bytes = netif->remaining_credit = ~0UL;
+    netif->credit_usec  = 0UL;
+    init_timer(&netif->credit_timeout);
+
+    pnetif = &netif_hash[NETIF_HASH(domid, handle)];
+    while ( *pnetif != NULL )
+    {
+        if ( ((*pnetif)->domid == domid) && ((*pnetif)->handle == handle) )
+        {
+            DPRINTK("Could not create netif: already exists\n");
+            create->status = NETIF_BE_STATUS_INTERFACE_EXISTS;
+            free_netdev(dev);
+            return;
+        }
+        pnetif = &(*pnetif)->hash_next;
+    }
+
+    dev->hard_start_xmit = netif_be_start_xmit;
+    dev->get_stats       = netif_be_get_stats;
+    dev->open            = net_open;
+    dev->stop            = net_close;
+
+    /* Disable queuing. */
+    dev->tx_queue_len = 0;
+
+    if ( (create->be_mac[0] == 0) && (create->be_mac[1] == 0) &&
+         (create->be_mac[2] == 0) && (create->be_mac[3] == 0) &&
+         (create->be_mac[4] == 0) && (create->be_mac[5] == 0) )
+    {
+        /*
+         * Initialise a dummy MAC address. We choose the numerically largest
+         * non-broadcast address to prevent the address getting stolen by an
+         * Ethernet bridge for STP purposes. (FE:FF:FF:FF:FF:FF)
+         */ 
+        memset(dev->dev_addr, 0xFF, ETH_ALEN);
+        dev->dev_addr[0] &= ~0x01;
+    }
+    else
+    {
+        memcpy(dev->dev_addr, create->be_mac, ETH_ALEN);
+    }
+
+    memcpy(netif->fe_dev_addr, create->mac, ETH_ALEN);
+
+    rtnl_lock();
+    err = register_netdevice(dev);
+    rtnl_unlock();
+
+    if ( err != 0 )
+    {
+        DPRINTK("Could not register new net device %s: err=%d\n",
+                dev->name, err);
+        create->status = NETIF_BE_STATUS_OUT_OF_MEMORY;
+        free_netdev(dev);
+        return;
+    }
+
+    netif->hash_next = *pnetif;
+    *pnetif = netif;
+
+    DPRINTK("Successfully created netif\n");
+    create->status = NETIF_BE_STATUS_OKAY;
+}
+
+void netif_destroy(netif_be_destroy_t *destroy)
+{
+    domid_t       domid  = destroy->domid;
+    unsigned int  handle = destroy->netif_handle;
+    netif_t     **pnetif, *netif;
+
+    pnetif = &netif_hash[NETIF_HASH(domid, handle)];
+    while ( (netif = *pnetif) != NULL )
+    {
+        if ( (netif->domid == domid) && (netif->handle == handle) )
+        {
+            if ( netif->status != DISCONNECTED )
+                goto still_connected;
+            goto destroy;
+        }
+        pnetif = &netif->hash_next;
+    }
+
+    destroy->status = NETIF_BE_STATUS_INTERFACE_NOT_FOUND;
+    return;
+
+ still_connected:
+    destroy->status = NETIF_BE_STATUS_INTERFACE_CONNECTED;
+    return;
+
+ destroy:
+    *pnetif = netif->hash_next;
+    unregister_netdev(netif->dev);
+    free_netdev(netif->dev);
+    destroy->status = NETIF_BE_STATUS_OKAY;
+}
+
+void netif_creditlimit(netif_be_creditlimit_t *creditlimit)
+{
+    domid_t       domid  = creditlimit->domid;
+    unsigned int  handle = creditlimit->netif_handle;
+    netif_t      *netif;
+
+    netif = netif_find_by_handle(domid, handle);
+    if ( unlikely(netif == NULL) )
+    {
+        DPRINTK("netif_creditlimit attempted for non-existent netif"
+                " (%u,%u)\n", creditlimit->domid, creditlimit->netif_handle); 
+        creditlimit->status = NETIF_BE_STATUS_INTERFACE_NOT_FOUND;
+        return; 
+    }
+
+    /* Set the credit limit (reset remaining credit to new limit). */
+    netif->credit_bytes = netif->remaining_credit = creditlimit->credit_bytes;
+    netif->credit_usec = creditlimit->period_usec;
+
+    if ( netif->status == CONNECTED )
+    {
+        /*
+         * Schedule work so that any packets waiting under previous credit 
+         * limit are dealt with (acts like a replenishment point).
+         */
+        netif->credit_timeout.expires = jiffies;
+        netif_schedule_work(netif);
+    }
+    
+    creditlimit->status = NETIF_BE_STATUS_OKAY;
+}
+
+void netif_connect(netif_be_connect_t *connect)
+{
+    domid_t       domid  = connect->domid;
+    unsigned int  handle = connect->netif_handle;
+    unsigned int  evtchn = connect->evtchn;
+    unsigned long tx_shmem_frame = connect->tx_shmem_frame;
+    unsigned long rx_shmem_frame = connect->rx_shmem_frame;
+    struct vm_struct *vma;
+    pgprot_t      prot;
+    int           error;
+    netif_t      *netif;
+
+    netif = netif_find_by_handle(domid, handle);
+    if ( unlikely(netif == NULL) )
+    {
+        DPRINTK("netif_connect attempted for non-existent netif (%u,%u)\n", 
+                connect->domid, connect->netif_handle); 
+        connect->status = NETIF_BE_STATUS_INTERFACE_NOT_FOUND;
+        return;
+    }
+
+    if ( netif->status != DISCONNECTED )
+    {
+        connect->status = NETIF_BE_STATUS_INTERFACE_CONNECTED;
+        return;
+    }
+
+    if ( (vma = get_vm_area(2*PAGE_SIZE, VM_IOREMAP)) == NULL )
+    {
+        connect->status = NETIF_BE_STATUS_OUT_OF_MEMORY;
+        return;
+    }
+
+    prot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED);
+    error  = direct_remap_area_pages(&init_mm, 
+                                     VMALLOC_VMADDR(vma->addr),
+                                     tx_shmem_frame<<PAGE_SHIFT, PAGE_SIZE,
+                                     prot, domid);
+    error |= direct_remap_area_pages(&init_mm, 
+                                     VMALLOC_VMADDR(vma->addr) + PAGE_SIZE,
+                                     rx_shmem_frame<<PAGE_SHIFT, PAGE_SIZE,
+                                     prot, domid);
+    if ( error != 0 )
+    {
+        if ( error == -ENOMEM )
+            connect->status = NETIF_BE_STATUS_OUT_OF_MEMORY;
+        else if ( error == -EFAULT )
+            connect->status = NETIF_BE_STATUS_MAPPING_ERROR;
+        else
+            connect->status = NETIF_BE_STATUS_ERROR;
+        vfree(vma->addr);
+        return;
+    }
+
+    netif->evtchn         = evtchn;
+    netif->irq            = bind_evtchn_to_irq(evtchn);
+    netif->tx_shmem_frame = tx_shmem_frame;
+    netif->rx_shmem_frame = rx_shmem_frame;
+    netif->tx             = 
+        (netif_tx_interface_t *)vma->addr;
+    netif->rx             = 
+        (netif_rx_interface_t *)((char *)vma->addr + PAGE_SIZE);
+    netif->tx->resp_prod = netif->rx->resp_prod = 0;
+    netif_get(netif);
+    wmb(); /* Other CPUs see new state before interface is started. */
+
+    rtnl_lock();
+    netif->status = CONNECTED;
+    wmb();
+    if ( netif_running(netif->dev) )
+        __netif_up(netif);
+    rtnl_unlock();
+
+    connect->status = NETIF_BE_STATUS_OKAY;
+}
+
+int netif_disconnect(netif_be_disconnect_t *disconnect, u8 rsp_id)
+{
+    domid_t       domid  = disconnect->domid;
+    unsigned int  handle = disconnect->netif_handle;
+    netif_t      *netif;
+
+    netif = netif_find_by_handle(domid, handle);
+    if ( unlikely(netif == NULL) )
+    {
+        DPRINTK("netif_disconnect attempted for non-existent netif"
+                " (%u,%u)\n", disconnect->domid, disconnect->netif_handle); 
+        disconnect->status = NETIF_BE_STATUS_INTERFACE_NOT_FOUND;
+        return 1; /* Caller will send response error message. */
+    }
+
+    if ( netif->status == CONNECTED )
+    {
+        rtnl_lock();
+        netif->status = DISCONNECTING;
+        netif->disconnect_rspid = rsp_id;
+        wmb();
+        if ( netif_running(netif->dev) )
+            __netif_down(netif);
+        rtnl_unlock();
+        netif_put(netif);
+        return 0; /* Caller should not send response message. */
+    }
+
+    disconnect->status = NETIF_BE_STATUS_OKAY;
+    return 1;
+}
+
+void netif_interface_init(void)
+{
+    memset(netif_hash, 0, sizeof(netif_hash));
+}
diff --git a/drivers/xen/netback/netback.c b/drivers/xen/netback/netback.c
new file mode 100644 (file)
index 0000000..d08c296
--- /dev/null
@@ -0,0 +1,819 @@
+/******************************************************************************
+ * drivers/xen/netback/netback.c
+ * 
+ * Back-end of the driver for virtual network devices. This portion of the
+ * driver exports a 'unified' network-device interface that can be accessed
+ * by any operating system that implements a compatible front end. A 
+ * reference front-end implementation can be found in:
+ *  drivers/xen/netfront/netfront.c
+ * 
+ * Copyright (c) 2002-2005, K A Fraser
+ */
+
+#include "common.h"
+#include <asm-xen/balloon.h>
+#include <asm-xen/evtchn.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+#include <linux/delay.h>
+#endif
+
+static void netif_idx_release(u16 pending_idx);
+static void netif_page_release(struct page *page);
+static void make_tx_response(netif_t *netif, 
+                             u16      id,
+                             s8       st);
+static int  make_rx_response(netif_t *netif, 
+                             u16      id, 
+                             s8       st,
+                             memory_t addr,
+                             u16      size);
+
+static void net_tx_action(unsigned long unused);
+static DECLARE_TASKLET(net_tx_tasklet, net_tx_action, 0);
+
+static void net_rx_action(unsigned long unused);
+static DECLARE_TASKLET(net_rx_tasklet, net_rx_action, 0);
+
+static struct timer_list net_timer;
+
+static struct sk_buff_head rx_queue;
+static multicall_entry_t rx_mcl[NETIF_RX_RING_SIZE*2+1];
+static mmu_update_t rx_mmu[NETIF_RX_RING_SIZE];
+static struct mmuext_op rx_mmuext[NETIF_RX_RING_SIZE];
+static unsigned char rx_notify[NR_EVENT_CHANNELS];
+
+/* Don't currently gate addition of an interface to the tx scheduling list. */
+#define tx_work_exists(_if) (1)
+
+#define MAX_PENDING_REQS 256
+static unsigned long mmap_vstart;
+#define MMAP_VADDR(_req) (mmap_vstart + ((_req) * PAGE_SIZE))
+
+#define PKT_PROT_LEN 64
+
+static struct {
+    netif_tx_request_t req;
+    netif_t *netif;
+} pending_tx_info[MAX_PENDING_REQS];
+static u16 pending_ring[MAX_PENDING_REQS];
+typedef unsigned int PEND_RING_IDX;
+#define MASK_PEND_IDX(_i) ((_i)&(MAX_PENDING_REQS-1))
+static PEND_RING_IDX pending_prod, pending_cons;
+#define NR_PENDING_REQS (MAX_PENDING_REQS - pending_prod + pending_cons)
+
+/* Freed TX SKBs get batched on this ring before return to pending_ring. */
+static u16 dealloc_ring[MAX_PENDING_REQS];
+static PEND_RING_IDX dealloc_prod, dealloc_cons;
+
+static struct sk_buff_head tx_queue;
+static multicall_entry_t tx_mcl[MAX_PENDING_REQS];
+
+static struct list_head net_schedule_list;
+static spinlock_t net_schedule_list_lock;
+
+#define MAX_MFN_ALLOC 64
+static unsigned long mfn_list[MAX_MFN_ALLOC];
+static unsigned int alloc_index = 0;
+static spinlock_t mfn_lock = SPIN_LOCK_UNLOCKED;
+
+static unsigned long alloc_mfn(void)
+{
+    unsigned long mfn = 0, flags;
+    spin_lock_irqsave(&mfn_lock, flags);
+    if ( unlikely(alloc_index == 0) )
+        alloc_index = HYPERVISOR_dom_mem_op(
+            MEMOP_increase_reservation, mfn_list, MAX_MFN_ALLOC, 0);
+    if ( alloc_index != 0 )
+        mfn = mfn_list[--alloc_index];
+    spin_unlock_irqrestore(&mfn_lock, flags);
+    return mfn;
+}
+
+static void free_mfn(unsigned long mfn)
+{
+    unsigned long flags;
+    spin_lock_irqsave(&mfn_lock, flags);
+    if ( alloc_index != MAX_MFN_ALLOC )
+        mfn_list[alloc_index++] = mfn;
+    else if ( HYPERVISOR_dom_mem_op(MEMOP_decrease_reservation,
+                                    &mfn, 1, 0) != 1 )
+        BUG();
+    spin_unlock_irqrestore(&mfn_lock, flags);
+}
+
+static inline void maybe_schedule_tx_action(void)
+{
+    smp_mb();
+    if ( (NR_PENDING_REQS < (MAX_PENDING_REQS/2)) &&
+         !list_empty(&net_schedule_list) )
+        tasklet_schedule(&net_tx_tasklet);
+}
+
+/*
+ * A gross way of confirming the origin of an skb data page. The slab
+ * allocator abuses a field in the page struct to cache the kmem_cache_t ptr.
+ */
+static inline int is_xen_skb(struct sk_buff *skb)
+{
+    extern kmem_cache_t *skbuff_cachep;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    kmem_cache_t *cp = (kmem_cache_t *)virt_to_page(skb->head)->lru.next;
+#else
+    kmem_cache_t *cp = (kmem_cache_t *)virt_to_page(skb->head)->list.next;
+#endif
+    return (cp == skbuff_cachep);
+}
+
+int netif_be_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+    netif_t *netif = netdev_priv(dev);
+
+    ASSERT(skb->dev == dev);
+
+    /* Drop the packet if the target domain has no receive buffers. */
+    if ( !netif->active || 
+         (netif->rx_req_cons == netif->rx->req_prod) ||
+         ((netif->rx_req_cons-netif->rx_resp_prod) == NETIF_RX_RING_SIZE) )
+        goto drop;
+
+    /*
+     * We do not copy the packet unless:
+     *  1. The data is shared; or
+     *  2. The data is not allocated from our special cache.
+     * NB. We also couldn't cope with fragmented packets, but we won't get
+     *     any because we not advertise the NETIF_F_SG feature.
+     */
+    if ( skb_shared(skb) || skb_cloned(skb) || !is_xen_skb(skb) )
+    {
+        int hlen = skb->data - skb->head;
+        struct sk_buff *nskb = dev_alloc_skb(hlen + skb->len);
+        if ( unlikely(nskb == NULL) )
+            goto drop;
+        skb_reserve(nskb, hlen);
+        __skb_put(nskb, skb->len);
+        (void)skb_copy_bits(skb, -hlen, nskb->data - hlen, skb->len + hlen);
+        nskb->dev = skb->dev;
+        dev_kfree_skb(skb);
+        skb = nskb;
+    }
+
+    netif->rx_req_cons++;
+    netif_get(netif);
+
+    skb_queue_tail(&rx_queue, skb);
+    tasklet_schedule(&net_rx_tasklet);
+
+    return 0;
+
+ drop:
+    netif->stats.tx_dropped++;
+    dev_kfree_skb(skb);
+    return 0;
+}
+
+#if 0
+static void xen_network_done_notify(void)
+{
+    static struct net_device *eth0_dev = NULL;
+    if ( unlikely(eth0_dev == NULL) )
+        eth0_dev = __dev_get_by_name("eth0");
+    netif_rx_schedule(eth0_dev);
+}
+/* 
+ * Add following to poll() function in NAPI driver (Tigon3 is example):
+ *  if ( xen_network_done() )
+ *      tg3_enable_ints(tp); 
+ */
+int xen_network_done(void)
+{
+    return skb_queue_empty(&rx_queue);
+}
+#endif
+
+static void net_rx_action(unsigned long unused)
+{
+    netif_t *netif;
+    s8 status;
+    u16 size, id, evtchn;
+    multicall_entry_t *mcl;
+    mmu_update_t *mmu;
+    struct mmuext_op *mmuext;
+    unsigned long vdata, mdata, new_mfn;
+    struct sk_buff_head rxq;
+    struct sk_buff *skb;
+    u16 notify_list[NETIF_RX_RING_SIZE];
+    int notify_nr = 0;
+
+    skb_queue_head_init(&rxq);
+
+    mcl = rx_mcl;
+    mmu = rx_mmu;
+    mmuext = rx_mmuext;
+    while ( (skb = skb_dequeue(&rx_queue)) != NULL )
+    {
+        netif   = netdev_priv(skb->dev);
+        vdata   = (unsigned long)skb->data;
+        mdata   = virt_to_machine(vdata);
+
+        /* Memory squeeze? Back off for an arbitrary while. */
+        if ( (new_mfn = alloc_mfn()) == 0 )
+        {
+            if ( net_ratelimit() )
+                printk(KERN_WARNING "Memory squeeze in netback driver.\n");
+            mod_timer(&net_timer, jiffies + HZ);
+            skb_queue_head(&rx_queue, skb);
+            break;
+        }
+
+        /*
+         * Set the new P2M table entry before reassigning the old data page.
+         * Heed the comment in pgtable-2level.h:pte_page(). :-)
+         */
+        phys_to_machine_mapping[__pa(skb->data) >> PAGE_SHIFT] = new_mfn;
+        
+        mcl->op = __HYPERVISOR_update_va_mapping;
+        mcl->args[0] = vdata;
+        mcl->args[1] = (new_mfn << PAGE_SHIFT) | __PAGE_KERNEL;
+        mcl->args[2] = 0;
+        mcl++;
+
+        mcl->op = __HYPERVISOR_mmuext_op;
+        mcl->args[0] = (unsigned long)mmuext;
+        mcl->args[1] = 1;
+        mcl->args[2] = 0;
+        mcl->args[3] = netif->domid;
+        mcl++;
+
+        mmuext->cmd = MMUEXT_REASSIGN_PAGE;
+        mmuext->mfn = mdata >> PAGE_SHIFT;
+        mmuext++;
+
+        mmu->ptr = (new_mfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
+        mmu->val = __pa(vdata) >> PAGE_SHIFT;  
+        mmu++;
+
+        __skb_queue_tail(&rxq, skb);
+
+        /* Filled the batch queue? */
+        if ( (mcl - rx_mcl) == ARRAY_SIZE(rx_mcl) )
+            break;
+    }
+
+    if ( mcl == rx_mcl )
+        return;
+
+    mcl->op = __HYPERVISOR_mmu_update;
+    mcl->args[0] = (unsigned long)rx_mmu;
+    mcl->args[1] = mmu - rx_mmu;
+    mcl->args[2] = 0;
+    mcl->args[3] = DOMID_SELF;
+    mcl++;
+
+    mcl[-3].args[2] = UVMF_TLB_FLUSH|UVMF_ALL;
+    if ( unlikely(HYPERVISOR_multicall(rx_mcl, mcl - rx_mcl) != 0) )
+        BUG();
+
+    mcl = rx_mcl;
+    mmuext = rx_mmuext;
+    while ( (skb = __skb_dequeue(&rxq)) != NULL )
+    {
+        netif   = netdev_priv(skb->dev);
+        size    = skb->tail - skb->data;
+
+        /* Rederive the machine addresses. */
+        new_mfn = mcl[0].args[1] >> PAGE_SHIFT;
+        mdata   = ((mmuext[0].mfn << PAGE_SHIFT) |
+                   ((unsigned long)skb->data & ~PAGE_MASK));
+        
+        atomic_set(&(skb_shinfo(skb)->dataref), 1);
+        skb_shinfo(skb)->nr_frags = 0;
+        skb_shinfo(skb)->frag_list = NULL;
+
+        netif->stats.tx_bytes += size;
+        netif->stats.tx_packets++;
+
+        /* The update_va_mapping() must not fail. */
+        if ( unlikely(mcl[0].args[5] != 0) )
+            BUG();
+
+        /* Check the reassignment error code. */
+        status = NETIF_RSP_OKAY;
+        if ( unlikely(mcl[1].args[5] != 0) )
+        {
+            DPRINTK("Failed MMU update transferring to DOM%u\n", netif->domid);
+            free_mfn(mdata >> PAGE_SHIFT);
+            status = NETIF_RSP_ERROR;
+        }
+
+        evtchn = netif->evtchn;
+        id = netif->rx->ring[MASK_NETIF_RX_IDX(netif->rx_resp_prod)].req.id;
+        if ( make_rx_response(netif, id, status, mdata, size) &&
+             (rx_notify[evtchn] == 0) )
+        {
+            rx_notify[evtchn] = 1;
+            notify_list[notify_nr++] = evtchn;
+        }
+
+        netif_put(netif);
+        dev_kfree_skb(skb);
+
+        mcl += 2;
+        mmuext += 1;
+    }
+
+    while ( notify_nr != 0 )
+    {
+        evtchn = notify_list[--notify_nr];
+        rx_notify[evtchn] = 0;
+        notify_via_evtchn(evtchn);
+    }
+
+    /* More work to do? */
+    if ( !skb_queue_empty(&rx_queue) && !timer_pending(&net_timer) )
+        tasklet_schedule(&net_rx_tasklet);
+#if 0
+    else
+        xen_network_done_notify();
+#endif
+}
+
+static void net_alarm(unsigned long unused)
+{
+    tasklet_schedule(&net_rx_tasklet);
+}
+
+struct net_device_stats *netif_be_get_stats(struct net_device *dev)
+{
+    netif_t *netif = netdev_priv(dev);
+    return &netif->stats;
+}
+
+static int __on_net_schedule_list(netif_t *netif)
+{
+    return netif->list.next != NULL;
+}
+
+static void remove_from_net_schedule_list(netif_t *netif)
+{
+    spin_lock_irq(&net_schedule_list_lock);
+    if ( likely(__on_net_schedule_list(netif)) )
+    {
+        list_del(&netif->list);
+        netif->list.next = NULL;
+        netif_put(netif);
+    }
+    spin_unlock_irq(&net_schedule_list_lock);
+}
+
+static void add_to_net_schedule_list_tail(netif_t *netif)
+{
+    if ( __on_net_schedule_list(netif) )
+        return;
+
+    spin_lock_irq(&net_schedule_list_lock);
+    if ( !__on_net_schedule_list(netif) && netif->active )
+    {
+        list_add_tail(&netif->list, &net_schedule_list);
+        netif_get(netif);
+    }
+    spin_unlock_irq(&net_schedule_list_lock);
+}
+
+void netif_schedule_work(netif_t *netif)
+{
+    if ( (netif->tx_req_cons != netif->tx->req_prod) &&
+         ((netif->tx_req_cons-netif->tx_resp_prod) != NETIF_TX_RING_SIZE) )
+    {
+        add_to_net_schedule_list_tail(netif);
+        maybe_schedule_tx_action();
+    }
+}
+
+void netif_deschedule_work(netif_t *netif)
+{
+    remove_from_net_schedule_list(netif);
+}
+
+
+static void tx_credit_callback(unsigned long data)
+{
+    netif_t *netif = (netif_t *)data;
+    netif->remaining_credit = netif->credit_bytes;
+    netif_schedule_work(netif);
+}
+
+static void net_tx_action(unsigned long unused)
+{
+    struct list_head *ent;
+    struct sk_buff *skb;
+    netif_t *netif;
+    netif_tx_request_t txreq;
+    u16 pending_idx;
+    NETIF_RING_IDX i;
+    multicall_entry_t *mcl;
+    PEND_RING_IDX dc, dp;
+    unsigned int data_len;
+
+    if ( (dc = dealloc_cons) == (dp = dealloc_prod) )
+        goto skip_dealloc;
+
+    mcl = tx_mcl;
+    while ( dc != dp )
+    {
+        pending_idx = dealloc_ring[MASK_PEND_IDX(dc++)];
+        mcl[0].op = __HYPERVISOR_update_va_mapping;
+        mcl[0].args[0] = MMAP_VADDR(pending_idx);
+        mcl[0].args[1] = 0;
+        mcl[0].args[2] = 0;
+        mcl++;     
+    }
+
+    mcl[-1].args[2] = UVMF_TLB_FLUSH|UVMF_ALL;
+    if ( unlikely(HYPERVISOR_multicall(tx_mcl, mcl - tx_mcl) != 0) )
+        BUG();
+
+    mcl = tx_mcl;
+    while ( dealloc_cons != dp )
+    {
+        /* The update_va_mapping() must not fail. */
+        if ( unlikely(mcl[0].args[5] != 0) )
+            BUG();
+
+        pending_idx = dealloc_ring[MASK_PEND_IDX(dealloc_cons++)];
+
+        netif = pending_tx_info[pending_idx].netif;
+
+        make_tx_response(netif, pending_tx_info[pending_idx].req.id, 
+                         NETIF_RSP_OKAY);
+        
+        pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx;
+
+        /*
+         * Scheduling checks must happen after the above response is posted.
+         * This avoids a possible race with a guest OS on another CPU if that
+         * guest is testing against 'resp_prod' when deciding whether to notify
+         * us when it queues additional packets.
+         */
+        mb();
+        if ( (netif->tx_req_cons != netif->tx->req_prod) &&
+             ((netif->tx_req_cons-netif->tx_resp_prod) != NETIF_TX_RING_SIZE) )
+            add_to_net_schedule_list_tail(netif);
+        
+        netif_put(netif);
+
+        mcl++;
+    }
+
+ skip_dealloc:
+    mcl = tx_mcl;
+    while ( (NR_PENDING_REQS < MAX_PENDING_REQS) &&
+            !list_empty(&net_schedule_list) )
+    {
+        /* Get a netif from the list with work to do. */
+        ent = net_schedule_list.next;
+        netif = list_entry(ent, netif_t, list);
+        netif_get(netif);
+        remove_from_net_schedule_list(netif);
+
+        /* Work to do? */
+        i = netif->tx_req_cons;
+        if ( (i == netif->tx->req_prod) ||
+             ((i-netif->tx_resp_prod) == NETIF_TX_RING_SIZE) )
+        {
+            netif_put(netif);
+            continue;
+        }
+
+        rmb(); /* Ensure that we see the request before we copy it. */
+        memcpy(&txreq, &netif->tx->ring[MASK_NETIF_TX_IDX(i)].req, 
+               sizeof(txreq));
+
+        /* Credit-based scheduling. */
+        if ( txreq.size > netif->remaining_credit )
+        {
+            unsigned long now = jiffies;
+            unsigned long next_credit = 
+                netif->credit_timeout.expires +
+                msecs_to_jiffies(netif->credit_usec / 1000);
+
+            /* Timer could already be pending in some rare cases. */
+            if ( timer_pending(&netif->credit_timeout) )
+                break;
+
+            /* Already passed the point at which we can replenish credit? */
+            if ( time_after_eq(now, next_credit) )
+            {
+                netif->credit_timeout.expires = now;
+                netif->remaining_credit = netif->credit_bytes;
+            }
+
+            /* Still too big to send right now? Then set a timer callback. */
+            if ( txreq.size > netif->remaining_credit )
+            {
+                netif->remaining_credit = 0;
+                netif->credit_timeout.expires  = next_credit;
+                netif->credit_timeout.data     = (unsigned long)netif;
+                netif->credit_timeout.function = tx_credit_callback;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+                add_timer_on(&netif->credit_timeout, smp_processor_id());
+#else
+                add_timer(&netif->credit_timeout); 
+#endif
+                break;
+            }
+        }
+        netif->remaining_credit -= txreq.size;
+
+        /*
+         * Why the barrier? It ensures that the frontend sees updated req_cons
+         * before we check for more work to schedule.
+         */
+        netif->tx->req_cons = ++netif->tx_req_cons;
+        mb();
+
+        netif_schedule_work(netif);
+
+        if ( unlikely(txreq.size < ETH_HLEN) || 
+             unlikely(txreq.size > ETH_FRAME_LEN) )
+        {
+            DPRINTK("Bad packet size: %d\n", txreq.size);
+            make_tx_response(netif, txreq.id, NETIF_RSP_ERROR);
+            netif_put(netif);
+            continue; 
+        }
+
+        /* No crossing a page boundary as the payload mustn't fragment. */
+        if ( unlikely(((txreq.addr & ~PAGE_MASK) + txreq.size) >= PAGE_SIZE) ) 
+        {
+            DPRINTK("txreq.addr: %lx, size: %u, end: %lu\n", 
+                    txreq.addr, txreq.size, 
+                    (txreq.addr &~PAGE_MASK) + txreq.size);
+            make_tx_response(netif, txreq.id, NETIF_RSP_ERROR);
+            netif_put(netif);
+            continue;
+        }
+
+        pending_idx = pending_ring[MASK_PEND_IDX(pending_cons)];
+
+        data_len = (txreq.size > PKT_PROT_LEN) ? PKT_PROT_LEN : txreq.size;
+
+        if ( unlikely((skb = alloc_skb(data_len+16, GFP_ATOMIC)) == NULL) )
+        {
+            DPRINTK("Can't allocate a skb in start_xmit.\n");
+            make_tx_response(netif, txreq.id, NETIF_RSP_ERROR);
+            netif_put(netif);
+            break;
+        }
+
+        /* Packets passed to netif_rx() must have some headroom. */
+        skb_reserve(skb, 16);
+
+        mcl[0].op = __HYPERVISOR_update_va_mapping_otherdomain;
+        mcl[0].args[0] = MMAP_VADDR(pending_idx);
+        mcl[0].args[1] = (txreq.addr & PAGE_MASK) | __PAGE_KERNEL;
+        mcl[0].args[2] = 0;
+        mcl[0].args[3] = netif->domid;
+        mcl++;
+
+        memcpy(&pending_tx_info[pending_idx].req, &txreq, sizeof(txreq));
+        pending_tx_info[pending_idx].netif = netif;
+        *((u16 *)skb->data) = pending_idx;
+
+        __skb_queue_tail(&tx_queue, skb);
+
+        pending_cons++;
+
+        /* Filled the batch queue? */
+        if ( (mcl - tx_mcl) == ARRAY_SIZE(tx_mcl) )
+            break;
+    }
+
+    if ( mcl == tx_mcl )
+        return;
+
+    if ( unlikely(HYPERVISOR_multicall(tx_mcl, mcl - tx_mcl) != 0) )
+        BUG();
+
+    mcl = tx_mcl;
+    while ( (skb = __skb_dequeue(&tx_queue)) != NULL )
+    {
+        pending_idx = *((u16 *)skb->data);
+        netif       = pending_tx_info[pending_idx].netif;
+        memcpy(&txreq, &pending_tx_info[pending_idx].req, sizeof(txreq));
+
+        /* Check the remap error code. */
+        if ( unlikely(mcl[0].args[5] != 0) )
+        {
+            DPRINTK("Bad page frame\n");
+            make_tx_response(netif, txreq.id, NETIF_RSP_ERROR);
+            netif_put(netif);
+            kfree_skb(skb);
+            mcl++;
+            pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx;
+            continue;
+        }
+
+        phys_to_machine_mapping[__pa(MMAP_VADDR(pending_idx)) >> PAGE_SHIFT] =
+            FOREIGN_FRAME(txreq.addr >> PAGE_SHIFT);
+
+        data_len = (txreq.size > PKT_PROT_LEN) ? PKT_PROT_LEN : txreq.size;
+
+        __skb_put(skb, data_len);
+        memcpy(skb->data, 
+               (void *)(MMAP_VADDR(pending_idx)|(txreq.addr&~PAGE_MASK)),
+               data_len);
+
+        if ( data_len < txreq.size )
+        {
+            /* Append the packet payload as a fragment. */
+            skb_shinfo(skb)->frags[0].page        = 
+                virt_to_page(MMAP_VADDR(pending_idx));
+            skb_shinfo(skb)->frags[0].size        = txreq.size - data_len;
+            skb_shinfo(skb)->frags[0].page_offset = 
+                (txreq.addr + data_len) & ~PAGE_MASK;
+            skb_shinfo(skb)->nr_frags = 1;
+        }
+        else
+        {
+            /* Schedule a response immediately. */
+            netif_idx_release(pending_idx);
+        }
+
+        skb->data_len  = txreq.size - data_len;
+        skb->len      += skb->data_len;
+
+        skb->dev      = netif->dev;
+        skb->protocol = eth_type_trans(skb, skb->dev);
+
+        netif->stats.rx_bytes += txreq.size;
+        netif->stats.rx_packets++;
+
+        netif_rx(skb);
+        netif->dev->last_rx = jiffies;
+
+        mcl++;
+    }
+}
+
+static void netif_idx_release(u16 pending_idx)
+{
+    static spinlock_t _lock = SPIN_LOCK_UNLOCKED;
+    unsigned long flags;
+
+    spin_lock_irqsave(&_lock, flags);
+    dealloc_ring[MASK_PEND_IDX(dealloc_prod++)] = pending_idx;
+    spin_unlock_irqrestore(&_lock, flags);
+
+    tasklet_schedule(&net_tx_tasklet);
+}
+
+static void netif_page_release(struct page *page)
+{
+    u16 pending_idx = page - virt_to_page(mmap_vstart);
+
+    /* Ready for next use. */
+    set_page_count(page, 1);
+
+    netif_idx_release(pending_idx);
+}
+
+irqreturn_t netif_be_int(int irq, void *dev_id, struct pt_regs *regs)
+{
+    netif_t *netif = dev_id;
+    if ( tx_work_exists(netif) )
+    {
+        add_to_net_schedule_list_tail(netif);
+        maybe_schedule_tx_action();
+    }
+    return IRQ_HANDLED;
+}
+
+static void make_tx_response(netif_t *netif, 
+                             u16      id,
+                             s8       st)
+{
+    NETIF_RING_IDX i = netif->tx_resp_prod;
+    netif_tx_response_t *resp;
+
+    resp = &netif->tx->ring[MASK_NETIF_TX_IDX(i)].resp;
+    resp->id     = id;
+    resp->status = st;
+    wmb();
+    netif->tx->resp_prod = netif->tx_resp_prod = ++i;
+
+    mb(); /* Update producer before checking event threshold. */
+    if ( i == netif->tx->event )
+        notify_via_evtchn(netif->evtchn);
+}
+
+static int make_rx_response(netif_t *netif, 
+                            u16      id, 
+                            s8       st,
+                            memory_t addr,
+                            u16      size)
+{
+    NETIF_RING_IDX i = netif->rx_resp_prod;
+    netif_rx_response_t *resp;
+
+    resp = &netif->rx->ring[MASK_NETIF_RX_IDX(i)].resp;
+    resp->addr   = addr;
+    resp->id     = id;
+    resp->status = (s16)size;
+    if ( st < 0 )
+        resp->status = (s16)st;
+    wmb();
+    netif->rx->resp_prod = netif->rx_resp_prod = ++i;
+
+    mb(); /* Update producer before checking event threshold. */
+    return (i == netif->rx->event);
+}
+
+static irqreturn_t netif_be_dbg(int irq, void *dev_id, struct pt_regs *regs)
+{
+    struct list_head *ent;
+    netif_t *netif;
+    int i = 0;
+
+    printk(KERN_ALERT "netif_schedule_list:\n");
+    spin_lock_irq(&net_schedule_list_lock);
+
+    list_for_each ( ent, &net_schedule_list )
+    {
+        netif = list_entry(ent, netif_t, list);
+        printk(KERN_ALERT " %d: private(rx_req_cons=%08x rx_resp_prod=%08x\n",
+               i, netif->rx_req_cons, netif->rx_resp_prod);               
+        printk(KERN_ALERT "   tx_req_cons=%08x tx_resp_prod=%08x)\n",
+               netif->tx_req_cons, netif->tx_resp_prod);
+        printk(KERN_ALERT "   shared(rx_req_prod=%08x rx_resp_prod=%08x\n",
+               netif->rx->req_prod, netif->rx->resp_prod);
+        printk(KERN_ALERT "   rx_event=%08x tx_req_prod=%08x\n",
+               netif->rx->event, netif->tx->req_prod);
+        printk(KERN_ALERT "   tx_resp_prod=%08x, tx_event=%08x)\n",
+               netif->tx->resp_prod, netif->tx->event);
+        i++;
+    }
+
+    spin_unlock_irq(&net_schedule_list_lock);
+    printk(KERN_ALERT " ** End of netif_schedule_list **\n");
+
+    return IRQ_HANDLED;
+}
+
+static int __init netback_init(void)
+{
+    int i;
+    struct page *page;
+
+    if ( !(xen_start_info.flags & SIF_NET_BE_DOMAIN) &&
+         !(xen_start_info.flags & SIF_INITDOMAIN) )
+        return 0;
+
+    printk("Initialising Xen netif backend\n");
+
+    /* We can increase reservation by this much in net_rx_action(). */
+    balloon_update_driver_allowance(NETIF_RX_RING_SIZE);
+
+    skb_queue_head_init(&rx_queue);
+    skb_queue_head_init(&tx_queue);
+
+    init_timer(&net_timer);
+    net_timer.data = 0;
+    net_timer.function = net_alarm;
+    
+    netif_interface_init();
+
+    if ( (mmap_vstart = allocate_empty_lowmem_region(MAX_PENDING_REQS)) == 0 )
+        BUG();
+
+    for ( i = 0; i < MAX_PENDING_REQS; i++ )
+    {
+        page = virt_to_page(MMAP_VADDR(i));
+        set_page_count(page, 1);
+        SetPageForeign(page, netif_page_release);
+    }
+
+    pending_cons = 0;
+    pending_prod = MAX_PENDING_REQS;
+    for ( i = 0; i < MAX_PENDING_REQS; i++ )
+        pending_ring[i] = i;
+
+    spin_lock_init(&net_schedule_list_lock);
+    INIT_LIST_HEAD(&net_schedule_list);
+
+    netif_ctrlif_init();
+
+    (void)request_irq(bind_virq_to_irq(VIRQ_DEBUG),
+                      netif_be_dbg, SA_SHIRQ, 
+                      "net-be-dbg", &netif_be_dbg);
+
+    return 0;
+}
+
+static void netback_cleanup(void)
+{
+    BUG();
+}
+
+module_init(netback_init);
+module_exit(netback_cleanup);
diff --git a/drivers/xen/netfront/Kconfig b/drivers/xen/netfront/Kconfig
new file mode 100644 (file)
index 0000000..334e6c3
--- /dev/null
@@ -0,0 +1,6 @@
+
+config XENNET
+       tristate "Xen network driver"
+       depends on NETDEVICES && ARCH_XEN
+       help
+         Network driver for Xen
diff --git a/drivers/xen/netfront/Makefile b/drivers/xen/netfront/Makefile
new file mode 100644 (file)
index 0000000..7eb07a2
--- /dev/null
@@ -0,0 +1,2 @@
+
+obj-y  := netfront.o
diff --git a/drivers/xen/netfront/netfront.c b/drivers/xen/netfront/netfront.c
new file mode 100644 (file)
index 0000000..f729295
--- /dev/null
@@ -0,0 +1,1300 @@
+/******************************************************************************
+ * Virtual network driver for conversing with remote driver backends.
+ * 
+ * Copyright (c) 2002-2004, K A Fraser
+ * 
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <net/sock.h>
+#include <net/pkt_sched.h>
+#include <net/arp.h>
+#include <net/route.h>
+#include <asm/io.h>
+#include <asm-xen/evtchn.h>
+#include <asm-xen/ctrl_if.h>
+#include <asm-xen/xen-public/io/netif.h>
+#include <asm-xen/balloon.h>
+#include <asm/page.h>
+
+#ifndef __GFP_NOWARN
+#define __GFP_NOWARN 0
+#endif
+#define alloc_xen_skb(_l) __dev_alloc_skb((_l), GFP_ATOMIC|__GFP_NOWARN)
+
+#define init_skb_shinfo(_skb)                         \
+    do {                                              \
+        atomic_set(&(skb_shinfo(_skb)->dataref), 1);  \
+        skb_shinfo(_skb)->nr_frags = 0;               \
+        skb_shinfo(_skb)->frag_list = NULL;           \
+    } while (0)
+
+/* Allow headroom on each rx pkt for Ethernet header, alignment padding, ... */
+#define RX_HEADROOM 200
+
+/*
+ * If the backend driver is pipelining transmit requests then we can be very
+ * aggressive in avoiding new-packet notifications -- only need to send a
+ * notification if there are no outstanding unreceived responses.
+ * If the backend may be buffering our transmit buffers for any reason then we
+ * are rather more conservative.
+ */
+#ifdef CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER
+#define TX_TEST_IDX resp_prod /* aggressive: any outstanding responses? */
+#else
+#define TX_TEST_IDX req_cons  /* conservative: not seen all our requests? */
+#endif
+
+static void network_tx_buf_gc(struct net_device *dev);
+static void network_alloc_rx_buffers(struct net_device *dev);
+
+static unsigned long rx_pfn_array[NETIF_RX_RING_SIZE];
+static multicall_entry_t rx_mcl[NETIF_RX_RING_SIZE+1];
+static mmu_update_t rx_mmu[NETIF_RX_RING_SIZE];
+
+static struct list_head dev_list;
+
+struct net_private
+{
+    struct list_head list;
+    struct net_device *dev;
+
+    struct net_device_stats stats;
+    NETIF_RING_IDX rx_resp_cons, tx_resp_cons;
+    unsigned int tx_full;
+    
+    netif_tx_interface_t *tx;
+    netif_rx_interface_t *rx;
+
+    spinlock_t   tx_lock;
+    spinlock_t   rx_lock;
+
+    unsigned int handle;
+    unsigned int evtchn;
+    unsigned int irq;
+
+    /* What is the status of our connection to the remote backend? */
+#define BEST_CLOSED       0
+#define BEST_DISCONNECTED 1
+#define BEST_CONNECTED    2
+    unsigned int backend_state;
+
+    /* Is this interface open or closed (down or up)? */
+#define UST_CLOSED        0
+#define UST_OPEN          1
+    unsigned int user_state;
+
+    /* Receive-ring batched refills. */
+#define RX_MIN_TARGET 8
+#define RX_MAX_TARGET NETIF_RX_RING_SIZE
+    int rx_target;
+    struct sk_buff_head rx_batch;
+
+    /*
+     * {tx,rx}_skbs store outstanding skbuffs. The first entry in each
+     * array is an index into a chain of free entries.
+     */
+    struct sk_buff *tx_skbs[NETIF_TX_RING_SIZE+1];
+    struct sk_buff *rx_skbs[NETIF_RX_RING_SIZE+1];
+};
+
+/* Access macros for acquiring freeing slots in {tx,rx}_skbs[]. */
+#define ADD_ID_TO_FREELIST(_list, _id)             \
+    (_list)[(_id)] = (_list)[0];                   \
+    (_list)[0]     = (void *)(unsigned long)(_id);
+#define GET_ID_FROM_FREELIST(_list)                \
+ ({ unsigned long _id = (unsigned long)(_list)[0]; \
+    (_list)[0]  = (_list)[_id];                    \
+    (unsigned short)_id; })
+
+static char *status_name[] = {
+    [NETIF_INTERFACE_STATUS_CLOSED]       = "closed",
+    [NETIF_INTERFACE_STATUS_DISCONNECTED] = "disconnected",
+    [NETIF_INTERFACE_STATUS_CONNECTED]    = "connected",
+    [NETIF_INTERFACE_STATUS_CHANGED]      = "changed",
+};
+
+static char *be_state_name[] = {
+    [BEST_CLOSED]       = "closed",
+    [BEST_DISCONNECTED] = "disconnected",
+    [BEST_CONNECTED]    = "connected",
+};
+
+#if DEBUG
+#define DPRINTK(fmt, args...) \
+    printk(KERN_ALERT "xen_net (%s:%d) " fmt, __FUNCTION__, __LINE__, ##args)
+#else
+#define DPRINTK(fmt, args...) ((void)0)
+#endif
+#define IPRINTK(fmt, args...) \
+    printk(KERN_INFO "xen_net: " fmt, ##args)
+#define WPRINTK(fmt, args...) \
+    printk(KERN_WARNING "xen_net: " fmt, ##args)
+
+static struct net_device *find_dev_by_handle(unsigned int handle)
+{
+    struct list_head *ent;
+    struct net_private *np;
+    list_for_each (ent, &dev_list) {
+        np = list_entry(ent, struct net_private, list);
+        if (np->handle == handle)
+            return np->dev;
+    }
+    return NULL;
+}
+
+/** Network interface info. */
+struct netif_ctrl {
+    /** Number of interfaces. */
+    int interface_n;
+    /** Number of connected interfaces. */
+    int connected_n;
+    /** Error code. */
+    int err;
+    int up;
+};
+
+static struct netif_ctrl netctrl;
+
+static void netctrl_init(void)
+{
+    memset(&netctrl, 0, sizeof(netctrl));
+    netctrl.up = NETIF_DRIVER_STATUS_DOWN;
+}
+
+/** Get or set a network interface error.
+ */
+static int netctrl_err(int err)
+{
+    if ((err < 0) && !netctrl.err)
+        netctrl.err = err;
+    return netctrl.err;
+}
+
+/** Test if all network interfaces are connected.
+ *
+ * @return 1 if all connected, 0 if not, negative error code otherwise
+ */
+static int netctrl_connected(void)
+{
+    int ok;
+
+    if (netctrl.err)
+        ok = netctrl.err;
+    else if (netctrl.up == NETIF_DRIVER_STATUS_UP)
+        ok = (netctrl.connected_n == netctrl.interface_n);
+    else
+        ok = 0;
+
+    return ok;
+}
+
+/** Count the connected network interfaces.
+ *
+ * @return connected count
+ */
+static int netctrl_connected_count(void)
+{
+    
+    struct list_head *ent;
+    struct net_private *np;
+    unsigned int connected;
+
+    connected = 0;
+    
+    list_for_each(ent, &dev_list) {
+        np = list_entry(ent, struct net_private, list);
+        if (np->backend_state == BEST_CONNECTED)
+            connected++;
+    }
+
+    netctrl.connected_n = connected;
+    DPRINTK("> connected_n=%d interface_n=%d\n",
+            netctrl.connected_n, netctrl.interface_n);
+    return connected;
+}
+
+/** Send a packet on a net device to encourage switches to learn the
+ * MAC. We send a fake ARP request.
+ *
+ * @param dev device
+ * @return 0 on success, error code otherwise
+ */
+static int send_fake_arp(struct net_device *dev)
+{
+    struct sk_buff *skb;
+    u32             src_ip, dst_ip;
+
+    dst_ip = INADDR_BROADCAST;
+    src_ip = inet_select_addr(dev, dst_ip, RT_SCOPE_LINK);
+
+    /* No IP? Then nothing to do. */
+    if (src_ip == 0)
+        return 0;
+
+    skb = arp_create(ARPOP_REPLY, ETH_P_ARP,
+                     dst_ip, dev, src_ip,
+                     /*dst_hw*/ NULL, /*src_hw*/ NULL, 
+                     /*target_hw*/ dev->dev_addr);
+    if (skb == NULL)
+        return -ENOMEM;
+
+    return dev_queue_xmit(skb);
+}
+
+static int network_open(struct net_device *dev)
+{
+    struct net_private *np = netdev_priv(dev);
+
+    memset(&np->stats, 0, sizeof(np->stats));
+
+    np->user_state = UST_OPEN;
+
+    network_alloc_rx_buffers(dev);
+    np->rx->event = np->rx_resp_cons + 1;
+
+    netif_start_queue(dev);
+
+    return 0;
+}
+
+static void network_tx_buf_gc(struct net_device *dev)
+{
+    NETIF_RING_IDX i, prod;
+    unsigned short id;
+    struct net_private *np = netdev_priv(dev);
+    struct sk_buff *skb;
+
+    if (np->backend_state != BEST_CONNECTED)
+        return;
+
+    do {
+        prod = np->tx->resp_prod;
+        rmb(); /* Ensure we see responses up to 'rp'. */
+
+        for (i = np->tx_resp_cons; i != prod; i++) {
+            id  = np->tx->ring[MASK_NETIF_TX_IDX(i)].resp.id;
+            skb = np->tx_skbs[id];
+            ADD_ID_TO_FREELIST(np->tx_skbs, id);
+            dev_kfree_skb_irq(skb);
+        }
+        
+        np->tx_resp_cons = prod;
+        
+        /*
+         * Set a new event, then check for race with update of tx_cons. Note
+         * that it is essential to schedule a callback, no matter how few
+         * buffers are pending. Even if there is space in the transmit ring,
+         * higher layers may be blocked because too much data is outstanding:
+         * in such cases notification from Xen is likely to be the only kick
+         * that we'll get.
+         */
+        np->tx->event = 
+            prod + ((np->tx->req_prod - prod) >> 1) + 1;
+        mb();
+    } while (prod != np->tx->resp_prod);
+
+    if (np->tx_full && ((np->tx->req_prod - prod) < NETIF_TX_RING_SIZE)) {
+        np->tx_full = 0;
+        if (np->user_state == UST_OPEN)
+            netif_wake_queue(dev);
+    }
+}
+
+
+static void network_alloc_rx_buffers(struct net_device *dev)
+{
+    unsigned short id;
+    struct net_private *np = netdev_priv(dev);
+    struct sk_buff *skb;
+    int i, batch_target;
+    NETIF_RING_IDX req_prod = np->rx->req_prod;
+
+    if (unlikely(np->backend_state != BEST_CONNECTED))
+        return;
+
+    /*
+     * Allocate skbuffs greedily, even though we batch updates to the
+     * receive ring. This creates a less bursty demand on the memory allocator,
+     * so should reduce the chance of failed allocation requests both for
+     * ourself and for other kernel subsystems.
+     */
+    batch_target = np->rx_target - (req_prod - np->rx_resp_cons);
+    for (i = skb_queue_len(&np->rx_batch); i < batch_target; i++) {
+        if (unlikely((skb = alloc_xen_skb(dev->mtu + RX_HEADROOM)) == NULL))
+            break;
+        __skb_queue_tail(&np->rx_batch, skb);
+    }
+
+    /* Is the batch large enough to be worthwhile? */
+    if (i < (np->rx_target/2))
+        return;
+
+    for (i = 0; ; i++) {
+        if ((skb = __skb_dequeue(&np->rx_batch)) == NULL)
+            break;
+
+        skb->dev = dev;
+
+        id = GET_ID_FROM_FREELIST(np->rx_skbs);
+
+        np->rx_skbs[id] = skb;
+        
+        np->rx->ring[MASK_NETIF_RX_IDX(req_prod + i)].req.id = id;
+        
+        rx_pfn_array[i] = virt_to_machine(skb->head) >> PAGE_SHIFT;
+
+       /* Remove this page from pseudo phys map before passing back to Xen. */
+       phys_to_machine_mapping[__pa(skb->head) >> PAGE_SHIFT] 
+           = INVALID_P2M_ENTRY;
+
+        rx_mcl[i].op = __HYPERVISOR_update_va_mapping;
+        rx_mcl[i].args[0] = (unsigned long)skb->head;
+        rx_mcl[i].args[1] = 0;
+        rx_mcl[i].args[2] = 0;
+    }
+
+    /* After all PTEs have been zapped we blow away stale TLB entries. */
+    rx_mcl[i-1].args[2] = UVMF_TLB_FLUSH|UVMF_ALL;
+
+    /* Give away a batch of pages. */
+    rx_mcl[i].op = __HYPERVISOR_dom_mem_op;
+    rx_mcl[i].args[0] = MEMOP_decrease_reservation;
+    rx_mcl[i].args[1] = (unsigned long)rx_pfn_array;
+    rx_mcl[i].args[2] = (unsigned long)i;
+    rx_mcl[i].args[3] = 0;
+    rx_mcl[i].args[4] = DOMID_SELF;
+
+    /* Tell the ballon driver what is going on. */
+    balloon_update_driver_allowance(i);
+
+    /* Zap PTEs and give away pages in one big multicall. */
+    (void)HYPERVISOR_multicall(rx_mcl, i+1);
+
+    /* Check return status of HYPERVISOR_dom_mem_op(). */
+    if (unlikely(rx_mcl[i].args[5] != i))
+        panic("Unable to reduce memory reservation\n");
+
+    /* Above is a suitable barrier to ensure backend will see requests. */
+    np->rx->req_prod = req_prod + i;
+
+    /* Adjust our floating fill target if we risked running out of buffers. */
+    if (((req_prod - np->rx->resp_prod) < (np->rx_target / 4)) &&
+         ((np->rx_target *= 2) > RX_MAX_TARGET))
+        np->rx_target = RX_MAX_TARGET;
+}
+
+
+static int network_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+    unsigned short id;
+    struct net_private *np = netdev_priv(dev);
+    netif_tx_request_t *tx;
+    NETIF_RING_IDX i;
+
+    if (unlikely(np->tx_full)) {
+        printk(KERN_ALERT "%s: full queue wasn't stopped!\n", dev->name);
+        netif_stop_queue(dev);
+        goto drop;
+    }
+
+    if (unlikely((((unsigned long)skb->data & ~PAGE_MASK) + skb->len) >=
+                  PAGE_SIZE)) {
+        struct sk_buff *nskb;
+        if (unlikely((nskb = alloc_xen_skb(skb->len)) == NULL))
+            goto drop;
+        skb_put(nskb, skb->len);
+        memcpy(nskb->data, skb->data, skb->len);
+        nskb->dev = skb->dev;
+        dev_kfree_skb(skb);
+        skb = nskb;
+    }
+    
+    spin_lock_irq(&np->tx_lock);
+
+    if (np->backend_state != BEST_CONNECTED) {
+        spin_unlock_irq(&np->tx_lock);
+        goto drop;
+    }
+
+    i = np->tx->req_prod;
+
+    id = GET_ID_FROM_FREELIST(np->tx_skbs);
+    np->tx_skbs[id] = skb;
+
+    tx = &np->tx->ring[MASK_NETIF_TX_IDX(i)].req;
+
+    tx->id   = id;
+    tx->addr = virt_to_machine(skb->data);
+    tx->size = skb->len;
+
+    wmb(); /* Ensure that backend will see the request. */
+    np->tx->req_prod = i + 1;
+
+    network_tx_buf_gc(dev);
+
+    if ((i - np->tx_resp_cons) == (NETIF_TX_RING_SIZE - 1)) {
+        np->tx_full = 1;
+        netif_stop_queue(dev);
+    }
+
+    spin_unlock_irq(&np->tx_lock);
+
+    np->stats.tx_bytes += skb->len;
+    np->stats.tx_packets++;
+
+    /* Only notify Xen if we really have to. */
+    mb();
+    if (np->tx->TX_TEST_IDX == i)
+        notify_via_evtchn(np->evtchn);
+
+    return 0;
+
+ drop:
+    np->stats.tx_dropped++;
+    dev_kfree_skb(skb);
+    return 0;
+}
+
+static irqreturn_t netif_int(int irq, void *dev_id, struct pt_regs *ptregs)
+{
+    struct net_device *dev = dev_id;
+    struct net_private *np = netdev_priv(dev);
+    unsigned long flags;
+
+    spin_lock_irqsave(&np->tx_lock, flags);
+    network_tx_buf_gc(dev);
+    spin_unlock_irqrestore(&np->tx_lock, flags);
+
+    if ((np->rx_resp_cons != np->rx->resp_prod) && (np->user_state == UST_OPEN))
+        netif_rx_schedule(dev);
+
+    return IRQ_HANDLED;
+}
+
+
+static int netif_poll(struct net_device *dev, int *pbudget)
+{
+    struct net_private *np = netdev_priv(dev);
+    struct sk_buff *skb, *nskb;
+    netif_rx_response_t *rx;
+    NETIF_RING_IDX i, rp;
+    mmu_update_t *mmu = rx_mmu;
+    multicall_entry_t *mcl = rx_mcl;
+    int work_done, budget, more_to_do = 1;
+    struct sk_buff_head rxq;
+    unsigned long flags;
+
+    spin_lock(&np->rx_lock);
+
+    if (np->backend_state != BEST_CONNECTED) {
+        spin_unlock(&np->rx_lock);
+        return 0;
+    }
+
+    skb_queue_head_init(&rxq);
+
+    if ((budget = *pbudget) > dev->quota)
+        budget = dev->quota;
+
+    rp = np->rx->resp_prod;
+    rmb(); /* Ensure we see queued responses up to 'rp'. */
+
+    for (i = np->rx_resp_cons, work_done = 0; 
+                   (i != rp) && (work_done < budget);
+                   i++, work_done++) {
+        rx = &np->rx->ring[MASK_NETIF_RX_IDX(i)].resp;
+
+        /*
+         * An error here is very odd. Usually indicates a backend bug,
+         * low-memory condition, or that we didn't have reservation headroom.
+         */
+        if (unlikely(rx->status <= 0)) {
+            if (net_ratelimit())
+                printk(KERN_WARNING "Bad rx buffer (memory squeeze?).\n");
+            np->rx->ring[MASK_NETIF_RX_IDX(np->rx->req_prod)].req.id = rx->id;
+            wmb();
+            np->rx->req_prod++;
+            work_done--;
+            continue;
+        }
+
+        skb = np->rx_skbs[rx->id];
+        ADD_ID_TO_FREELIST(np->rx_skbs, rx->id);
+
+        /* NB. We handle skb overflow later. */
+        skb->data = skb->head + (rx->addr & ~PAGE_MASK);
+        skb->len  = rx->status;
+        skb->tail = skb->data + skb->len;
+
+        np->stats.rx_packets++;
+        np->stats.rx_bytes += rx->status;
+
+        /* Remap the page. */
+        mmu->ptr  = (rx->addr & PAGE_MASK) | MMU_MACHPHYS_UPDATE;
+        mmu->val  = __pa(skb->head) >> PAGE_SHIFT;
+        mmu++;
+        mcl->op = __HYPERVISOR_update_va_mapping;
+        mcl->args[0] = (unsigned long)skb->head;
+        mcl->args[1] = (rx->addr & PAGE_MASK) | __PAGE_KERNEL;
+        mcl->args[2] = 0;
+        mcl++;
+
+        phys_to_machine_mapping[__pa(skb->head) >> PAGE_SHIFT] = 
+            rx->addr >> PAGE_SHIFT;
+
+        __skb_queue_tail(&rxq, skb);
+    }
+
+    /* Some pages are no longer absent... */
+    balloon_update_driver_allowance(-work_done);
+
+    /* Do all the remapping work, and M->P updates, in one big hypercall. */
+    if (likely((mcl - rx_mcl) != 0)) {
+        mcl->op = __HYPERVISOR_mmu_update;
+        mcl->args[0] = (unsigned long)rx_mmu;
+        mcl->args[1] = mmu - rx_mmu;
+        mcl->args[2] = 0;
+        mcl->args[3] = DOMID_SELF;
+        mcl++;
+        (void)HYPERVISOR_multicall(rx_mcl, mcl - rx_mcl);
+    }
+
+    while ((skb = __skb_dequeue(&rxq)) != NULL) {
+        /*
+         * Enough room in skbuff for the data we were passed? Also, Linux 
+         * expects at least 16 bytes headroom in each receive buffer.
+         */
+        if (unlikely(skb->tail > skb->end) || 
+                       unlikely((skb->data - skb->head) < 16)) {
+            nskb = NULL;
+
+            /* Only copy the packet if it fits in the current MTU. */
+            if (skb->len <= (dev->mtu + ETH_HLEN)) {
+                if ((skb->tail > skb->end) && net_ratelimit())
+                    printk(KERN_INFO "Received packet needs %d bytes more "
+                           "headroom.\n", skb->tail - skb->end);
+
+                if ((nskb = alloc_xen_skb(skb->len + 2)) != NULL) {
+                    skb_reserve(nskb, 2);
+                    skb_put(nskb, skb->len);
+                    memcpy(nskb->data, skb->data, skb->len);
+                    nskb->dev = skb->dev;
+                }
+            }
+            else if (net_ratelimit())
+                printk(KERN_INFO "Received packet too big for MTU "
+                       "(%d > %d)\n", skb->len - ETH_HLEN, dev->mtu);
+
+            /* Reinitialise and then destroy the old skbuff. */
+            skb->len  = 0;
+            skb->tail = skb->data;
+            init_skb_shinfo(skb);
+            dev_kfree_skb(skb);
+
+            /* Switch old for new, if we copied the buffer. */
+            if ((skb = nskb) == NULL)
+                continue;
+        }
+        
+        /* Set the shared-info area, which is hidden behind the real data. */
+        init_skb_shinfo(skb);
+
+        /* Ethernet-specific work. Delayed to here as it peeks the header. */
+        skb->protocol = eth_type_trans(skb, dev);
+
+        /* Pass it up. */
+        netif_receive_skb(skb);
+        dev->last_rx = jiffies;
+    }
+
+    np->rx_resp_cons = i;
+
+    /* If we get a callback with very few responses, reduce fill target. */
+    /* NB. Note exponential increase, linear decrease. */
+    if (((np->rx->req_prod - np->rx->resp_prod) > ((3*np->rx_target) / 4)) &&
+         (--np->rx_target < RX_MIN_TARGET))
+        np->rx_target = RX_MIN_TARGET;
+
+    network_alloc_rx_buffers(dev);
+
+    *pbudget   -= work_done;
+    dev->quota -= work_done;
+
+    if (work_done < budget) {
+        local_irq_save(flags);
+
+        np->rx->event = i + 1;
+    
+        /* Deal with hypervisor racing our resetting of rx_event. */
+        mb();
+        if (np->rx->resp_prod == i) {
+            __netif_rx_complete(dev);
+            more_to_do = 0;
+        }
+
+        local_irq_restore(flags);
+    }
+
+    spin_unlock(&np->rx_lock);
+
+    return more_to_do;
+}
+
+
+static int network_close(struct net_device *dev)
+{
+    struct net_private *np = netdev_priv(dev);
+    np->user_state = UST_CLOSED;
+    netif_stop_queue(np->dev);
+    return 0;
+}
+
+
+static struct net_device_stats *network_get_stats(struct net_device *dev)
+{
+    struct net_private *np = netdev_priv(dev);
+    return &np->stats;
+}
+
+
+static void network_connect(struct net_device *dev,
+                            netif_fe_interface_status_t *status)
+{
+    struct net_private *np;
+    int i, requeue_idx;
+    netif_tx_request_t *tx;
+
+    np = netdev_priv(dev);
+    spin_lock_irq(&np->tx_lock);
+    spin_lock(&np->rx_lock);
+
+    /* Recovery procedure: */
+
+    /* Step 1: Reinitialise variables. */
+    np->rx_resp_cons = np->tx_resp_cons = np->tx_full = 0;
+    np->rx->event = np->tx->event = 1;
+
+    /* Step 2: Rebuild the RX and TX ring contents.
+     * NB. We could just free the queued TX packets now but we hope
+     * that sending them out might do some good.  We have to rebuild
+     * the RX ring because some of our pages are currently flipped out
+     * so we can't just free the RX skbs.
+     * NB2. Freelist index entries are always going to be less than
+     *  __PAGE_OFFSET, whereas pointers to skbs will always be equal or
+     * greater than __PAGE_OFFSET: we use this property to distinguish
+     * them.
+     */
+
+    /* Rebuild the TX buffer freelist and the TX ring itself.
+     * NB. This reorders packets.  We could keep more private state
+     * to avoid this but maybe it doesn't matter so much given the
+     * interface has been down.
+     */
+    for (requeue_idx = 0, i = 1; i <= NETIF_TX_RING_SIZE; i++) {
+            if ((unsigned long)np->tx_skbs[i] >= __PAGE_OFFSET) {
+                struct sk_buff *skb = np->tx_skbs[i];
+                
+                tx = &np->tx->ring[requeue_idx++].req;
+                
+                tx->id   = i;
+                tx->addr = virt_to_machine(skb->data);
+                tx->size = skb->len;
+                
+                np->stats.tx_bytes += skb->len;
+                np->stats.tx_packets++;
+            }
+    }
+    wmb();
+    np->tx->req_prod = requeue_idx;
+
+    /* Rebuild the RX buffer freelist and the RX ring itself. */
+    for (requeue_idx = 0, i = 1; i <= NETIF_RX_RING_SIZE; i++)
+        if ((unsigned long)np->rx_skbs[i] >= __PAGE_OFFSET)
+            np->rx->ring[requeue_idx++].req.id = i;
+    wmb();                
+    np->rx->req_prod = requeue_idx;
+
+    /* Step 3: All public and private state should now be sane.  Get
+     * ready to start sending and receiving packets and give the driver
+     * domain a kick because we've probably just requeued some
+     * packets.
+     */
+    np->backend_state = BEST_CONNECTED;
+    wmb();
+    notify_via_evtchn(status->evtchn);  
+    network_tx_buf_gc(dev);
+
+    if (np->user_state == UST_OPEN)
+        netif_start_queue(dev);
+
+    spin_unlock(&np->rx_lock);
+    spin_unlock_irq(&np->tx_lock);
+}
+
+static void vif_show(struct net_private *np)
+{
+#if DEBUG
+    if (np) {
+        IPRINTK("<vif handle=%u %s(%s) evtchn=%u irq=%u tx=%p rx=%p>\n",
+               np->handle,
+               be_state_name[np->backend_state],
+               np->user_state ? "open" : "closed",
+               np->evtchn,
+               np->irq,
+               np->tx,
+               np->rx);
+    } else {
+        IPRINTK("<vif NULL>\n");
+    }
+#endif
+}
+
+/* Send a connect message to xend to tell it to bring up the interface. */
+static void send_interface_connect(struct net_private *np)
+{
+    ctrl_msg_t cmsg = {
+        .type    = CMSG_NETIF_FE,
+        .subtype = CMSG_NETIF_FE_INTERFACE_CONNECT,
+        .length  = sizeof(netif_fe_interface_connect_t),
+    };
+    netif_fe_interface_connect_t *msg = (void*)cmsg.msg;
+
+    msg->handle = np->handle;
+    msg->tx_shmem_frame = (virt_to_machine(np->tx) >> PAGE_SHIFT);
+    msg->rx_shmem_frame = (virt_to_machine(np->rx) >> PAGE_SHIFT);
+        
+    ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
+}
+
+/* Send a driver status notification to the domain controller. */
+static int send_driver_status(int ok)
+{
+    int err = 0;
+    ctrl_msg_t cmsg = {
+        .type    = CMSG_NETIF_FE,
+        .subtype = CMSG_NETIF_FE_DRIVER_STATUS,
+        .length  = sizeof(netif_fe_driver_status_t),
+    };
+    netif_fe_driver_status_t *msg = (void*)cmsg.msg;
+
+    msg->status = (ok ? NETIF_DRIVER_STATUS_UP : NETIF_DRIVER_STATUS_DOWN);
+    err = ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
+    return err;
+}
+
+/* Stop network device and free tx/rx queues and irq.
+ */
+static void vif_release(struct net_private *np)
+{
+    /* Stop old i/f to prevent errors whilst we rebuild the state. */
+    spin_lock_irq(&np->tx_lock);
+    spin_lock(&np->rx_lock);
+    netif_stop_queue(np->dev);
+    /* np->backend_state = BEST_DISCONNECTED; */
+    spin_unlock(&np->rx_lock);
+    spin_unlock_irq(&np->tx_lock);
+    
+    /* Free resources. */
+    if(np->tx != NULL){
+        free_irq(np->irq, np->dev);
+        unbind_evtchn_from_irq(np->evtchn);
+        free_page((unsigned long)np->tx);
+        free_page((unsigned long)np->rx);
+        np->irq = 0;
+        np->evtchn = 0;
+        np->tx = NULL;
+        np->rx = NULL;
+    }
+}
+
+/* Release vif resources and close it down completely.
+ */
+static void vif_close(struct net_private *np)
+{
+    WPRINTK("Unexpected netif-CLOSED message in state %s\n",
+            be_state_name[np->backend_state]);
+    vif_release(np);
+    np->backend_state = BEST_CLOSED;
+    /* todo: take dev down and free. */
+    vif_show(np);
+}
+
+/* Move the vif into disconnected state.
+ * Allocates tx/rx pages.
+ * Sends connect message to xend.
+ */
+static void vif_disconnect(struct net_private *np)
+{
+    if(np->tx) free_page((unsigned long)np->tx);
+    if(np->rx) free_page((unsigned long)np->rx);
+    // Before this np->tx and np->rx had better be null.
+    np->tx = (netif_tx_interface_t *)__get_free_page(GFP_KERNEL);
+    np->rx = (netif_rx_interface_t *)__get_free_page(GFP_KERNEL);
+    memset(np->tx, 0, PAGE_SIZE);
+    memset(np->rx, 0, PAGE_SIZE);
+    np->backend_state = BEST_DISCONNECTED;
+    send_interface_connect(np);
+    vif_show(np);
+}
+
+/* Begin interface recovery.
+ *
+ * NB. Whilst we're recovering, we turn the carrier state off.  We
+ * take measures to ensure that this device isn't used for
+ * anything.  We also stop the queue for this device.  Various
+ * different approaches (e.g. continuing to buffer packets) have
+ * been tested but don't appear to improve the overall impact on
+ * TCP connections.
+ *
+ * TODO: (MAW) Change the Xend<->Guest protocol so that a recovery
+ * is initiated by a special "RESET" message - disconnect could
+ * just mean we're not allowed to use this interface any more.
+ */
+static void vif_reset(struct net_private *np)
+{
+    IPRINTK("Attempting to reconnect network interface: handle=%u\n",
+            np->handle);    
+    vif_release(np);
+    vif_disconnect(np);
+    vif_show(np);
+}
+
+/* Move the vif into connected state.
+ * Sets the mac and event channel from the message.
+ * Binds the irq to the event channel.
+ */
+static void 
+vif_connect(struct net_private *np, netif_fe_interface_status_t *status)
+{
+    struct net_device *dev = np->dev;
+    memcpy(dev->dev_addr, status->mac, ETH_ALEN);
+    network_connect(dev, status);
+    np->evtchn = status->evtchn;
+    np->irq = bind_evtchn_to_irq(np->evtchn);
+    (void)request_irq(np->irq, netif_int, SA_SAMPLE_RANDOM, dev->name, dev);
+    netctrl_connected_count();
+    (void)send_fake_arp(dev);
+    vif_show(np);
+}
+
+
+/** Create a network device.
+ * @param handle device handle
+ * @param val return parameter for created device
+ * @return 0 on success, error code otherwise
+ */
+static int create_netdev(int handle, struct net_device **val)
+{
+    int i, err = 0;
+    struct net_device *dev = NULL;
+    struct net_private *np = NULL;
+
+    if ((dev = alloc_etherdev(sizeof(struct net_private))) == NULL) {
+        printk(KERN_WARNING "%s> alloc_etherdev failed.\n", __FUNCTION__);
+        err = -ENOMEM;
+        goto exit;
+    }
+
+    np                = netdev_priv(dev);
+    np->backend_state = BEST_CLOSED;
+    np->user_state    = UST_CLOSED;
+    np->handle        = handle;
+    
+    spin_lock_init(&np->tx_lock);
+    spin_lock_init(&np->rx_lock);
+
+    skb_queue_head_init(&np->rx_batch);
+    np->rx_target = RX_MIN_TARGET;
+
+    /* Initialise {tx,rx}_skbs to be a free chain containing every entry. */
+    for (i = 0; i <= NETIF_TX_RING_SIZE; i++)
+        np->tx_skbs[i] = (void *)(i+1);
+    for (i = 0; i <= NETIF_RX_RING_SIZE; i++)
+        np->rx_skbs[i] = (void *)(i+1);
+
+    dev->open            = network_open;
+    dev->hard_start_xmit = network_start_xmit;
+    dev->stop            = network_close;
+    dev->get_stats       = network_get_stats;
+    dev->poll            = netif_poll;
+    dev->weight          = 64;
+    
+    if ((err = register_netdev(dev)) != 0) {
+        printk(KERN_WARNING "%s> register_netdev err=%d\n", __FUNCTION__, err);
+        goto exit;
+    }
+    np->dev = dev;
+    list_add(&np->list, &dev_list);
+
+  exit:
+    if ((err != 0) && (dev != NULL ))
+        kfree(dev);
+    else if (val != NULL)
+        *val = dev;
+    return err;
+}
+
+/* Get the target interface for a status message.
+ * Creates the interface when it makes sense.
+ * The returned interface may be null when there is no error.
+ *
+ * @param status status message
+ * @param np return parameter for interface state
+ * @return 0 on success, error code otherwise
+ */
+static int 
+target_vif(netif_fe_interface_status_t *status, struct net_private **np)
+{
+    int err = 0;
+    struct net_device *dev;
+
+    DPRINTK("> handle=%d\n", status->handle);
+    if (status->handle < 0) {
+        err = -EINVAL;
+        goto exit;
+    }
+
+    if ((dev = find_dev_by_handle(status->handle)) != NULL)
+        goto exit;
+
+    if (status->status == NETIF_INTERFACE_STATUS_CLOSED)
+        goto exit;
+    if (status->status == NETIF_INTERFACE_STATUS_CHANGED)
+        goto exit;
+
+    /* It's a new interface in a good state - create it. */
+    DPRINTK("> create device...\n");
+    if ((err = create_netdev(status->handle, &dev)) != 0)
+        goto exit;
+
+    netctrl.interface_n++;
+
+  exit:
+    if (np != NULL)
+        *np = ((dev && !err) ? netdev_priv(dev) : NULL);
+    DPRINTK("< err=%d\n", err);
+    return err;
+}
+
+/* Handle an interface status message. */
+static void netif_interface_status(netif_fe_interface_status_t *status)
+{
+    int err = 0;
+    struct net_private *np = NULL;
+    
+    DPRINTK("> status=%s handle=%d\n",
+            status_name[status->status], status->handle);
+
+    if ((err = target_vif(status, &np)) != 0) {
+        WPRINTK("Invalid netif: handle=%u\n", status->handle);
+        return;
+    }
+
+    if (np == NULL) {
+        DPRINTK("> no vif\n");
+        return;
+    }
+
+    switch (status->status) {
+    case NETIF_INTERFACE_STATUS_CLOSED:
+        switch (np->backend_state) {
+        case BEST_CLOSED:
+        case BEST_DISCONNECTED:
+        case BEST_CONNECTED:
+            vif_close(np);
+            break;
+        }
+        break;
+
+    case NETIF_INTERFACE_STATUS_DISCONNECTED:
+        switch (np->backend_state) {
+        case BEST_CLOSED:
+            vif_disconnect(np);
+            break;
+        case BEST_DISCONNECTED:
+        case BEST_CONNECTED:
+            vif_reset(np);
+            break;
+        }
+        break;
+
+    case NETIF_INTERFACE_STATUS_CONNECTED:
+        switch (np->backend_state) {
+        case BEST_CLOSED:
+            WPRINTK("Unexpected netif status %s in state %s\n",
+                    status_name[status->status],
+                    be_state_name[np->backend_state]);
+            vif_disconnect(np);
+            vif_connect(np, status);
+            break;
+        case BEST_DISCONNECTED:
+            vif_connect(np, status);
+            break;
+        }
+        break;
+
+    case NETIF_INTERFACE_STATUS_CHANGED:
+        /*
+         * The domain controller is notifying us that a device has been
+         * added or removed.
+         */
+        break;
+
+    default:
+        WPRINTK("Invalid netif status code %d\n", status->status);
+        break;
+    }
+
+    vif_show(np);
+}
+
+/*
+ * Initialize the network control interface. 
+ */
+static void netif_driver_status(netif_fe_driver_status_t *status)
+{
+    netctrl.up = status->status;
+    netctrl_connected_count();
+}
+
+/* Receive handler for control messages. */
+static void netif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id)
+{
+
+    switch (msg->subtype) {
+    case CMSG_NETIF_FE_INTERFACE_STATUS:
+        netif_interface_status((netif_fe_interface_status_t *) &msg->msg[0]);
+        break;
+
+    case CMSG_NETIF_FE_DRIVER_STATUS:
+        netif_driver_status((netif_fe_driver_status_t *) &msg->msg[0]);
+        break;
+
+    default:
+        msg->length = 0;
+        break;
+    }
+
+    ctrl_if_send_response(msg);
+}
+
+
+#if 1
+/* Wait for all interfaces to be connected.
+ *
+ * This works OK, but we'd like to use the probing mode (see below).
+ */
+static int probe_interfaces(void)
+{
+    int err = 0, conn = 0;
+    int wait_i, wait_n = 100;
+
+    DPRINTK(">\n");
+
+    for (wait_i = 0; wait_i < wait_n; wait_i++) { 
+        DPRINTK("> wait_i=%d\n", wait_i);
+        conn = netctrl_connected();
+        if(conn) break;
+        DPRINTK("> schedule_timeout...\n");
+        set_current_state(TASK_INTERRUPTIBLE);
+        schedule_timeout(10);
+    }
+
+    DPRINTK("> wait finished...\n");
+    if (conn <= 0) {
+        err = netctrl_err(-ENETDOWN);
+        WPRINTK("Failed to connect all virtual interfaces: err=%d\n", err);
+    }
+
+    DPRINTK("< err=%d\n", err);
+
+    return err;
+}
+#else
+/* Probe for interfaces until no more are found.
+ *
+ * This is the mode we'd like to use, but at the moment it panics the kernel.
+*/
+static int probe_interfaces(void)
+{
+    int err = 0;
+    int wait_i, wait_n = 100;
+    ctrl_msg_t cmsg = {
+        .type    = CMSG_NETIF_FE,
+        .subtype = CMSG_NETIF_FE_INTERFACE_STATUS,
+        .length  = sizeof(netif_fe_interface_status_t),
+    };
+    netif_fe_interface_status_t msg = {};
+    ctrl_msg_t rmsg = {};
+    netif_fe_interface_status_t *reply = (void*)rmsg.msg;
+    int state = TASK_UNINTERRUPTIBLE;
+    u32 query = -1;
+
+    DPRINTK(">\n");
+
+    netctrl.interface_n = 0;
+    for (wait_i = 0; wait_i < wait_n; wait_i++) { 
+        DPRINTK("> wait_i=%d query=%d\n", wait_i, query);
+        msg.handle = query;
+        memcpy(cmsg.msg, &msg, sizeof(msg));
+        DPRINTK("> set_current_state...\n");
+        set_current_state(state);
+        DPRINTK("> rmsg=%p msg=%p, reply=%p\n", &rmsg, rmsg.msg, reply);
+        DPRINTK("> sending...\n");
+        err = ctrl_if_send_message_and_get_response(&cmsg, &rmsg, state);
+        DPRINTK("> err=%d\n", err);
+        if(err) goto exit;
+        DPRINTK("> rmsg=%p msg=%p, reply=%p\n", &rmsg, rmsg.msg, reply);
+        if((int)reply->handle < 0) {
+            // No more interfaces.
+            break;
+        }
+        query = -reply->handle - 2;
+        DPRINTK(">netif_interface_status ...\n");
+        netif_interface_status(reply);
+    }
+
+  exit:
+    if (err) {
+        err = netctrl_err(-ENETDOWN);
+        WPRINTK("Connecting virtual network interfaces failed: err=%d\n", err);
+    }
+
+    DPRINTK("< err=%d\n", err);
+    return err;
+}
+
+#endif
+
+/*
+ * We use this notifier to send out a fake ARP reply to reset switches and
+ * router ARP caches when an IP interface is brought up on a VIF.
+ */
+static int 
+inetdev_notify(struct notifier_block *this, unsigned long event, void *ptr)
+{
+    struct in_ifaddr  *ifa = (struct in_ifaddr *)ptr; 
+    struct net_device *dev = ifa->ifa_dev->dev;
+    struct list_head  *ent;
+    struct net_private *np;
+
+    if (event != NETDEV_UP)
+        goto out;
+
+    list_for_each (ent, &dev_list) {
+        np = list_entry(ent, struct net_private, list);
+        if (np->dev == dev)
+            (void)send_fake_arp(dev);
+    }
+        
+ out:
+    return NOTIFY_DONE;
+}
+
+static struct notifier_block notifier_inetdev = {
+    .notifier_call  = inetdev_notify,
+    .next           = NULL,
+    .priority       = 0
+};
+
+static int __init netif_init(void)
+{
+    int err = 0;
+
+    if (xen_start_info.flags & SIF_INITDOMAIN)
+        return 0;
+
+    IPRINTK("Initialising virtual ethernet driver.\n");
+    INIT_LIST_HEAD(&dev_list);
+    (void)register_inetaddr_notifier(&notifier_inetdev);
+    netctrl_init();
+    (void)ctrl_if_register_receiver(CMSG_NETIF_FE, netif_ctrlif_rx,
+                                    CALLBACK_IN_BLOCKING_CONTEXT);
+    send_driver_status(1);
+    err = probe_interfaces();
+    if (err)
+        ctrl_if_unregister_receiver(CMSG_NETIF_FE, netif_ctrlif_rx);
+
+    DPRINTK("< err=%d\n", err);
+    return err;
+}
+
+static void vif_suspend(struct net_private *np)
+{
+    /* Avoid having tx/rx stuff happen until we're ready. */
+    free_irq(np->irq, np->dev);
+    unbind_evtchn_from_irq(np->evtchn);
+}
+
+static void vif_resume(struct net_private *np)
+{
+    /*
+     * Connect regardless of whether IFF_UP flag set.
+     * Stop bad things from happening until we're back up.
+     */
+    np->backend_state = BEST_DISCONNECTED;
+    memset(np->tx, 0, PAGE_SIZE);
+    memset(np->rx, 0, PAGE_SIZE);
+    
+    send_interface_connect(np);
+}
+
+void netif_suspend(void)
+{
+    struct list_head *ent;
+    struct net_private *np;
+    
+    list_for_each (ent, &dev_list) {
+        np = list_entry(ent, struct net_private, list);
+        vif_suspend(np);
+    }
+}
+
+void netif_resume(void)
+{
+    struct list_head *ent;
+    struct net_private *np;
+
+    list_for_each (ent, &dev_list) {
+        np = list_entry(ent, struct net_private, list);
+        vif_resume(np);
+    }
+}
+
+
+module_init(netif_init);
+
diff --git a/drivers/xen/privcmd/Makefile b/drivers/xen/privcmd/Makefile
new file mode 100644 (file)
index 0000000..e218695
--- /dev/null
@@ -0,0 +1,2 @@
+
+obj-y  := privcmd.o
diff --git a/drivers/xen/privcmd/privcmd.c b/drivers/xen/privcmd/privcmd.c
new file mode 100644 (file)
index 0000000..0b78cc7
--- /dev/null
@@ -0,0 +1,232 @@
+/******************************************************************************
+ * privcmd.c
+ * 
+ * Interface to privileged domain-0 commands.
+ * 
+ * Copyright (c) 2002-2004, K A Fraser, B Dragovic
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/swap.h>
+#include <linux/smp_lock.h>
+#include <linux/highmem.h>
+#include <linux/pagemap.h>
+#include <linux/seq_file.h>
+
+#include <asm/pgalloc.h>
+#include <asm/pgtable.h>
+#include <asm/uaccess.h>
+#include <asm/tlb.h>
+#include <asm-xen/linux-public/privcmd.h>
+#include <asm-xen/xen-public/dom0_ops.h>
+#include <asm-xen/xen_proc.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+#define pud_t pgd_t
+#define pud_offset(d, va) d
+#endif
+
+static struct proc_dir_entry *privcmd_intf;
+
+static int privcmd_ioctl(struct inode *inode, struct file *file,
+                         unsigned int cmd, unsigned long data)
+{
+    int ret = -ENOSYS;
+
+    switch ( cmd )
+    {
+    case IOCTL_PRIVCMD_HYPERCALL:
+    {
+        privcmd_hypercall_t hypercall;
+  
+        if ( copy_from_user(&hypercall, (void *)data, sizeof(hypercall)) )
+            return -EFAULT;
+
+#if defined(__i386__)
+        __asm__ __volatile__ (
+            "pushl %%ebx; pushl %%ecx; pushl %%edx; pushl %%esi; pushl %%edi; "
+            "movl  4(%%eax),%%ebx ;"
+            "movl  8(%%eax),%%ecx ;"
+            "movl 12(%%eax),%%edx ;"
+            "movl 16(%%eax),%%esi ;"
+            "movl 20(%%eax),%%edi ;"
+            "movl   (%%eax),%%eax ;"
+            TRAP_INSTR "; "
+            "popl %%edi; popl %%esi; popl %%edx; popl %%ecx; popl %%ebx"
+            : "=a" (ret) : "0" (&hypercall) : "memory" );
+#elif defined (__x86_64__)
+       __asm__ __volatile__ (
+           "movq   %5,%%r10; movq %6,%%r8;" TRAP_INSTR
+           : "=a" (ret)
+           : "a" ((unsigned long)hypercall.op), 
+             "D" ((unsigned long)hypercall.arg[0]), 
+             "S" ((unsigned long)hypercall.arg[1]),
+             "d" ((unsigned long)hypercall.arg[2]), 
+             "g" ((unsigned long)hypercall.arg[3]),
+             "g" ((unsigned long)hypercall.arg[4])
+           : "r11","rcx","r8","r10","memory");
+#endif
+    }
+    break;
+
+    case IOCTL_PRIVCMD_INITDOMAIN_EVTCHN:
+    {
+        extern int initdom_ctrlif_domcontroller_port;
+        ret = initdom_ctrlif_domcontroller_port;
+    }
+    break;
+    
+#if defined(CONFIG_XEN_PRIVILEGED_GUEST)
+    case IOCTL_PRIVCMD_MMAP:
+    {
+#define PRIVCMD_MMAP_SZ 32
+        privcmd_mmap_t mmapcmd;
+        privcmd_mmap_entry_t msg[PRIVCMD_MMAP_SZ], *p;
+        int i, rc;
+
+        if ( copy_from_user(&mmapcmd, (void *)data, sizeof(mmapcmd)) )
+            return -EFAULT;
+
+        p = mmapcmd.entry;
+
+        for (i=0; i<mmapcmd.num; i+=PRIVCMD_MMAP_SZ, p+=PRIVCMD_MMAP_SZ)
+        {
+            int j, n = ((mmapcmd.num-i)>PRIVCMD_MMAP_SZ)?
+                PRIVCMD_MMAP_SZ:(mmapcmd.num-i);
+
+
+            if ( copy_from_user(&msg, p, n*sizeof(privcmd_mmap_entry_t)) )
+                return -EFAULT;
+     
+            for ( j = 0; j < n; j++ )
+            {
+                struct vm_area_struct *vma = 
+                    find_vma( current->mm, msg[j].va );
+
+                if ( !vma )
+                    return -EINVAL;
+
+                if ( msg[j].va > PAGE_OFFSET )
+                    return -EINVAL;
+
+                if ( (msg[j].va + (msg[j].npages<<PAGE_SHIFT)) > vma->vm_end )
+                    return -EINVAL;
+
+                if ( (rc = direct_remap_area_pages(vma->vm_mm, 
+                                                   msg[j].va&PAGE_MASK, 
+                                                   msg[j].mfn<<PAGE_SHIFT, 
+                                                   msg[j].npages<<PAGE_SHIFT, 
+                                                   vma->vm_page_prot,
+                                                   mmapcmd.dom)) < 0 )
+                    return rc;
+            }
+        }
+        ret = 0;
+    }
+    break;
+
+    case IOCTL_PRIVCMD_MMAPBATCH:
+    {
+        mmu_update_t u;
+        privcmd_mmapbatch_t m;
+        struct vm_area_struct *vma = NULL;
+        unsigned long *p, addr;
+        unsigned long mfn;
+        int i;
+
+        if ( copy_from_user(&m, (void *)data, sizeof(m)) )
+        { ret = -EFAULT; goto batch_err; }
+
+        vma = find_vma( current->mm, m.addr );
+
+        if ( !vma )
+        { ret = -EINVAL; goto batch_err; }
+
+        if ( m.addr > PAGE_OFFSET )
+        { ret = -EFAULT; goto batch_err; }
+
+        if ( (m.addr + (m.num<<PAGE_SHIFT)) > vma->vm_end )
+        { ret = -EFAULT; goto batch_err; }
+
+        p = m.arr;
+        addr = m.addr;
+        for ( i = 0; i < m.num; i++, addr += PAGE_SIZE, p++ )
+        {
+            if ( get_user(mfn, p) )
+                return -EFAULT;
+
+            u.val = (mfn << PAGE_SHIFT) | pgprot_val(vma->vm_page_prot);
+
+            __direct_remap_area_pages(vma->vm_mm,
+                                      addr, 
+                                      PAGE_SIZE, 
+                                      &u);
+
+            if ( unlikely(HYPERVISOR_mmu_update(&u, 1, NULL, m.dom) < 0) )
+                put_user(0xF0000000 | mfn, p);
+        }
+
+        ret = 0;
+        break;
+
+    batch_err:
+        printk("batch_err ret=%d vma=%p addr=%lx num=%d arr=%p %lx-%lx\n", 
+               ret, vma, m.addr, m.num, m.arr,
+               vma ? vma->vm_start : 0, vma ? vma->vm_end : 0);
+        break;
+    }
+    break;
+#endif
+
+    case IOCTL_PRIVCMD_GET_MACH2PHYS_START_MFN:
+    {
+        unsigned long m2pv = (unsigned long)machine_to_phys_mapping;
+        pgd_t *pgd = pgd_offset_k(m2pv);
+        pud_t *pud = pud_offset(pgd, m2pv);
+        pmd_t *pmd = pmd_offset(pud, m2pv);
+        unsigned long m2p_start_mfn = (*(unsigned long *)pmd) >> PAGE_SHIFT; 
+        ret = put_user(m2p_start_mfn, (unsigned long *)data) ? -EFAULT: 0;
+    }
+    break;
+
+    default:
+        ret = -EINVAL;
+        break;
+    }
+    return ret;
+}
+
+static int privcmd_mmap(struct file * file, struct vm_area_struct * vma)
+{
+    /* DONTCOPY is essential for Xen as copy_page_range is broken. */
+    vma->vm_flags |= VM_RESERVED | VM_IO | VM_DONTCOPY;
+
+    return 0;
+}
+
+static struct file_operations privcmd_file_ops = {
+    ioctl : privcmd_ioctl,
+    mmap:   privcmd_mmap
+};
+
+
+static int __init privcmd_init(void)
+{
+    if ( !(xen_start_info.flags & SIF_PRIVILEGED) )
+        return 0;
+
+    privcmd_intf = create_xen_proc_entry("privcmd", 0400);
+    if ( privcmd_intf != NULL )
+        privcmd_intf->proc_fops = &privcmd_file_ops;
+
+    return 0;
+}
+
+__initcall(privcmd_init);
diff --git a/include/asm-arm/arch-imx/imxfb.h b/include/asm-arm/arch-imx/imxfb.h
new file mode 100644 (file)
index 0000000..2346d45
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * This structure describes the machine which we are running on.
+ */
+struct imxfb_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           pcr;
+       u_int           pwmr;
+       u_int           lscr1;
+
+       u_char * fixed_screen_cpu;
+       dma_addr_t fixed_screen_dma;
+
+       void (*lcd_power)(int);
+       void (*backlight_power)(int);
+};
+void set_imx_fb_info(struct imxfb_mach_info *hard_imx_fb_info);
diff --git a/include/asm-arm/arch-omap/board-voiceblue.h b/include/asm-arm/arch-omap/board-voiceblue.h
new file mode 100644 (file)
index 0000000..33977b8
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2004 2N Telekomunikace, Ladislav Michl <michl@2n.cz>
+ *
+ * Hardware definitions for OMAP5910 based VoiceBlue board.
+ *
+ * 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
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_VOICEBLUE_H
+#define __ASM_ARCH_VOICEBLUE_H
+
+#if (EXTERNAL_MAX_NR_PORTS < 4)
+#undef EXTERNAL_MAX_NR_PORTS
+#define EXTERNAL_MAX_NR_PORTS  4
+#endif
+
+extern void voiceblue_wdt_enable(void);
+extern void voiceblue_wdt_disable(void);
+extern void voiceblue_wdt_ping(void);
+extern void voiceblue_reset(void);
+
+#endif /*  __ASM_ARCH_VOICEBLUE_H */
+
diff --git a/include/asm-arm/arch-s3c2410/otom-map.h b/include/asm-arm/arch-s3c2410/otom-map.h
new file mode 100644 (file)
index 0000000..e40c934
--- /dev/null
@@ -0,0 +1,30 @@
+/* linux/include/asm-arm/arch-s3c2410/otom-map.h
+ *
+ * (c) 2005 Guillaume GOURAT / NexVision
+ *          guillaume.gourat@nexvision.fr
+ *
+ * NexVision OTOM board memory map definitions
+ *
+ * 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
+ * published by the Free Software Foundation.
+*/
+
+/* needs arch/map.h including with this */
+
+/* ok, we've used up to 0x01300000, now we need to find space for the
+ * peripherals that live in the nGCS[x] areas, which are quite numerous
+ * in their space.
+ */
+
+#ifndef __ASM_ARCH_OTOMMAP_H
+#define __ASM_ARCH_OTOMMAP_H
+
+#define OTOM_PA_CS8900A_BASE       (S3C2410_CS3 + 0x01000000)  /* nGCS3 +0x01000000 */
+#define OTOM_VA_CS8900A_BASE       S3C2410_ADDR(0x04000000)            /* 0xF4000000 */
+
+/* physical offset addresses for the peripherals */
+
+#define OTOM_PA_FLASH0_BASE        (S3C2410_CS0)                               /* Bank 0 */
+
+#endif /* __ASM_ARCH_OTOMMAP_H */
diff --git a/include/asm-arm/mach/sharpsl_param.h b/include/asm-arm/mach/sharpsl_param.h
new file mode 100644 (file)
index 0000000..7a24ecf
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Hardware parameter area specific to Sharp SL series devices
+ *
+ * Copyright (c) 2005 Richard Purdie
+ *
+ * Based on Sharp's 2.4 kernel patches
+ *
+ * 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
+ * published by the Free Software Foundation.
+ *
+ */
+
+struct sharpsl_param_info {
+  unsigned int comadj_keyword;
+  unsigned int comadj;
+
+  unsigned int uuid_keyword;
+  unsigned char uuid[16];
+
+  unsigned int touch_keyword;
+  unsigned int touch_xp;
+  unsigned int touch_yp;
+  unsigned int touch_xd;
+  unsigned int touch_yd;
+
+  unsigned int adadj_keyword;
+  unsigned int adadj;
+
+  unsigned int phad_keyword;
+  unsigned int phadadj;
+} __attribute__((packed));
+
+
+extern struct sharpsl_param_info sharpsl_param;
+extern void sharpsl_save_param(void);
+
diff --git a/include/asm-generic/ipc.h b/include/asm-generic/ipc.h
new file mode 100644 (file)
index 0000000..a40407a
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef _ASM_GENERIC_IPC_H
+#define _ASM_GENERIC_IPC_H
+/*
+ * These are used to wrap system calls.
+ *
+ * See architecture code for ugly details..
+ */
+struct ipc_kludge {
+       struct msgbuf __user *msgp;
+       long msgtyp;
+};
+
+#define SEMOP           1
+#define SEMGET          2
+#define SEMCTL          3
+#define SEMTIMEDOP      4
+#define MSGSND         11
+#define MSGRCV         12
+#define MSGGET         13
+#define MSGCTL         14
+#define SHMAT          21
+#define SHMDT          22
+#define SHMGET         23
+#define SHMCTL         24
+
+/* Used by the DIPC package, try and avoid reusing it */
+#define DIPC            25
+
+#define IPCCALL(version,op)    ((version)<<16 | (op))
+
+#endif /* _ASM_GENERIC_IPC_H */
diff --git a/include/asm-i386/seccomp.h b/include/asm-i386/seccomp.h
new file mode 100644 (file)
index 0000000..18da19e
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef _ASM_SECCOMP_H
+
+#include <linux/thread_info.h>
+
+#ifdef TIF_32BIT
+#error "unexpected TIF_32BIT on i386"
+#endif
+
+#include <linux/unistd.h>
+
+#define __NR_seccomp_read __NR_read
+#define __NR_seccomp_write __NR_write
+#define __NR_seccomp_exit __NR_exit
+#define __NR_seccomp_sigreturn __NR_sigreturn
+
+#endif /* _ASM_SECCOMP_H */
diff --git a/include/asm-ia64/sn/tioca.h b/include/asm-ia64/sn/tioca.h
new file mode 100644 (file)
index 0000000..bc1aacf
--- /dev/null
@@ -0,0 +1,596 @@
+#ifndef _ASM_IA64_SN_TIO_TIOCA_H
+#define _ASM_IA64_SN_TIO_TIOCA_H
+
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 2003-2005 Silicon Graphics, Inc. All rights reserved.
+ */
+
+
+#define TIOCA_PART_NUM 0xE020
+#define TIOCA_MFGR_NUM 0x24
+#define TIOCA_REV_A    0x1
+
+/*
+ * Register layout for TIO:CA.  See below for bitmasks for each register.
+ */
+
+struct tioca {
+       uint64_t        ca_id;                          /* 0x000000 */
+       uint64_t        ca_control1;                    /* 0x000008 */
+       uint64_t        ca_control2;                    /* 0x000010 */
+       uint64_t        ca_status1;                     /* 0x000018 */
+       uint64_t        ca_status2;                     /* 0x000020 */
+       uint64_t        ca_gart_aperature;              /* 0x000028 */
+       uint64_t        ca_gfx_detach;                  /* 0x000030 */
+       uint64_t        ca_inta_dest_addr;              /* 0x000038 */
+       uint64_t        ca_intb_dest_addr;              /* 0x000040 */
+       uint64_t        ca_err_int_dest_addr;           /* 0x000048 */
+       uint64_t        ca_int_status;                  /* 0x000050 */
+       uint64_t        ca_int_status_alias;            /* 0x000058 */
+       uint64_t        ca_mult_error;                  /* 0x000060 */
+       uint64_t        ca_mult_error_alias;            /* 0x000068 */
+       uint64_t        ca_first_error;                 /* 0x000070 */
+       uint64_t        ca_int_mask;                    /* 0x000078 */
+       uint64_t        ca_crm_pkterr_type;             /* 0x000080 */
+       uint64_t        ca_crm_pkterr_type_alias;       /* 0x000088 */
+       uint64_t        ca_crm_ct_error_detail_1;       /* 0x000090 */
+       uint64_t        ca_crm_ct_error_detail_2;       /* 0x000098 */
+       uint64_t        ca_crm_tnumto;                  /* 0x0000A0 */
+       uint64_t        ca_gart_err;                    /* 0x0000A8 */
+       uint64_t        ca_pcierr_type;                 /* 0x0000B0 */
+       uint64_t        ca_pcierr_addr;                 /* 0x0000B8 */
+
+       uint64_t        ca_pad_0000C0[3];               /* 0x0000{C0..D0} */
+
+       uint64_t        ca_pci_rd_buf_flush;            /* 0x0000D8 */
+       uint64_t        ca_pci_dma_addr_extn;           /* 0x0000E0 */
+       uint64_t        ca_agp_dma_addr_extn;           /* 0x0000E8 */
+       uint64_t        ca_force_inta;                  /* 0x0000F0 */
+       uint64_t        ca_force_intb;                  /* 0x0000F8 */
+       uint64_t        ca_debug_vector_sel;            /* 0x000100 */
+       uint64_t        ca_debug_mux_core_sel;          /* 0x000108 */
+       uint64_t        ca_debug_mux_pci_sel;           /* 0x000110 */
+       uint64_t        ca_debug_domain_sel;            /* 0x000118 */
+
+       uint64_t        ca_pad_000120[28];              /* 0x0001{20..F8} */
+
+       uint64_t        ca_gart_ptr_table;              /* 0x200 */
+       uint64_t        ca_gart_tlb_addr[8];            /* 0x2{08..40} */
+};
+
+/*
+ * Mask/shift definitions for TIO:CA registers.  The convention here is
+ * to mainly use the names as they appear in the "TIO AEGIS Programmers'
+ * Reference" with a CA_ prefix added.  Some exceptions were made to fix
+ * duplicate field names or to generalize fields that are common to
+ * different registers (ca_debug_mux_core_sel and ca_debug_mux_pci_sel for
+ * example).
+ *
+ * Fields consisting of a single bit have a single #define have a single
+ * macro declaration to mask the bit.  Fields consisting of multiple bits
+ * have two declarations: one to mask the proper bits in a register, and 
+ * a second with the suffix "_SHFT" to identify how far the mask needs to
+ * be shifted right to get its base value.
+ */
+
+/* ==== ca_control1 */
+#define CA_SYS_BIG_END                 (1ull << 0)
+#define CA_DMA_AGP_SWAP                        (1ull << 1)
+#define CA_DMA_PCI_SWAP                        (1ull << 2)
+#define CA_PIO_IO_SWAP                 (1ull << 3)
+#define CA_PIO_MEM_SWAP                        (1ull << 4)
+#define CA_GFX_WR_SWAP                 (1ull << 5)
+#define CA_AGP_FW_ENABLE               (1ull << 6)
+#define CA_AGP_CAL_CYCLE               (0x7ull << 7)
+#define CA_AGP_CAL_CYCLE_SHFT          7
+#define CA_AGP_CAL_PRSCL_BYP           (1ull << 10)
+#define CA_AGP_INIT_CAL_ENB            (1ull << 11)
+#define CA_INJ_ADDR_PERR               (1ull << 12)
+#define CA_INJ_DATA_PERR               (1ull << 13)
+       /* bits 15:14 unused */
+#define CA_PCIM_IO_NBE_AD              (0x7ull << 16)
+#define CA_PCIM_IO_NBE_AD_SHFT         16
+#define CA_PCIM_FAST_BTB_ENB           (1ull << 19)
+       /* bits 23:20 unused */
+#define CA_PIO_ADDR_OFFSET             (0xffull << 24)
+#define CA_PIO_ADDR_OFFSET_SHFT                24
+       /* bits 35:32 unused */
+#define CA_AGPDMA_OP_COMBDELAY         (0x1full << 36)
+#define CA_AGPDMA_OP_COMBDELAY_SHFT    36
+       /* bit 41 unused */
+#define CA_AGPDMA_OP_ENB_COMBDELAY     (1ull << 42)
+#define        CA_PCI_INT_LPCNT                (0xffull << 44)
+#define CA_PCI_INT_LPCNT_SHFT          44
+       /* bits 63:52 unused */
+
+/* ==== ca_control2 */
+#define CA_AGP_LATENCY_TO              (0xffull << 0)
+#define CA_AGP_LATENCY_TO_SHFT         0
+#define CA_PCI_LATENCY_TO              (0xffull << 8)
+#define CA_PCI_LATENCY_TO_SHFT         8
+#define CA_PCI_MAX_RETRY               (0x3ffull << 16)
+#define CA_PCI_MAX_RETRY_SHFT          16
+       /* bits 27:26 unused */
+#define CA_RT_INT_EN                   (0x3ull << 28)
+#define CA_RT_INT_EN_SHFT                      28
+#define CA_MSI_INT_ENB                 (1ull << 30)
+#define CA_PCI_ARB_ERR_ENB             (1ull << 31)
+#define CA_GART_MEM_PARAM              (0x3ull << 32)
+#define CA_GART_MEM_PARAM_SHFT         32
+#define CA_GART_RD_PREFETCH_ENB                (1ull << 34)
+#define CA_GART_WR_PREFETCH_ENB                (1ull << 35)
+#define CA_GART_FLUSH_TLB              (1ull << 36)
+       /* bits 39:37 unused */
+#define CA_CRM_TNUMTO_PERIOD           (0x1fffull << 40)
+#define CA_CRM_TNUMTO_PERIOD_SHFT      40
+       /* bits 55:53 unused */
+#define CA_CRM_TNUMTO_ENB              (1ull << 56)
+#define CA_CRM_PRESCALER_BYP           (1ull << 57)
+       /* bits 59:58 unused */
+#define CA_CRM_MAX_CREDIT              (0x7ull << 60)
+#define CA_CRM_MAX_CREDIT_SHFT         60
+       /* bit 63 unused */
+
+/* ==== ca_status1 */
+#define CA_CORELET_ID                  (0x3ull << 0)
+#define CA_CORELET_ID_SHFT             0
+#define CA_INTA_N                      (1ull << 2)
+#define CA_INTB_N                      (1ull << 3)
+#define CA_CRM_CREDIT_AVAIL            (0x7ull << 4)
+#define CA_CRM_CREDIT_AVAIL_SHFT       4
+       /* bit 7 unused */
+#define CA_CRM_SPACE_AVAIL             (0x7full << 8)
+#define CA_CRM_SPACE_AVAIL_SHFT                8
+       /* bit 15 unused */
+#define CA_GART_TLB_VAL                        (0xffull << 16)
+#define CA_GART_TLB_VAL_SHFT           16
+       /* bits 63:24 unused */
+
+/* ==== ca_status2 */
+#define CA_GFX_CREDIT_AVAIL            (0xffull << 0)
+#define CA_GFX_CREDIT_AVAIL_SHFT       0
+#define CA_GFX_OPQ_AVAIL               (0xffull << 8)
+#define CA_GFX_OPQ_AVAIL_SHFT          8
+#define CA_GFX_WRBUFF_AVAIL            (0xffull << 16)
+#define CA_GFX_WRBUFF_AVAIL_SHFT       16
+#define CA_ADMA_OPQ_AVAIL              (0xffull << 24)
+#define CA_ADMA_OPQ_AVAIL_SHFT         24
+#define CA_ADMA_WRBUFF_AVAIL           (0xffull << 32)
+#define CA_ADMA_WRBUFF_AVAIL_SHFT      32
+#define CA_ADMA_RDBUFF_AVAIL           (0x7full << 40)
+#define CA_ADMA_RDBUFF_AVAIL_SHFT      40
+#define CA_PCI_PIO_OP_STAT             (1ull << 47)
+#define CA_PDMA_OPQ_AVAIL              (0xfull << 48)
+#define CA_PDMA_OPQ_AVAIL_SHFT         48
+#define CA_PDMA_WRBUFF_AVAIL           (0xfull << 52)
+#define CA_PDMA_WRBUFF_AVAIL_SHFT      52
+#define CA_PDMA_RDBUFF_AVAIL           (0x3ull << 56)
+#define CA_PDMA_RDBUFF_AVAIL_SHFT      56
+       /* bits 63:58 unused */
+
+/* ==== ca_gart_aperature */
+#define CA_GART_AP_ENB_AGP             (1ull << 0)
+#define CA_GART_PAGE_SIZE              (1ull << 1)
+#define CA_GART_AP_ENB_PCI             (1ull << 2)
+       /* bits 11:3 unused */
+#define CA_GART_AP_SIZE                        (0x3ffull << 12)
+#define CA_GART_AP_SIZE_SHFT           12
+#define CA_GART_AP_BASE                        (0x3ffffffffffull << 22)
+#define CA_GART_AP_BASE_SHFT           22
+
+/* ==== ca_inta_dest_addr
+   ==== ca_intb_dest_addr 
+   ==== ca_err_int_dest_addr */
+       /* bits 2:0 unused */
+#define CA_INT_DEST_ADDR               (0x7ffffffffffffull << 3)
+#define CA_INT_DEST_ADDR_SHFT          3
+       /* bits 55:54 unused */
+#define CA_INT_DEST_VECT               (0xffull << 56)
+#define CA_INT_DEST_VECT_SHFT          56
+
+/* ==== ca_int_status */
+/* ==== ca_int_status_alias */
+/* ==== ca_mult_error */
+/* ==== ca_mult_error_alias */
+/* ==== ca_first_error */
+/* ==== ca_int_mask */
+#define CA_PCI_ERR                     (1ull << 0)
+       /* bits 3:1 unused */
+#define CA_GART_FETCH_ERR              (1ull << 4)
+#define CA_GFX_WR_OVFLW                        (1ull << 5)
+#define CA_PIO_REQ_OVFLW               (1ull << 6)
+#define CA_CRM_PKTERR                  (1ull << 7)
+#define CA_CRM_DVERR                   (1ull << 8)
+#define CA_TNUMTO                      (1ull << 9)
+#define CA_CXM_RSP_CRED_OVFLW          (1ull << 10)
+#define CA_CXM_REQ_CRED_OVFLW          (1ull << 11)
+#define CA_PIO_INVALID_ADDR            (1ull << 12)
+#define CA_PCI_ARB_TO                  (1ull << 13)
+#define CA_AGP_REQ_OFLOW               (1ull << 14)
+#define CA_SBA_TYPE1_ERR               (1ull << 15)
+       /* bit 16 unused */
+#define CA_INTA                                (1ull << 17)
+#define CA_INTB                                (1ull << 18)
+#define CA_MULT_INTA                   (1ull << 19)
+#define CA_MULT_INTB                   (1ull << 20)
+#define CA_GFX_CREDIT_OVFLW            (1ull << 21)
+       /* bits 63:22 unused */
+
+/* ==== ca_crm_pkterr_type */
+/* ==== ca_crm_pkterr_type_alias */
+#define CA_CRM_PKTERR_SBERR_HDR                (1ull << 0)
+#define CA_CRM_PKTERR_DIDN             (1ull << 1)
+#define CA_CRM_PKTERR_PACTYPE          (1ull << 2)
+#define CA_CRM_PKTERR_INV_TNUM         (1ull << 3)
+#define CA_CRM_PKTERR_ADDR_RNG         (1ull << 4)
+#define CA_CRM_PKTERR_ADDR_ALGN                (1ull << 5)
+#define CA_CRM_PKTERR_HDR_PARAM                (1ull << 6)
+#define CA_CRM_PKTERR_CW_ERR           (1ull << 7)
+#define CA_CRM_PKTERR_SBERR_NH         (1ull << 8)
+#define CA_CRM_PKTERR_EARLY_TERM       (1ull << 9)
+#define CA_CRM_PKTERR_EARLY_TAIL       (1ull << 10)
+#define CA_CRM_PKTERR_MSSNG_TAIL       (1ull << 11)
+#define CA_CRM_PKTERR_MSSNG_HDR                (1ull << 12)
+       /* bits 15:13 unused */
+#define CA_FIRST_CRM_PKTERR_SBERR_HDR  (1ull << 16)
+#define CA_FIRST_CRM_PKTERR_DIDN       (1ull << 17)
+#define CA_FIRST_CRM_PKTERR_PACTYPE    (1ull << 18)
+#define CA_FIRST_CRM_PKTERR_INV_TNUM   (1ull << 19)
+#define CA_FIRST_CRM_PKTERR_ADDR_RNG   (1ull << 20)
+#define CA_FIRST_CRM_PKTERR_ADDR_ALGN  (1ull << 21)
+#define CA_FIRST_CRM_PKTERR_HDR_PARAM  (1ull << 22)
+#define CA_FIRST_CRM_PKTERR_CW_ERR     (1ull << 23)
+#define CA_FIRST_CRM_PKTERR_SBERR_NH   (1ull << 24)
+#define CA_FIRST_CRM_PKTERR_EARLY_TERM (1ull << 25)
+#define CA_FIRST_CRM_PKTERR_EARLY_TAIL (1ull << 26)
+#define CA_FIRST_CRM_PKTERR_MSSNG_TAIL (1ull << 27)
+#define CA_FIRST_CRM_PKTERR_MSSNG_HDR  (1ull << 28)
+       /* bits 63:29 unused */
+
+/* ==== ca_crm_ct_error_detail_1 */
+#define CA_PKT_TYPE                    (0xfull << 0)
+#define CA_PKT_TYPE_SHFT               0
+#define CA_SRC_ID                      (0x3ull << 4)
+#define CA_SRC_ID_SHFT                 4
+#define CA_DATA_SZ                     (0x3ull << 6)
+#define CA_DATA_SZ_SHFT                        6
+#define CA_TNUM                                (0xffull << 8)
+#define CA_TNUM_SHFT                   8
+#define CA_DW_DATA_EN                  (0xffull << 16)
+#define CA_DW_DATA_EN_SHFT             16
+#define CA_GFX_CRED                    (0xffull << 24)
+#define CA_GFX_CRED_SHFT               24
+#define CA_MEM_RD_PARAM                        (0x3ull << 32)
+#define CA_MEM_RD_PARAM_SHFT           32
+#define CA_PIO_OP                      (1ull << 34)
+#define CA_CW_ERR                      (1ull << 35)
+       /* bits 62:36 unused */
+#define CA_VALID                       (1ull << 63)
+
+/* ==== ca_crm_ct_error_detail_2 */
+       /* bits 2:0 unused */
+#define CA_PKT_ADDR                    (0x1fffffffffffffull << 3)
+#define CA_PKT_ADDR_SHFT               3
+       /* bits 63:56 unused */
+
+/* ==== ca_crm_tnumto */
+#define CA_CRM_TNUMTO_VAL              (0xffull << 0)
+#define CA_CRM_TNUMTO_VAL_SHFT         0
+#define CA_CRM_TNUMTO_WR               (1ull << 8)
+       /* bits 63:9 unused */
+
+/* ==== ca_gart_err */
+#define CA_GART_ERR_SOURCE             (0x3ull << 0)
+#define CA_GART_ERR_SOURCE_SHFT                0
+       /* bits 3:2 unused */
+#define CA_GART_ERR_ADDR               (0xfffffffffull << 4)
+#define CA_GART_ERR_ADDR_SHFT          4
+       /* bits 63:40 unused */
+
+/* ==== ca_pcierr_type */
+#define CA_PCIERR_DATA                 (0xffffffffull << 0)
+#define CA_PCIERR_DATA_SHFT            0
+#define CA_PCIERR_ENB                  (0xfull << 32)
+#define CA_PCIERR_ENB_SHFT             32
+#define CA_PCIERR_CMD                  (0xfull << 36)
+#define CA_PCIERR_CMD_SHFT             36
+#define CA_PCIERR_A64                  (1ull << 40)
+#define CA_PCIERR_SLV_SERR             (1ull << 41)
+#define CA_PCIERR_SLV_WR_PERR          (1ull << 42)
+#define CA_PCIERR_SLV_RD_PERR          (1ull << 43)
+#define CA_PCIERR_MST_SERR             (1ull << 44)
+#define CA_PCIERR_MST_WR_PERR          (1ull << 45)
+#define CA_PCIERR_MST_RD_PERR          (1ull << 46)
+#define CA_PCIERR_MST_MABT             (1ull << 47)
+#define CA_PCIERR_MST_TABT             (1ull << 48)
+#define CA_PCIERR_MST_RETRY_TOUT       (1ull << 49)
+
+#define CA_PCIERR_TYPES \
+       (CA_PCIERR_A64|CA_PCIERR_SLV_SERR| \
+        CA_PCIERR_SLV_WR_PERR|CA_PCIERR_SLV_RD_PERR| \
+        CA_PCIERR_MST_SERR|CA_PCIERR_MST_WR_PERR|CA_PCIERR_MST_RD_PERR| \
+        CA_PCIERR_MST_MABT|CA_PCIERR_MST_TABT|CA_PCIERR_MST_RETRY_TOUT)
+
+       /* bits 63:50 unused */
+
+/* ==== ca_pci_dma_addr_extn */
+#define CA_UPPER_NODE_OFFSET           (0x3full << 0)
+#define CA_UPPER_NODE_OFFSET_SHFT      0
+       /* bits 7:6 unused */
+#define CA_CHIPLET_ID                  (0x3ull << 8)
+#define CA_CHIPLET_ID_SHFT             8
+       /* bits 11:10 unused */
+#define CA_PCI_DMA_NODE_ID             (0xffffull << 12)
+#define CA_PCI_DMA_NODE_ID_SHFT                12
+       /* bits 27:26 unused */
+#define CA_PCI_DMA_PIO_MEM_TYPE                (1ull << 28)
+       /* bits 63:29 unused */
+
+
+/* ==== ca_agp_dma_addr_extn */
+       /* bits 19:0 unused */
+#define CA_AGP_DMA_NODE_ID             (0xffffull << 20)
+#define CA_AGP_DMA_NODE_ID_SHFT                20
+       /* bits 27:26 unused */
+#define CA_AGP_DMA_PIO_MEM_TYPE                (1ull << 28)
+       /* bits 63:29 unused */
+
+/* ==== ca_debug_vector_sel */
+#define CA_DEBUG_MN_VSEL               (0xfull << 0)
+#define CA_DEBUG_MN_VSEL_SHFT          0
+#define CA_DEBUG_PP_VSEL               (0xfull << 4)
+#define CA_DEBUG_PP_VSEL_SHFT          4
+#define CA_DEBUG_GW_VSEL               (0xfull << 8)
+#define CA_DEBUG_GW_VSEL_SHFT          8
+#define CA_DEBUG_GT_VSEL               (0xfull << 12)
+#define CA_DEBUG_GT_VSEL_SHFT          12
+#define CA_DEBUG_PD_VSEL               (0xfull << 16)
+#define CA_DEBUG_PD_VSEL_SHFT          16
+#define CA_DEBUG_AD_VSEL               (0xfull << 20)
+#define CA_DEBUG_AD_VSEL_SHFT          20
+#define CA_DEBUG_CX_VSEL               (0xfull << 24)
+#define CA_DEBUG_CX_VSEL_SHFT          24
+#define CA_DEBUG_CR_VSEL               (0xfull << 28)
+#define CA_DEBUG_CR_VSEL_SHFT          28
+#define CA_DEBUG_BA_VSEL               (0xfull << 32)
+#define CA_DEBUG_BA_VSEL_SHFT          32
+#define CA_DEBUG_PE_VSEL               (0xfull << 36)
+#define CA_DEBUG_PE_VSEL_SHFT          36
+#define CA_DEBUG_BO_VSEL               (0xfull << 40)
+#define CA_DEBUG_BO_VSEL_SHFT          40
+#define CA_DEBUG_BI_VSEL               (0xfull << 44)
+#define CA_DEBUG_BI_VSEL_SHFT          44
+#define CA_DEBUG_AS_VSEL               (0xfull << 48)
+#define CA_DEBUG_AS_VSEL_SHFT          48
+#define CA_DEBUG_PS_VSEL               (0xfull << 52)
+#define CA_DEBUG_PS_VSEL_SHFT          52
+#define CA_DEBUG_PM_VSEL               (0xfull << 56)
+#define CA_DEBUG_PM_VSEL_SHFT          56
+       /* bits 63:60 unused */
+
+/* ==== ca_debug_mux_core_sel */
+/* ==== ca_debug_mux_pci_sel */
+#define CA_DEBUG_MSEL0                 (0x7ull << 0)
+#define CA_DEBUG_MSEL0_SHFT            0
+       /* bit 3 unused */
+#define CA_DEBUG_NSEL0                 (0x7ull << 4)
+#define CA_DEBUG_NSEL0_SHFT            4
+       /* bit 7 unused */
+#define CA_DEBUG_MSEL1                 (0x7ull << 8)
+#define CA_DEBUG_MSEL1_SHFT            8
+       /* bit 11 unused */
+#define CA_DEBUG_NSEL1                 (0x7ull << 12)
+#define CA_DEBUG_NSEL1_SHFT            12
+       /* bit 15 unused */
+#define CA_DEBUG_MSEL2                 (0x7ull << 16)
+#define CA_DEBUG_MSEL2_SHFT            16
+       /* bit 19 unused */
+#define CA_DEBUG_NSEL2                 (0x7ull << 20)
+#define CA_DEBUG_NSEL2_SHFT            20
+       /* bit 23 unused */
+#define CA_DEBUG_MSEL3                 (0x7ull << 24)
+#define CA_DEBUG_MSEL3_SHFT            24
+       /* bit 27 unused */
+#define CA_DEBUG_NSEL3                 (0x7ull << 28)
+#define CA_DEBUG_NSEL3_SHFT            28
+       /* bit 31 unused */
+#define CA_DEBUG_MSEL4                 (0x7ull << 32)
+#define CA_DEBUG_MSEL4_SHFT            32
+       /* bit 35 unused */
+#define CA_DEBUG_NSEL4                 (0x7ull << 36)
+#define CA_DEBUG_NSEL4_SHFT            36
+       /* bit 39 unused */
+#define CA_DEBUG_MSEL5                 (0x7ull << 40)
+#define CA_DEBUG_MSEL5_SHFT            40
+       /* bit 43 unused */
+#define CA_DEBUG_NSEL5                 (0x7ull << 44)
+#define CA_DEBUG_NSEL5_SHFT            44
+       /* bit 47 unused */
+#define CA_DEBUG_MSEL6                 (0x7ull << 48)
+#define CA_DEBUG_MSEL6_SHFT            48
+       /* bit 51 unused */
+#define CA_DEBUG_NSEL6                 (0x7ull << 52)
+#define CA_DEBUG_NSEL6_SHFT            52
+       /* bit 55 unused */
+#define CA_DEBUG_MSEL7                 (0x7ull << 56)
+#define CA_DEBUG_MSEL7_SHFT            56
+       /* bit 59 unused */
+#define CA_DEBUG_NSEL7                 (0x7ull << 60)
+#define CA_DEBUG_NSEL7_SHFT            60
+       /* bit 63 unused */
+
+
+/* ==== ca_debug_domain_sel */
+#define CA_DEBUG_DOMAIN_L              (1ull << 0)
+#define CA_DEBUG_DOMAIN_H              (1ull << 1)
+       /* bits 63:2 unused */
+
+/* ==== ca_gart_ptr_table */
+#define CA_GART_PTR_VAL                        (1ull << 0)
+       /* bits 11:1 unused */
+#define CA_GART_PTR_ADDR               (0xfffffffffffull << 12)
+#define CA_GART_PTR_ADDR_SHFT          12
+       /* bits 63:56 unused */
+
+/* ==== ca_gart_tlb_addr[0-7] */
+#define CA_GART_TLB_ADDR               (0xffffffffffffffull << 0)
+#define CA_GART_TLB_ADDR_SHFT          0
+       /* bits 62:56 unused */
+#define CA_GART_TLB_ENTRY_VAL          (1ull << 63)
+
+/*
+ * PIO address space ranges for TIO:CA
+ */
+
+/* CA internal registers */
+#define CA_PIO_ADMIN                   0x00000000
+#define CA_PIO_ADMIN_LEN               0x00010000
+
+/* GFX Write Buffer - Diagnostics */
+#define CA_PIO_GFX                     0x00010000
+#define CA_PIO_GFX_LEN                 0x00010000
+
+/* AGP DMA Write Buffer - Diagnostics */
+#define CA_PIO_AGP_DMAWRITE            0x00020000
+#define CA_PIO_AGP_DMAWRITE_LEN                0x00010000
+
+/* AGP DMA READ Buffer - Diagnostics */
+#define CA_PIO_AGP_DMAREAD             0x00030000
+#define CA_PIO_AGP_DMAREAD_LEN         0x00010000
+
+/* PCI Config Type 0 */
+#define CA_PIO_PCI_TYPE0_CONFIG                0x01000000
+#define CA_PIO_PCI_TYPE0_CONFIG_LEN    0x01000000
+
+/* PCI Config Type 1 */
+#define CA_PIO_PCI_TYPE1_CONFIG                0x02000000
+#define CA_PIO_PCI_TYPE1_CONFIG_LEN    0x01000000
+
+/* PCI I/O Cycles - mapped to PCI Address 0x00000000-0x04ffffff */
+#define CA_PIO_PCI_IO                  0x03000000
+#define CA_PIO_PCI_IO_LEN              0x05000000
+
+/* PCI MEM Cycles - mapped to PCI with CA_PIO_ADDR_OFFSET of ca_control1 */
+/*     use Fast Write if enabled and coretalk packet type is a GFX request */
+#define CA_PIO_PCI_MEM_OFFSET          0x08000000
+#define CA_PIO_PCI_MEM_OFFSET_LEN      0x08000000
+
+/* PCI MEM Cycles - mapped to PCI Address 0x00000000-0xbfffffff */
+/*     use Fast Write if enabled and coretalk packet type is a GFX request */
+#define CA_PIO_PCI_MEM                 0x40000000
+#define CA_PIO_PCI_MEM_LEN             0xc0000000
+
+/*
+ * DMA space
+ *
+ * The CA aperature (ie. bus address range) mapped by the GART is segmented into
+ * two parts.  The lower portion of the aperature is used for mapping 32 bit
+ * PCI addresses which are managed by the dma interfaces in this file.  The
+ * upper poprtion of the aperature is used for mapping 48 bit AGP addresses.
+ * The AGP portion of the aperature is managed by the agpgart_be.c driver
+ * in drivers/linux/agp.  There are ca-specific hooks in that driver to
+ * manipulate the gart, but management of the AGP portion of the aperature
+ * is the responsibility of that driver.
+ *
+ * CA allows three main types of DMA mapping:
+ *
+ * PCI 64-bit  Managed by this driver
+ * PCI 32-bit  Managed by this driver
+ * AGP 48-bit  Managed by hooks in the /dev/agpgart driver
+ *
+ * All of the above can optionally be remapped through the GART.  The following
+ * table lists the combinations of addressing types and GART remapping that
+ * is currently supported by the driver (h/w supports all, s/w limits this):
+ *
+ *             PCI64           PCI32           AGP48
+ * GART                no              yes             yes
+ * Direct      yes             yes             no
+ *
+ * GART remapping of PCI64 is not done because there is no need to.  The
+ * 64 bit PCI address holds all of the information necessary to target any
+ * memory in the system.
+ *
+ * AGP48 is always mapped through the GART.  Management of the AGP48 portion
+ * of the aperature is the responsibility of code in the agpgart_be driver.
+ *
+ * The non-64 bit bus address space will currently be partitioned like this:
+ *
+ *     0xffff_ffff_ffff        +--------
+ *                             | AGP48 direct
+ *                             | Space managed by this driver
+ *     CA_AGP_DIRECT_BASE      +--------
+ *                             | AGP GART mapped (gfx aperature)
+ *                             | Space managed by /dev/agpgart driver
+ *                             | This range is exposed to the agpgart
+ *                             | driver as the "graphics aperature"
+ *     CA_AGP_MAPPED_BASE      +-----
+ *                             | PCI GART mapped
+ *                             | Space managed by this driver          
+ *     CA_PCI32_MAPPED_BASE    +----
+ *                             | PCI32 direct
+ *                             | Space managed by this driver
+ *     0xC000_0000             +--------
+ *     (CA_PCI32_DIRECT_BASE)
+ *
+ * The bus address range CA_PCI32_MAPPED_BASE through CA_AGP_DIRECT_BASE
+ * is what we call the CA aperature.  Addresses falling in this range will
+ * be remapped using the GART.
+ *
+ * The bus address range CA_AGP_MAPPED_BASE through CA_AGP_DIRECT_BASE
+ * is what we call the graphics aperature.  This is a subset of the CA
+ * aperature and is under the control of the agpgart_be driver.
+ *
+ * CA_PCI32_MAPPED_BASE, CA_AGP_MAPPED_BASE, and CA_AGP_DIRECT_BASE are
+ * somewhat arbitrary values.  The known constraints on choosing these is:
+ *
+ * 1)  CA_AGP_DIRECT_BASE-CA_PCI32_MAPPED_BASE+1 (the CA aperature size)
+ *     must be one of the values supported by the ca_gart_aperature register.
+ *     Currently valid values are: 4MB through 4096MB in powers of 2 increments
+ *
+ * 2)  CA_AGP_DIRECT_BASE-CA_AGP_MAPPED_BASE+1 (the gfx aperature size)
+ *     must be in MB units since that's what the agpgart driver assumes.
+ */
+
+/*
+ * Define Bus DMA ranges.  These are configurable (see constraints above)
+ * and will probably need tuning based on experience.
+ */
+
+
+/*
+ * 11/24/03
+ * CA has an addressing glitch w.r.t. PCI direct 32 bit DMA that makes it
+ * generally unusable.  The problem is that for PCI direct 32 
+ * DMA's, all 32 bits of the bus address are used to form the lower 32 bits
+ * of the coretalk address, and coretalk bits 38:32 come from a register.
+ * Since only PCI bus addresses 0xC0000000-0xFFFFFFFF (1GB) are available
+ * for DMA (the rest is allocated to PIO), host node addresses need to be
+ * such that their lower 32 bits fall in the 0xC0000000-0xffffffff range
+ * as well.  So there can be no PCI32 direct DMA below 3GB!!  For this
+ * reason we set the CA_PCI32_DIRECT_SIZE to 0 which essentially makes
+ * tioca_dma_direct32() a noop but preserves the code flow should this issue
+ * be fixed in a respin.
+ *
+ * For now, all PCI32 DMA's must be mapped through the GART.
+ */
+
+#define CA_PCI32_DIRECT_BASE   0xC0000000UL    /* BASE not configurable */
+#define CA_PCI32_DIRECT_SIZE   0x00000000UL    /* 0 MB */
+
+#define CA_PCI32_MAPPED_BASE   0xC0000000UL
+#define CA_PCI32_MAPPED_SIZE   0x40000000UL    /* 2GB */
+
+#define CA_AGP_MAPPED_BASE     0x80000000UL
+#define CA_AGP_MAPPED_SIZE     0x40000000UL    /* 2GB */
+
+#define CA_AGP_DIRECT_BASE     0x40000000UL    /* 2GB */
+#define CA_AGP_DIRECT_SIZE     0x40000000UL
+
+#define CA_APERATURE_BASE      (CA_AGP_MAPPED_BASE)
+#define CA_APERATURE_SIZE      (CA_AGP_MAPPED_SIZE+CA_PCI32_MAPPED_SIZE)
+
+#endif  /* _ASM_IA64_SN_TIO_TIOCA_H */
diff --git a/include/asm-ia64/sn/tiocx.h b/include/asm-ia64/sn/tiocx.h
new file mode 100644 (file)
index 0000000..c5447a5
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 2005 Silicon Graphics, Inc. All rights reserved.
+ */
+
+#ifndef _ASM_IA64_SN_TIO_TIOCX_H
+#define _ASM_IA64_SN_TIO_TIOCX_H
+
+#ifdef __KERNEL__
+
+struct cx_id_s {
+       unsigned int part_num;
+       unsigned int mfg_num;
+       int nasid;
+};
+
+struct cx_dev {
+       struct cx_id_s cx_id;
+       void *soft;                     /* driver specific */
+       struct hubdev_info *hubdev;
+       struct device dev;
+       struct cx_drv *driver;
+};
+
+struct cx_device_id {
+       unsigned int part_num;
+       unsigned int mfg_num;
+};
+
+struct cx_drv {
+       char *name;
+       const struct cx_device_id *id_table;
+       struct device_driver driver;
+       int (*probe) (struct cx_dev * dev, const struct cx_device_id * id);
+       int (*remove) (struct cx_dev * dev);
+};
+
+/* create DMA address by stripping AS bits */
+#define TIOCX_DMA_ADDR(a) (uint64_t)((uint64_t)(a) & 0xffffcfffffffffUL)
+
+#define TIOCX_TO_TIOCX_DMA_ADDR(a) (uint64_t)(((uint64_t)(a) & 0xfffffffff) |  \
+                                  ((((uint64_t)(a)) & 0xffffc000000000UL) <<2))
+
+#define TIO_CE_ASIC_PARTNUM 0xce00
+#define TIOCX_CORELET 3
+
+/* These are taken from tio_mmr_as.h */
+#define TIO_ICE_FRZ_CFG               TIO_MMR_ADDR_MOD(0x00000000b0008100UL)
+#define TIO_ICE_PMI_TX_CFG            TIO_MMR_ADDR_MOD(0x00000000b000b100UL)
+#define TIO_ICE_PMI_TX_DYN_CREDIT_STAT_CB3 TIO_MMR_ADDR_MOD(0x00000000b000be18UL)
+#define TIO_ICE_PMI_TX_DYN_CREDIT_STAT_CB3_CREDIT_CNT_MASK 0x000000000000000fUL
+
+#define to_cx_dev(n) container_of(n, struct cx_dev, dev)
+#define to_cx_driver(drv) container_of(drv, struct cx_drv, driver)
+
+extern struct sn_irq_info *tiocx_irq_alloc(nasid_t, int, int, nasid_t, int);
+extern void tiocx_irq_free(struct sn_irq_info *);
+extern int cx_device_unregister(struct cx_dev *);
+extern int cx_device_register(nasid_t, int, int, struct hubdev_info *);
+extern int cx_driver_unregister(struct cx_drv *);
+extern int cx_driver_register(struct cx_drv *);
+extern uint64_t tiocx_dma_addr(uint64_t addr);
+extern uint64_t tiocx_swin_base(int nasid);
+extern void tiocx_mmr_store(int nasid, uint64_t offset, uint64_t value);
+extern uint64_t tiocx_mmr_load(int nasid, uint64_t offset);
+
+#endif                         //  __KERNEL__
+#endif                         // _ASM_IA64_SN_TIO_TIOCX__
diff --git a/include/asm-mips/vr41xx/pci.h b/include/asm-mips/vr41xx/pci.h
new file mode 100644 (file)
index 0000000..c473aa7
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ *  Include file for NEC VR4100 series PCI Control Unit.
+ *
+ *  Copyright (C) 2004-2005  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *
+ *  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
+ */
+#ifndef __NEC_VR41XX_PCI_H
+#define __NEC_VR41XX_PCI_H
+
+#define PCI_MASTER_ADDRESS_MASK        0x7fffffffU
+
+struct pci_master_address_conversion {
+       uint32_t bus_base_address;
+       uint32_t address_mask;
+       uint32_t pci_base_address;
+};
+
+struct pci_target_address_conversion {
+       uint32_t address_mask;
+       uint32_t bus_base_address;
+};
+
+typedef enum {
+       CANNOT_LOCK_FROM_DEVICE,
+       CAN_LOCK_FROM_DEVICE,
+} pci_exclusive_access_t;
+
+struct pci_mailbox_address {
+       uint32_t base_address;
+};
+
+struct pci_target_address_window {
+       uint32_t base_address;
+};
+
+typedef enum {
+       PCI_ARBITRATION_MODE_FAIR,
+       PCI_ARBITRATION_MODE_ALTERNATE_0,
+       PCI_ARBITRATION_MODE_ALTERNATE_B,
+} pci_arbiter_priority_control_t;
+
+typedef enum {
+       PCI_TAKE_AWAY_GNT_DISABLE,
+       PCI_TAKE_AWAY_GNT_ENABLE,
+} pci_take_away_gnt_mode_t;
+
+struct pci_controller_unit_setup {
+       struct pci_master_address_conversion *master_memory1;
+       struct pci_master_address_conversion *master_memory2;
+
+       struct pci_target_address_conversion *target_memory1;
+       struct pci_target_address_conversion *target_memory2;
+
+       struct pci_master_address_conversion *master_io;
+
+       pci_exclusive_access_t exclusive_access;
+
+       uint32_t pci_clock_max;
+       uint8_t wait_time_limit_from_irdy_to_trdy;      /* Only VR4122 is supported */
+
+       struct pci_mailbox_address *mailbox;
+       struct pci_target_address_window *target_window1;
+       struct pci_target_address_window *target_window2;
+
+       uint8_t master_latency_timer;
+       uint8_t retry_limit;
+
+       pci_arbiter_priority_control_t arbiter_priority_control;
+       pci_take_away_gnt_mode_t take_away_gnt_mode;
+
+       struct resource *mem_resource;
+       struct resource *io_resource;
+};
+
+extern void vr41xx_pciu_setup(struct pci_controller_unit_setup *setup);
+
+#endif /* __NEC_VR41XX_PCI_H */
diff --git a/include/asm-mips/vr41xx/siu.h b/include/asm-mips/vr41xx/siu.h
new file mode 100644 (file)
index 0000000..865cc07
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ *  Include file for NEC VR4100 series Serial Interface Unit.
+ *
+ *  Copyright (C) 2005  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *
+ *  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
+ */
+#ifndef __NEC_VR41XX_SIU_H
+#define __NEC_VR41XX_SIU_H
+
+typedef enum {
+       SIU_INTERFACE_RS232C,
+       SIU_INTERFACE_IRDA,
+} siu_interface_t;
+
+extern void vr41xx_select_siu_interface(siu_interface_t interface);
+
+typedef enum {
+       SIU_USE_IRDA,
+       FIR_USE_IRDA,
+} irda_use_t;
+
+extern void vr41xx_use_irda(irda_use_t use);
+
+typedef enum {
+       SHARP_IRDA,
+       TEMIC_IRDA,
+       HP_IRDA,
+} irda_module_t;
+
+typedef enum {
+       IRDA_TX_1_5MBPS,
+       IRDA_TX_4MBPS,
+} irda_speed_t;
+
+extern void vr41xx_select_irda_module(irda_module_t module, irda_speed_t speed);
+
+#endif /* __NEC_VR41XX_SIU_H */
diff --git a/include/asm-ppc/suspend.h b/include/asm-ppc/suspend.h
new file mode 100644 (file)
index 0000000..3df9f32
--- /dev/null
@@ -0,0 +1,12 @@
+static inline int arch_prepare_suspend(void)
+{
+       return 0;
+}
+
+static inline void save_processor_state(void)
+{
+}
+
+static inline void restore_processor_state(void)
+{
+}
diff --git a/include/asm-sh/cpu-sh4/timer.h b/include/asm-sh/cpu-sh4/timer.h
new file mode 100644 (file)
index 0000000..8a4af12
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * include/asm-sh/cpu-sh4/timer.h
+ *
+ * Copyright (C) 2004 Lineo Solutions, Inc. 
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#ifndef __ASM_CPU_SH4_TIMER_H
+#define __ASM_CPU_SH4_TIMER_H
+
+/*
+ * ---------------------------------------------------------------------------
+ * TMU Common definitions for SH4 processors
+ *     SH7750S/SH7750R
+ *     SH7751/SH7751R
+ *     SH7760
+ * ---------------------------------------------------------------------------
+ */
+
+#if !defined(CONFIG_CPU_SUBTYPE_SH7760)
+#define TMU_TOCR        0xffd80000      /* Byte access */
+#endif
+#define TMU_TSTR        0xffd80004      /* Byte access */
+
+#define TMU0_TCOR       0xffd80008      /* Long access */
+#define TMU0_TCNT       0xffd8000c      /* Long access */
+#define TMU0_TCR        0xffd80010      /* Word access */
+
+#define TMU1_TCOR       0xffd80014      /* Long access */
+#define TMU1_TCNT       0xffd80018      /* Long access */
+#define TMU1_TCR        0xffd8001c      /* Word access */
+
+#define TMU2_TCOR       0xffd80020      /* Long access */
+#define TMU2_TCNT       0xffd80024      /* Long access */
+#define TMU2_TCR        0xffd80028      /* Word access */
+#define TMU2_TCPR      0xffd8002c      /* Long access */
+
+#if !defined(CONFIG_CPU_SUBTYPE_SH7760)
+#define TMU3_TCOR       0xfe100008      /* Long access */
+#define TMU3_TCNT       0xfe10000c      /* Long access */
+#define TMU3_TCR        0xfe100010      /* Word access */
+
+#define TMU4_TCOR       0xfe100014      /* Long access */
+#define TMU4_TCNT       0xfe100018      /* Long access */
+#define TMU4_TCR        0xfe10001c      /* Word access */
+#endif
+
+#endif /* __ASM_CPU_SH4_TIMER_H */
+
diff --git a/include/asm-sparc64/rwsem-const.h b/include/asm-sparc64/rwsem-const.h
new file mode 100644 (file)
index 0000000..a303c9d
--- /dev/null
@@ -0,0 +1,12 @@
+/* rwsem-const.h: RW semaphore counter constants.  */
+#ifndef _SPARC64_RWSEM_CONST_H
+#define _SPARC64_RWSEM_CONST_H
+
+#define RWSEM_UNLOCKED_VALUE           0x00000000
+#define RWSEM_ACTIVE_BIAS              0x00000001
+#define RWSEM_ACTIVE_MASK              0x0000ffff
+#define RWSEM_WAITING_BIAS             0xffff0000
+#define RWSEM_ACTIVE_READ_BIAS         RWSEM_ACTIVE_BIAS
+#define RWSEM_ACTIVE_WRITE_BIAS                (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
+
+#endif /* _SPARC64_RWSEM_CONST_H */
diff --git a/include/asm-um/elf-i386.h b/include/asm-um/elf-i386.h
new file mode 100644 (file)
index 0000000..9bab712
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL
+ */
+#ifndef __UM_ELF_I386_H
+#define __UM_ELF_I386_H
+
+#include <asm/user.h>
+
+#define R_386_NONE     0
+#define R_386_32       1
+#define R_386_PC32     2
+#define R_386_GOT32    3
+#define R_386_PLT32    4
+#define R_386_COPY     5
+#define R_386_GLOB_DAT 6
+#define R_386_JMP_SLOT 7
+#define R_386_RELATIVE 8
+#define R_386_GOTOFF   9
+#define R_386_GOTPC    10
+#define R_386_NUM      11
+
+typedef unsigned long elf_greg_t;
+
+#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t))
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+typedef struct user_i387_struct elf_fpregset_t;
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch(x) \
+       (((x)->e_machine == EM_386) || ((x)->e_machine == EM_486))
+
+#define ELF_CLASS      ELFCLASS32
+#define ELF_DATA        ELFDATA2LSB
+#define ELF_ARCH        EM_386
+
+#define ELF_PLAT_INIT(regs, load_addr) do { \
+       PT_REGS_EBX(regs) = 0; \
+       PT_REGS_ECX(regs) = 0; \
+       PT_REGS_EDX(regs) = 0; \
+       PT_REGS_ESI(regs) = 0; \
+       PT_REGS_EDI(regs) = 0; \
+       PT_REGS_EBP(regs) = 0; \
+       PT_REGS_EAX(regs) = 0; \
+} while(0)
+
+#define USE_ELF_CORE_DUMP
+#define ELF_EXEC_PAGESIZE 4096
+
+#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)
+
+/* Shamelessly stolen from include/asm-i386/elf.h */
+
+#define ELF_CORE_COPY_REGS(pr_reg, regs) do {  \
+       pr_reg[0] = PT_REGS_EBX(regs);          \
+       pr_reg[1] = PT_REGS_ECX(regs);          \
+       pr_reg[2] = PT_REGS_EDX(regs);          \
+       pr_reg[3] = PT_REGS_ESI(regs);          \
+       pr_reg[4] = PT_REGS_EDI(regs);          \
+       pr_reg[5] = PT_REGS_EBP(regs);          \
+       pr_reg[6] = PT_REGS_EAX(regs);          \
+       pr_reg[7] = PT_REGS_DS(regs);           \
+       pr_reg[8] = PT_REGS_ES(regs);           \
+       /* fake once used fs and gs selectors? */       \
+       pr_reg[9] = PT_REGS_DS(regs);           \
+       pr_reg[10] = PT_REGS_DS(regs);          \
+       pr_reg[11] = PT_REGS_SYSCALL_NR(regs);  \
+       pr_reg[12] = PT_REGS_IP(regs);          \
+       pr_reg[13] = PT_REGS_CS(regs);          \
+       pr_reg[14] = PT_REGS_EFLAGS(regs);      \
+       pr_reg[15] = PT_REGS_SP(regs);          \
+       pr_reg[16] = PT_REGS_SS(regs);          \
+} while(0);
+
+extern long elf_aux_hwcap;
+#define ELF_HWCAP (elf_aux_hwcap)
+
+extern char * elf_aux_platform;
+#define ELF_PLATFORM (elf_aux_platform)
+
+#define SET_PERSONALITY(ex, ibcs2) do ; while(0)
+
+extern unsigned long vsyscall_ehdr;
+extern unsigned long vsyscall_end;
+extern unsigned long __kernel_vsyscall;
+
+#define VSYSCALL_BASE vsyscall_ehdr
+#define VSYSCALL_END vsyscall_end
+
+/*
+ * This is the range that is readable by user mode, and things
+ * acting like user mode such as get_user_pages.
+ */
+#define FIXADDR_USER_START      VSYSCALL_BASE
+#define FIXADDR_USER_END        VSYSCALL_END
+
+/*
+ * Architecture-neutral AT_ values in 0-17, leave some room
+ * for more of them, start the x86-specific ones at 32.
+ */
+#define AT_SYSINFO             32
+#define AT_SYSINFO_EHDR                33
+
+#define ARCH_DLINFO                                            \
+do {                                                           \
+       if ( vsyscall_ehdr ) {                                  \
+               NEW_AUX_ENT(AT_SYSINFO, __kernel_vsyscall);     \
+               NEW_AUX_ENT(AT_SYSINFO_EHDR, vsyscall_ehdr);    \
+       }                                                       \
+} while (0)
+
+/*
+ * These macros parameterize elf_core_dump in fs/binfmt_elf.c to write out
+ * extra segments containing the vsyscall DSO contents.  Dumping its
+ * contents makes post-mortem fully interpretable later without matching up
+ * the same kernel and hardware config to see what PC values meant.
+ * Dumping its extra ELF program headers includes all the other information
+ * a debugger needs to easily find how the vsyscall DSO was being used.
+ */
+#define ELF_CORE_EXTRA_PHDRS                                                 \
+       (vsyscall_ehdr ? (((struct elfhdr *)vsyscall_ehdr)->e_phnum) : 0 )
+
+#define ELF_CORE_WRITE_EXTRA_PHDRS                                           \
+if ( vsyscall_ehdr ) {                                                       \
+       const struct elfhdr *const ehdrp = (struct elfhdr *)vsyscall_ehdr;    \
+       const struct elf_phdr *const phdrp =                                  \
+               (const struct elf_phdr *) (vsyscall_ehdr + ehdrp->e_phoff);   \
+       int i;                                                                \
+       Elf32_Off ofs = 0;                                                    \
+       for (i = 0; i < ehdrp->e_phnum; ++i) {                                \
+               struct elf_phdr phdr = phdrp[i];                              \
+               if (phdr.p_type == PT_LOAD) {                                 \
+                       ofs = phdr.p_offset = offset;                         \
+                       offset += phdr.p_filesz;                              \
+               }                                                             \
+               else                                                          \
+                       phdr.p_offset += ofs;                                 \
+               phdr.p_paddr = 0; /* match other core phdrs */                \
+               DUMP_WRITE(&phdr, sizeof(phdr));                              \
+       }                                                                     \
+}
+#define ELF_CORE_WRITE_EXTRA_DATA                                            \
+if ( vsyscall_ehdr ) {                                                       \
+       const struct elfhdr *const ehdrp = (struct elfhdr *)vsyscall_ehdr;    \
+       const struct elf_phdr *const phdrp =                                  \
+               (const struct elf_phdr *) (vsyscall_ehdr + ehdrp->e_phoff);   \
+       int i;                                                                \
+       for (i = 0; i < ehdrp->e_phnum; ++i) {                                \
+               if (phdrp[i].p_type == PT_LOAD)                               \
+                       DUMP_WRITE((void *) phdrp[i].p_vaddr,                 \
+                                  phdrp[i].p_filesz);                        \
+       }                                                                     \
+}
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/include/asm-um/elf-x86_64.h b/include/asm-um/elf-x86_64.h
new file mode 100644 (file)
index 0000000..8a8246d
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2003 PathScale, Inc.
+ *
+ * Licensed under the GPL
+ */
+#ifndef __UM_ELF_X86_64_H
+#define __UM_ELF_X86_64_H
+
+#include <asm/user.h>
+
+/* x86-64 relocation types, taken from asm-x86_64/elf.h */
+#define R_X86_64_NONE          0       /* No reloc */
+#define R_X86_64_64            1       /* Direct 64 bit  */
+#define R_X86_64_PC32          2       /* PC relative 32 bit signed */
+#define R_X86_64_GOT32         3       /* 32 bit GOT entry */
+#define R_X86_64_PLT32         4       /* 32 bit PLT address */
+#define R_X86_64_COPY          5       /* Copy symbol at runtime */
+#define R_X86_64_GLOB_DAT      6       /* Create GOT entry */
+#define R_X86_64_JUMP_SLOT     7       /* Create PLT entry */
+#define R_X86_64_RELATIVE      8       /* Adjust by program base */
+#define R_X86_64_GOTPCREL      9       /* 32 bit signed pc relative
+                                          offset to GOT */
+#define R_X86_64_32            10      /* Direct 32 bit zero extended */
+#define R_X86_64_32S           11      /* Direct 32 bit sign extended */
+#define R_X86_64_16            12      /* Direct 16 bit zero extended */
+#define R_X86_64_PC16          13      /* 16 bit sign extended pc relative */
+#define R_X86_64_8             14      /* Direct 8 bit sign extended  */
+#define R_X86_64_PC8           15      /* 8 bit sign extended pc relative */
+
+#define R_X86_64_NUM           16
+
+typedef unsigned long elf_greg_t;
+
+#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t))
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+typedef struct { } elf_fpregset_t;
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch(x) \
+       ((x)->e_machine == EM_X86_64)
+
+#define ELF_CLASS      ELFCLASS64
+#define ELF_DATA        ELFDATA2LSB
+#define ELF_ARCH        EM_X86_64
+
+#define ELF_PLAT_INIT(regs, load_addr)    do { \
+       PT_REGS_RBX(regs) = 0; \
+       PT_REGS_RCX(regs) = 0; \
+       PT_REGS_RDX(regs) = 0; \
+       PT_REGS_RSI(regs) = 0; \
+       PT_REGS_RDI(regs) = 0; \
+       PT_REGS_RBP(regs) = 0; \
+       PT_REGS_RAX(regs) = 0; \
+       PT_REGS_R8(regs) = 0; \
+       PT_REGS_R9(regs) = 0; \
+       PT_REGS_R10(regs) = 0; \
+       PT_REGS_R11(regs) = 0; \
+       PT_REGS_R12(regs) = 0; \
+       PT_REGS_R13(regs) = 0; \
+       PT_REGS_R14(regs) = 0; \
+       PT_REGS_R15(regs) = 0; \
+} while (0)
+
+#ifdef TIF_IA32 /* XXX */
+#error XXX, indeed
+        clear_thread_flag(TIF_IA32);
+#endif
+
+#define USE_ELF_CORE_DUMP
+#define ELF_EXEC_PAGESIZE 4096
+
+#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)
+
+extern long elf_aux_hwcap;
+#define ELF_HWCAP (elf_aux_hwcap)
+
+#define ELF_PLATFORM "x86_64"
+
+#define SET_PERSONALITY(ex, ibcs2) do ; while(0)
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/include/asm-x86_64/seccomp.h b/include/asm-x86_64/seccomp.h
new file mode 100644 (file)
index 0000000..553af65
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef _ASM_SECCOMP_H
+
+#include <linux/thread_info.h>
+
+#ifdef TIF_32BIT
+#error "unexpected TIF_32BIT on x86_64"
+#else
+#define TIF_32BIT TIF_IA32
+#endif
+
+#include <linux/unistd.h>
+#include <asm/ia32_unistd.h>
+
+#define __NR_seccomp_read __NR_read
+#define __NR_seccomp_write __NR_write
+#define __NR_seccomp_exit __NR_exit
+#define __NR_seccomp_sigreturn __NR_rt_sigreturn
+
+#define __NR_seccomp_read_32 __NR_ia32_read
+#define __NR_seccomp_write_32 __NR_ia32_write
+#define __NR_seccomp_exit_32 __NR_ia32_exit
+#define __NR_seccomp_sigreturn_32 __NR_ia32_sigreturn
+
+#endif /* _ASM_SECCOMP_H */
diff --git a/include/linux/compiler-gcc4.h b/include/linux/compiler-gcc4.h
new file mode 100644 (file)
index 0000000..53686c0
--- /dev/null
@@ -0,0 +1,16 @@
+/* Never include this file directly.  Include <linux/compiler.h> instead.  */
+
+/* These definitions are for GCC v4.x.  */
+#include <linux/compiler-gcc.h>
+
+#define inline                 inline          __attribute__((always_inline))
+#define __inline__             __inline__      __attribute__((always_inline))
+#define __inline               __inline        __attribute__((always_inline))
+#define __deprecated           __attribute__((deprecated))
+#define __attribute_used__     __attribute__((__used__))
+#define __attribute_pure__     __attribute__((pure))
+#define __attribute_const__    __attribute__((__const__))
+#define  noinline              __attribute__((noinline))
+#define __must_check           __attribute__((warn_unused_result))
+#define __compiler_offsetof(a,b) __builtin_offsetof(a,b)
+
diff --git a/include/linux/cryptohash.h b/include/linux/cryptohash.h
new file mode 100644 (file)
index 0000000..c118b2a
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef __CRYPTOHASH_H
+#define __CRYPTOHASH_H
+
+#define SHA_DIGEST_WORDS 5
+#define SHA_WORKSPACE_WORDS 80
+
+void sha_init(__u32 *buf);
+void sha_transform(__u32 *digest, const char *data, __u32 *W);
+
+__u32 half_md4_transform(__u32 buf[4], __u32 const in[8]);
+
+#endif
diff --git a/include/linux/hdpu_features.h b/include/linux/hdpu_features.h
new file mode 100644 (file)
index 0000000..6a87154
--- /dev/null
@@ -0,0 +1,26 @@
+#include <linux/spinlock.h>
+
+struct cpustate_t {
+       spinlock_t lock;
+       int excl;
+        int open_count;
+       unsigned char cached_val;
+       int inited;
+       unsigned long *set_addr;
+       unsigned long *clr_addr;
+};
+
+
+#define HDPU_CPUSTATE_NAME "hdpu cpustate"
+#define HDPU_NEXUS_NAME "hdpu nexus"
+
+#define CPUSTATE_KERNEL_MAJOR  0x10
+
+#define CPUSTATE_KERNEL_INIT_DRV   0 /* CPU State Driver Initialized */
+#define CPUSTATE_KERNEL_INIT_PCI   1 /* 64360 PCI Busses Init */
+#define CPUSTATE_KERNEL_INIT_REG   2 /* 64360 Bridge Init */
+#define CPUSTATE_KERNEL_CPU1_KICK  3 /* Boot cpu 1 */
+#define CPUSTATE_KERNEL_CPU1_OK    4  /* Cpu 1 has checked in */
+#define CPUSTATE_KERNEL_OK         5 /* Terminal state */
+#define CPUSTATE_KERNEL_RESET   14 /* Board reset via SW*/
+#define CPUSTATE_KERNEL_HALT   15 /* Board halted via SW*/
diff --git a/include/linux/ip_mp_alg.h b/include/linux/ip_mp_alg.h
new file mode 100644 (file)
index 0000000..e234e20
--- /dev/null
@@ -0,0 +1,22 @@
+/* ip_mp_alg.h: IPV4 multipath algorithm support, user-visible values.
+ *
+ * Copyright (C) 2004, 2005 Einar Lueck <elueck@de.ibm.com>
+ * Copyright (C) 2005 David S. Miller <davem@davemloft.net>
+ */
+
+#ifndef _LINUX_IP_MP_ALG_H
+#define _LINUX_IP_MP_ALG_H
+
+enum ip_mp_alg {
+       IP_MP_ALG_NONE,
+       IP_MP_ALG_RR,
+       IP_MP_ALG_DRR,
+       IP_MP_ALG_RANDOM,
+       IP_MP_ALG_WRANDOM,
+       __IP_MP_ALG_MAX
+};
+
+#define IP_MP_ALG_MAX (__IP_MP_ALG_MAX - 1)
+
+#endif /* _LINUX_IP_MP_ALG_H */
+
diff --git a/include/linux/patchkey.h b/include/linux/patchkey.h
new file mode 100644 (file)
index 0000000..d974a6e
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * <linux/patchkey.h> -- definition of _PATCHKEY macro
+ *
+ * Copyright (C) 2005 Stuart Brady
+ *
+ * This exists because awe_voice.h defined its own _PATCHKEY and it wasn't
+ * clear whether removing this would break anything in userspace.
+ *
+ * Do not include this file directly.  Please use <sys/soundcard.h> instead.
+ * For kernel code, use <linux/soundcard.h>
+ */
+
+#ifndef _LINUX_PATCHKEY_H_INDIRECT
+#error "patchkey.h included directly"
+#endif
+
+#ifndef _LINUX_PATCHKEY_H
+#define _LINUX_PATCHKEY_H
+
+/* Endian macros. */
+#ifdef __KERNEL__
+#  include <asm/byteorder.h>
+#else
+#  include <endian.h>
+#endif
+
+#if defined(__KERNEL__)
+#  if defined(__BIG_ENDIAN)
+#    define _PATCHKEY(id) (0xfd00|id)
+#  elif defined(__LITTLE_ENDIAN)
+#    define _PATCHKEY(id) ((id<<8)|0x00fd)
+#  else
+#    error "could not determine byte order"
+#  endif
+#elif defined(__BYTE_ORDER)
+#  if __BYTE_ORDER == __BIG_ENDIAN
+#    define _PATCHKEY(id) (0xfd00|id)
+#  elif __BYTE_ORDER == __LITTLE_ENDIAN
+#    define _PATCHKEY(id) ((id<<8)|0x00fd)
+#  else
+#    error "could not determine byte order"
+#  endif
+#endif
+
+#endif /* _LINUX_PATCHKEY_H */
diff --git a/include/linux/reboot_fixups.h b/include/linux/reboot_fixups.h
new file mode 100644 (file)
index 0000000..480ea2d
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef _LINUX_REBOOT_FIXUPS_H
+#define _LINUX_REBOOT_FIXUPS_H
+
+#ifdef CONFIG_X86_REBOOTFIXUPS
+extern void mach_reboot_fixups(void);
+#else
+#define mach_reboot_fixups() ((void)(0))
+#endif
+
+#endif /* _LINUX_REBOOT_FIXUPS_H */
diff --git a/include/linux/sort.h b/include/linux/sort.h
new file mode 100644 (file)
index 0000000..d534da2
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef _LINUX_SORT_H
+#define _LINUX_SORT_H
+
+#include <linux/types.h>
+
+void sort(void *base, size_t num, size_t size,
+         int (*cmp)(const void *, const void *),
+         void (*swap)(void *, void *, int));
+
+#endif
diff --git a/include/linux/superhyway.h b/include/linux/superhyway.h
new file mode 100644 (file)
index 0000000..c906c5a
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * include/linux/superhyway.h
+ *
+ * SuperHyway Bus definitions
+ *
+ * Copyright (C) 2004, 2005  Paul Mundt <lethal@linux-sh.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#ifndef __LINUX_SUPERHYWAY_H
+#define __LINUX_SUPERHYWAY_H
+
+#include <linux/device.h>
+
+/*
+ * SuperHyway IDs
+ */
+#define SUPERHYWAY_DEVICE_ID_SH5_DMAC  0x0183
+
+struct vcr_info {
+       u8      perr_flags;     /* P-port Error flags */
+       u8      merr_flags;     /* Module Error flags */
+       u16     mod_vers;       /* Module Version */
+       u16     mod_id;         /* Module ID */
+       u8      bot_mb;         /* Bottom Memory block */
+       u8      top_mb;         /* Top Memory block */
+};
+
+struct superhyway_device_id {
+       unsigned int id;
+       unsigned long driver_data;
+};
+
+struct superhyway_device;
+extern struct bus_type superhyway_bus_type;
+
+struct superhyway_driver {
+       char *name;
+
+       const struct superhyway_device_id *id_table;
+       struct device_driver drv;
+
+       int (*probe)(struct superhyway_device *dev, const struct superhyway_device_id *id);
+       void (*remove)(struct superhyway_device *dev);
+};
+
+#define to_superhyway_driver(d)        container_of((d), struct superhyway_driver, drv)
+
+struct superhyway_device {
+       char name[32];
+
+       struct device dev;
+
+       struct superhyway_device_id id;
+       struct superhyway_driver *drv;
+
+       struct resource resource;
+       struct vcr_info vcr;
+};
+
+#define to_superhyway_device(d)        container_of((d), struct superhyway_device, dev)
+
+#define superhyway_get_drvdata(d)      dev_get_drvdata(&(d)->dev)
+#define superhyway_set_drvdata(d,p)    dev_set_drvdata(&(d)->dev, (p))
+
+extern int superhyway_scan_bus(void);
+
+/* drivers/sh/superhyway/superhyway.c */
+int superhyway_register_driver(struct superhyway_driver *);
+void superhyway_unregister_driver(struct superhyway_driver *);
+int superhyway_add_device(unsigned int, unsigned long, unsigned long long);
+
+/* drivers/sh/superhyway/superhyway-sysfs.c */
+extern struct device_attribute superhyway_dev_attrs[];
+
+#endif /* __LINUX_SUPERHYWAY_H */
+
diff --git a/include/linux/tc_act/tc_defact.h b/include/linux/tc_act/tc_defact.h
new file mode 100644 (file)
index 0000000..964f473
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef __LINUX_TC_DEF_H
+#define __LINUX_TC_DEF_H
+
+#include <linux/pkt_cls.h>
+
+struct tc_defact
+{
+       tc_gen;
+};
+                                                                                
+enum
+{
+       TCA_DEF_UNSPEC,
+       TCA_DEF_TM,
+       TCA_DEF_PARMS,
+       TCA_DEF_DATA,
+       __TCA_DEF_MAX
+};
+#define TCA_DEF_MAX (__TCA_DEF_MAX - 1)
+
+#endif
diff --git a/include/linux/tc_ematch/tc_em_cmp.h b/include/linux/tc_ematch/tc_em_cmp.h
new file mode 100644 (file)
index 0000000..c7f4d43
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef __LINUX_TC_EM_CMP_H
+#define __LINUX_TC_EM_CMP_H
+
+#include <linux/pkt_cls.h>
+
+struct tcf_em_cmp
+{
+       __u32           val;
+       __u32           mask;
+       __u16           off;
+       __u8            align:4;
+       __u8            flags:4;
+       __u8            layer:4;
+       __u8            opnd:4;
+};
+
+enum
+{
+       TCF_EM_ALIGN_U8  = 1,
+       TCF_EM_ALIGN_U16 = 2,
+       TCF_EM_ALIGN_U32 = 4
+};
+
+#define TCF_EM_CMP_TRANS       1
+
+#endif
diff --git a/include/linux/tc_ematch/tc_em_meta.h b/include/linux/tc_ematch/tc_em_meta.h
new file mode 100644 (file)
index 0000000..a6b2cc5
--- /dev/null
@@ -0,0 +1,99 @@
+#ifndef __LINUX_TC_EM_META_H
+#define __LINUX_TC_EM_META_H
+
+#include <linux/pkt_cls.h>
+
+enum
+{
+       TCA_EM_META_UNSPEC,
+       TCA_EM_META_HDR,
+       TCA_EM_META_LVALUE,
+       TCA_EM_META_RVALUE,
+       __TCA_EM_META_MAX
+};
+#define TCA_EM_META_MAX (__TCA_EM_META_MAX - 1)
+
+struct tcf_meta_val
+{
+       __u16                   kind;
+       __u8                    shift;
+       __u8                    op;
+};
+
+#define TCF_META_TYPE_MASK     (0xf << 12)
+#define TCF_META_TYPE(kind)    (((kind) & TCF_META_TYPE_MASK) >> 12)
+#define TCF_META_ID_MASK       0x7ff
+#define TCF_META_ID(kind)      ((kind) & TCF_META_ID_MASK)
+
+enum
+{
+       TCF_META_TYPE_VAR,
+       TCF_META_TYPE_INT,
+       __TCF_META_TYPE_MAX
+};
+#define TCF_META_TYPE_MAX (__TCF_META_TYPE_MAX - 1)
+
+enum
+{
+       TCF_META_ID_VALUE,
+       TCF_META_ID_RANDOM,
+       TCF_META_ID_LOADAVG_0,
+       TCF_META_ID_LOADAVG_1,
+       TCF_META_ID_LOADAVG_2,
+       TCF_META_ID_DEV,
+       TCF_META_ID_INDEV,
+       TCF_META_ID_REALDEV,
+       TCF_META_ID_PRIORITY,
+       TCF_META_ID_PROTOCOL,
+       TCF_META_ID_SECURITY,
+       TCF_META_ID_PKTTYPE,
+       TCF_META_ID_PKTLEN,
+       TCF_META_ID_DATALEN,
+       TCF_META_ID_MACLEN,
+       TCF_META_ID_NFMARK,
+       TCF_META_ID_TCINDEX,
+       TCF_META_ID_TCVERDICT,
+       TCF_META_ID_TCCLASSID,
+       TCF_META_ID_RTCLASSID,
+       TCF_META_ID_RTIIF,
+       TCF_META_ID_SK_FAMILY,
+       TCF_META_ID_SK_STATE,
+       TCF_META_ID_SK_REUSE,
+       TCF_META_ID_SK_BOUND_IF,
+       TCF_META_ID_SK_REFCNT,
+       TCF_META_ID_SK_SHUTDOWN,
+       TCF_META_ID_SK_PROTO,
+       TCF_META_ID_SK_TYPE,
+       TCF_META_ID_SK_RCVBUF,
+       TCF_META_ID_SK_RMEM_ALLOC,
+       TCF_META_ID_SK_WMEM_ALLOC,
+       TCF_META_ID_SK_OMEM_ALLOC,
+       TCF_META_ID_SK_WMEM_QUEUED,
+       TCF_META_ID_SK_RCV_QLEN,
+       TCF_META_ID_SK_SND_QLEN,
+       TCF_META_ID_SK_ERR_QLEN,
+       TCF_META_ID_SK_FORWARD_ALLOCS,
+       TCF_META_ID_SK_SNDBUF,
+       TCF_META_ID_SK_ALLOCS,
+       TCF_META_ID_SK_ROUTE_CAPS,
+       TCF_META_ID_SK_HASHENT,
+       TCF_META_ID_SK_LINGERTIME,
+       TCF_META_ID_SK_ACK_BACKLOG,
+       TCF_META_ID_SK_MAX_ACK_BACKLOG,
+       TCF_META_ID_SK_PRIO,
+       TCF_META_ID_SK_RCVLOWAT,
+       TCF_META_ID_SK_RCVTIMEO,
+       TCF_META_ID_SK_SNDTIMEO,
+       TCF_META_ID_SK_SENDMSG_OFF,
+       TCF_META_ID_SK_WRITE_PENDING,
+       __TCF_META_ID_MAX
+};
+#define TCF_META_ID_MAX (__TCF_META_ID_MAX - 1)
+
+struct tcf_meta_hdr
+{
+       struct tcf_meta_val     left;
+       struct tcf_meta_val     right;
+};
+
+#endif
diff --git a/include/linux/tc_ematch/tc_em_nbyte.h b/include/linux/tc_ematch/tc_em_nbyte.h
new file mode 100644 (file)
index 0000000..f19d1f5
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef __LINUX_TC_EM_NBYTE_H
+#define __LINUX_TC_EM_NBYTE_H
+
+#include <linux/pkt_cls.h>
+
+struct tcf_em_nbyte
+{
+       __u16           off;
+       __u16           len:12;
+       __u8            layer:4;
+};
+
+#endif
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
new file mode 100644 (file)
index 0000000..7fe57f9
--- /dev/null
@@ -0,0 +1,882 @@
+/*
+ * Merged with mainline ieee80211.h in Aug 2004.  Original ieee802_11
+ * remains copyright by the original authors
+ *
+ * Portions of the merged code are based on Host AP (software wireless
+ * LAN access point) driver for Intersil Prism2/2.5/3.
+ *
+ * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
+ * <jkmaline@cc.hut.fi>
+ * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
+ *
+ * Adaption to a generic IEEE 802.11 stack by James Ketrenos
+ * <jketreno@linux.intel.com>
+ * Copyright (c) 2004, Intel Corporation
+ *
+ * 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
+ * published by the Free Software Foundation. See README and COPYING for
+ * more details.
+ */
+#ifndef IEEE80211_H
+#define IEEE80211_H
+
+#include <linux/if_ether.h> /* ETH_ALEN */
+#include <linux/kernel.h>   /* ARRAY_SIZE */
+
+#if WIRELESS_EXT < 17
+#define IW_QUAL_QUAL_INVALID   0x10
+#define IW_QUAL_LEVEL_INVALID  0x20
+#define IW_QUAL_NOISE_INVALID  0x40
+#define IW_QUAL_QUAL_UPDATED   0x1
+#define IW_QUAL_LEVEL_UPDATED  0x2
+#define IW_QUAL_NOISE_UPDATED  0x4
+#endif
+
+#define IEEE80211_DATA_LEN             2304
+/* Maximum size for the MA-UNITDATA primitive, 802.11 standard section
+   6.2.1.1.2.
+
+   The figure in section 7.1.2 suggests a body size of up to 2312
+   bytes is allowed, which is a bit confusing, I suspect this
+   represents the 2304 bytes of real data, plus a possible 8 bytes of
+   WEP IV and ICV. (this interpretation suggested by Ramiro Barreiro) */
+
+
+#define IEEE80211_HLEN                 30
+#define IEEE80211_FRAME_LEN            (IEEE80211_DATA_LEN + IEEE80211_HLEN)
+
+struct ieee80211_hdr {
+       u16 frame_ctl;
+       u16 duration_id;
+       u8 addr1[ETH_ALEN];
+       u8 addr2[ETH_ALEN];
+       u8 addr3[ETH_ALEN];
+       u16 seq_ctl;
+       u8 addr4[ETH_ALEN];
+} __attribute__ ((packed));
+
+struct ieee80211_hdr_3addr {
+       u16 frame_ctl;
+       u16 duration_id;
+       u8 addr1[ETH_ALEN];
+       u8 addr2[ETH_ALEN];
+       u8 addr3[ETH_ALEN];
+       u16 seq_ctl;
+} __attribute__ ((packed));
+
+enum eap_type {
+       EAP_PACKET = 0,
+       EAPOL_START,
+       EAPOL_LOGOFF,
+       EAPOL_KEY,
+       EAPOL_ENCAP_ASF_ALERT
+};
+
+static const char *eap_types[] = {
+       [EAP_PACKET]            = "EAP-Packet",
+       [EAPOL_START]           = "EAPOL-Start",
+       [EAPOL_LOGOFF]          = "EAPOL-Logoff",
+       [EAPOL_KEY]             = "EAPOL-Key",
+       [EAPOL_ENCAP_ASF_ALERT] = "EAPOL-Encap-ASF-Alert"
+};
+
+static inline const char *eap_get_type(int type)
+{
+       return (type >= ARRAY_SIZE(eap_types)) ? "Unknown" : eap_types[type];
+}
+
+struct eapol {
+       u8 snap[6];
+       u16 ethertype;
+       u8 version;
+       u8 type;
+       u16 length;
+} __attribute__ ((packed));
+
+#define IEEE80211_3ADDR_LEN 24
+#define IEEE80211_4ADDR_LEN 30
+#define IEEE80211_FCS_LEN    4
+
+#define MIN_FRAG_THRESHOLD     256U
+#define        MAX_FRAG_THRESHOLD     2346U
+
+/* Frame control field constants */
+#define IEEE80211_FCTL_VERS            0x0002
+#define IEEE80211_FCTL_FTYPE           0x000c
+#define IEEE80211_FCTL_STYPE           0x00f0
+#define IEEE80211_FCTL_TODS            0x0100
+#define IEEE80211_FCTL_FROMDS          0x0200
+#define IEEE80211_FCTL_MOREFRAGS       0x0400
+#define IEEE80211_FCTL_RETRY           0x0800
+#define IEEE80211_FCTL_PM              0x1000
+#define IEEE80211_FCTL_MOREDATA        0x2000
+#define IEEE80211_FCTL_WEP             0x4000
+#define IEEE80211_FCTL_ORDER           0x8000
+
+#define IEEE80211_FTYPE_MGMT           0x0000
+#define IEEE80211_FTYPE_CTL            0x0004
+#define IEEE80211_FTYPE_DATA           0x0008
+
+/* management */
+#define IEEE80211_STYPE_ASSOC_REQ      0x0000
+#define IEEE80211_STYPE_ASSOC_RESP     0x0010
+#define IEEE80211_STYPE_REASSOC_REQ    0x0020
+#define IEEE80211_STYPE_REASSOC_RESP   0x0030
+#define IEEE80211_STYPE_PROBE_REQ      0x0040
+#define IEEE80211_STYPE_PROBE_RESP     0x0050
+#define IEEE80211_STYPE_BEACON         0x0080
+#define IEEE80211_STYPE_ATIM           0x0090
+#define IEEE80211_STYPE_DISASSOC       0x00A0
+#define IEEE80211_STYPE_AUTH           0x00B0
+#define IEEE80211_STYPE_DEAUTH         0x00C0
+
+/* control */
+#define IEEE80211_STYPE_PSPOLL         0x00A0
+#define IEEE80211_STYPE_RTS            0x00B0
+#define IEEE80211_STYPE_CTS            0x00C0
+#define IEEE80211_STYPE_ACK            0x00D0
+#define IEEE80211_STYPE_CFEND          0x00E0
+#define IEEE80211_STYPE_CFENDACK       0x00F0
+
+/* data */
+#define IEEE80211_STYPE_DATA           0x0000
+#define IEEE80211_STYPE_DATA_CFACK     0x0010
+#define IEEE80211_STYPE_DATA_CFPOLL    0x0020
+#define IEEE80211_STYPE_DATA_CFACKPOLL 0x0030
+#define IEEE80211_STYPE_NULLFUNC       0x0040
+#define IEEE80211_STYPE_CFACK          0x0050
+#define IEEE80211_STYPE_CFPOLL         0x0060
+#define IEEE80211_STYPE_CFACKPOLL      0x0070
+
+#define IEEE80211_SCTL_FRAG            0x000F
+#define IEEE80211_SCTL_SEQ             0xFFF0
+
+
+/* debug macros */
+
+#ifdef CONFIG_IEEE80211_DEBUG
+extern u32 ieee80211_debug_level;
+#define IEEE80211_DEBUG(level, fmt, args...) \
+do { if (ieee80211_debug_level & (level)) \
+  printk(KERN_DEBUG "ieee80211: %c %s " fmt, \
+         in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0)
+#else
+#define IEEE80211_DEBUG(level, fmt, args...) do {} while (0)
+#endif /* CONFIG_IEEE80211_DEBUG */
+
+/*
+ * To use the debug system;
+ *
+ * If you are defining a new debug classification, simply add it to the #define
+ * list here in the form of:
+ *
+ * #define IEEE80211_DL_xxxx VALUE
+ *
+ * shifting value to the left one bit from the previous entry.  xxxx should be
+ * the name of the classification (for example, WEP)
+ *
+ * You then need to either add a IEEE80211_xxxx_DEBUG() macro definition for your
+ * classification, or use IEEE80211_DEBUG(IEEE80211_DL_xxxx, ...) whenever you want
+ * to send output to that classification.
+ *
+ * To add your debug level to the list of levels seen when you perform
+ *
+ * % cat /proc/net/ipw/debug_level
+ *
+ * you simply need to add your entry to the ipw_debug_levels array.
+ *
+ * If you do not see debug_level in /proc/net/ipw then you do not have
+ * CONFIG_IEEE80211_DEBUG defined in your kernel configuration
+ *
+ */
+
+#define IEEE80211_DL_INFO          (1<<0)
+#define IEEE80211_DL_WX            (1<<1)
+#define IEEE80211_DL_SCAN          (1<<2)
+#define IEEE80211_DL_STATE         (1<<3)
+#define IEEE80211_DL_MGMT          (1<<4)
+#define IEEE80211_DL_FRAG          (1<<5)
+#define IEEE80211_DL_EAP           (1<<6)
+#define IEEE80211_DL_DROP          (1<<7)
+
+#define IEEE80211_DL_TX            (1<<8)
+#define IEEE80211_DL_RX            (1<<9)
+
+#define IEEE80211_ERROR(f, a...) printk(KERN_ERR "ieee80211: " f, ## a)
+#define IEEE80211_WARNING(f, a...) printk(KERN_WARNING "ieee80211: " f, ## a)
+#define IEEE80211_DEBUG_INFO(f, a...)   IEEE80211_DEBUG(IEEE80211_DL_INFO, f, ## a)
+
+#define IEEE80211_DEBUG_WX(f, a...)     IEEE80211_DEBUG(IEEE80211_DL_WX, f, ## a)
+#define IEEE80211_DEBUG_SCAN(f, a...)   IEEE80211_DEBUG(IEEE80211_DL_SCAN, f, ## a)
+#define IEEE80211_DEBUG_STATE(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_STATE, f, ## a)
+#define IEEE80211_DEBUG_MGMT(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_MGMT, f, ## a)
+#define IEEE80211_DEBUG_FRAG(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_FRAG, f, ## a)
+#define IEEE80211_DEBUG_EAP(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_EAP, f, ## a)
+#define IEEE80211_DEBUG_DROP(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_DROP, f, ## a)
+#define IEEE80211_DEBUG_TX(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_TX, f, ## a)
+#define IEEE80211_DEBUG_RX(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_RX, f, ## a)
+#include <linux/netdevice.h>
+#include <linux/wireless.h>
+#include <linux/if_arp.h> /* ARPHRD_ETHER */
+
+#ifndef WIRELESS_SPY
+#define WIRELESS_SPY           // enable iwspy support
+#endif
+#include <net/iw_handler.h>    // new driver API
+
+#ifndef ETH_P_PAE
+#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */
+#endif /* ETH_P_PAE */
+
+#define ETH_P_PREAUTH 0x88C7 /* IEEE 802.11i pre-authentication */
+
+#ifndef ETH_P_80211_RAW
+#define ETH_P_80211_RAW (ETH_P_ECONET + 1)
+#endif
+
+/* IEEE 802.11 defines */
+
+#define P80211_OUI_LEN 3
+
+struct ieee80211_snap_hdr {
+
+        u8    dsap;   /* always 0xAA */
+        u8    ssap;   /* always 0xAA */
+        u8    ctrl;   /* always 0x03 */
+        u8    oui[P80211_OUI_LEN];    /* organizational universal id */
+
+} __attribute__ ((packed));
+
+#define SNAP_SIZE sizeof(struct ieee80211_snap_hdr)
+
+#define WLAN_FC_GET_TYPE(fc) ((fc) & IEEE80211_FCTL_FTYPE)
+#define WLAN_FC_GET_STYPE(fc) ((fc) & IEEE80211_FCTL_STYPE)
+
+#define WLAN_GET_SEQ_FRAG(seq) ((seq) & IEEE80211_SCTL_FRAG)
+#define WLAN_GET_SEQ_SEQ(seq)  ((seq) & IEEE80211_SCTL_SEQ)
+
+/* Authentication algorithms */
+#define WLAN_AUTH_OPEN 0
+#define WLAN_AUTH_SHARED_KEY 1
+
+#define WLAN_AUTH_CHALLENGE_LEN 128
+
+#define WLAN_CAPABILITY_BSS (1<<0)
+#define WLAN_CAPABILITY_IBSS (1<<1)
+#define WLAN_CAPABILITY_CF_POLLABLE (1<<2)
+#define WLAN_CAPABILITY_CF_POLL_REQUEST (1<<3)
+#define WLAN_CAPABILITY_PRIVACY (1<<4)
+#define WLAN_CAPABILITY_SHORT_PREAMBLE (1<<5)
+#define WLAN_CAPABILITY_PBCC (1<<6)
+#define WLAN_CAPABILITY_CHANNEL_AGILITY (1<<7)
+
+/* Status codes */
+#define WLAN_STATUS_SUCCESS 0
+#define WLAN_STATUS_UNSPECIFIED_FAILURE 1
+#define WLAN_STATUS_CAPS_UNSUPPORTED 10
+#define WLAN_STATUS_REASSOC_NO_ASSOC 11
+#define WLAN_STATUS_ASSOC_DENIED_UNSPEC 12
+#define WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG 13
+#define WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION 14
+#define WLAN_STATUS_CHALLENGE_FAIL 15
+#define WLAN_STATUS_AUTH_TIMEOUT 16
+#define WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA 17
+#define WLAN_STATUS_ASSOC_DENIED_RATES 18
+/* 802.11b */
+#define WLAN_STATUS_ASSOC_DENIED_NOSHORT 19
+#define WLAN_STATUS_ASSOC_DENIED_NOPBCC 20
+#define WLAN_STATUS_ASSOC_DENIED_NOAGILITY 21
+
+/* Reason codes */
+#define WLAN_REASON_UNSPECIFIED 1
+#define WLAN_REASON_PREV_AUTH_NOT_VALID 2
+#define WLAN_REASON_DEAUTH_LEAVING 3
+#define WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY 4
+#define WLAN_REASON_DISASSOC_AP_BUSY 5
+#define WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA 6
+#define WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA 7
+#define WLAN_REASON_DISASSOC_STA_HAS_LEFT 8
+#define WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH 9
+
+
+/* Information Element IDs */
+#define WLAN_EID_SSID 0
+#define WLAN_EID_SUPP_RATES 1
+#define WLAN_EID_FH_PARAMS 2
+#define WLAN_EID_DS_PARAMS 3
+#define WLAN_EID_CF_PARAMS 4
+#define WLAN_EID_TIM 5
+#define WLAN_EID_IBSS_PARAMS 6
+#define WLAN_EID_CHALLENGE 16
+#define WLAN_EID_RSN 48
+#define WLAN_EID_GENERIC 221
+
+#define IEEE80211_MGMT_HDR_LEN 24
+#define IEEE80211_DATA_HDR3_LEN 24
+#define IEEE80211_DATA_HDR4_LEN 30
+
+
+#define IEEE80211_STATMASK_SIGNAL (1<<0)
+#define IEEE80211_STATMASK_RSSI (1<<1)
+#define IEEE80211_STATMASK_NOISE (1<<2)
+#define IEEE80211_STATMASK_RATE (1<<3)
+#define IEEE80211_STATMASK_WEMASK 0x7
+
+
+#define IEEE80211_CCK_MODULATION    (1<<0)
+#define IEEE80211_OFDM_MODULATION   (1<<1)
+
+#define IEEE80211_24GHZ_BAND     (1<<0)
+#define IEEE80211_52GHZ_BAND     (1<<1)
+
+#define IEEE80211_CCK_RATE_1MB                 0x02
+#define IEEE80211_CCK_RATE_2MB                 0x04
+#define IEEE80211_CCK_RATE_5MB                 0x0B
+#define IEEE80211_CCK_RATE_11MB                        0x16
+#define IEEE80211_OFDM_RATE_6MB                        0x0C
+#define IEEE80211_OFDM_RATE_9MB                        0x12
+#define IEEE80211_OFDM_RATE_12MB               0x18
+#define IEEE80211_OFDM_RATE_18MB               0x24
+#define IEEE80211_OFDM_RATE_24MB               0x30
+#define IEEE80211_OFDM_RATE_36MB               0x48
+#define IEEE80211_OFDM_RATE_48MB               0x60
+#define IEEE80211_OFDM_RATE_54MB               0x6C
+#define IEEE80211_BASIC_RATE_MASK              0x80
+
+#define IEEE80211_CCK_RATE_1MB_MASK            (1<<0)
+#define IEEE80211_CCK_RATE_2MB_MASK            (1<<1)
+#define IEEE80211_CCK_RATE_5MB_MASK            (1<<2)
+#define IEEE80211_CCK_RATE_11MB_MASK           (1<<3)
+#define IEEE80211_OFDM_RATE_6MB_MASK           (1<<4)
+#define IEEE80211_OFDM_RATE_9MB_MASK           (1<<5)
+#define IEEE80211_OFDM_RATE_12MB_MASK          (1<<6)
+#define IEEE80211_OFDM_RATE_18MB_MASK          (1<<7)
+#define IEEE80211_OFDM_RATE_24MB_MASK          (1<<8)
+#define IEEE80211_OFDM_RATE_36MB_MASK          (1<<9)
+#define IEEE80211_OFDM_RATE_48MB_MASK          (1<<10)
+#define IEEE80211_OFDM_RATE_54MB_MASK          (1<<11)
+
+#define IEEE80211_CCK_RATES_MASK               0x0000000F
+#define IEEE80211_CCK_BASIC_RATES_MASK (IEEE80211_CCK_RATE_1MB_MASK | \
+       IEEE80211_CCK_RATE_2MB_MASK)
+#define IEEE80211_CCK_DEFAULT_RATES_MASK       (IEEE80211_CCK_BASIC_RATES_MASK | \
+        IEEE80211_CCK_RATE_5MB_MASK | \
+        IEEE80211_CCK_RATE_11MB_MASK)
+
+#define IEEE80211_OFDM_RATES_MASK              0x00000FF0
+#define IEEE80211_OFDM_BASIC_RATES_MASK        (IEEE80211_OFDM_RATE_6MB_MASK | \
+       IEEE80211_OFDM_RATE_12MB_MASK | \
+       IEEE80211_OFDM_RATE_24MB_MASK)
+#define IEEE80211_OFDM_DEFAULT_RATES_MASK      (IEEE80211_OFDM_BASIC_RATES_MASK | \
+       IEEE80211_OFDM_RATE_9MB_MASK  | \
+       IEEE80211_OFDM_RATE_18MB_MASK | \
+       IEEE80211_OFDM_RATE_36MB_MASK | \
+       IEEE80211_OFDM_RATE_48MB_MASK | \
+       IEEE80211_OFDM_RATE_54MB_MASK)
+#define IEEE80211_DEFAULT_RATES_MASK (IEEE80211_OFDM_DEFAULT_RATES_MASK | \
+                                IEEE80211_CCK_DEFAULT_RATES_MASK)
+
+#define IEEE80211_NUM_OFDM_RATES           8
+#define IEEE80211_NUM_CCK_RATES                    4
+#define IEEE80211_OFDM_SHIFT_MASK_A         4
+
+
+
+
+/* NOTE: This data is for statistical purposes; not all hardware provides this
+ *       information for frames received.  Not setting these will not cause
+ *       any adverse affects. */
+struct ieee80211_rx_stats {
+       u32 mac_time;
+       s8 rssi;
+       u8 signal;
+       u8 noise;
+       u16 rate; /* in 100 kbps */
+       u8 received_channel;
+       u8 control;
+       u8 mask;
+       u8 freq;
+       u16 len;
+};
+
+/* IEEE 802.11 requires that STA supports concurrent reception of at least
+ * three fragmented frames. This define can be increased to support more
+ * concurrent frames, but it should be noted that each entry can consume about
+ * 2 kB of RAM and increasing cache size will slow down frame reassembly. */
+#define IEEE80211_FRAG_CACHE_LEN 4
+
+struct ieee80211_frag_entry {
+       unsigned long first_frag_time;
+       unsigned int seq;
+       unsigned int last_frag;
+       struct sk_buff *skb;
+       u8 src_addr[ETH_ALEN];
+       u8 dst_addr[ETH_ALEN];
+};
+
+struct ieee80211_stats {
+       unsigned int tx_unicast_frames;
+       unsigned int tx_multicast_frames;
+       unsigned int tx_fragments;
+       unsigned int tx_unicast_octets;
+       unsigned int tx_multicast_octets;
+       unsigned int tx_deferred_transmissions;
+       unsigned int tx_single_retry_frames;
+       unsigned int tx_multiple_retry_frames;
+       unsigned int tx_retry_limit_exceeded;
+       unsigned int tx_discards;
+       unsigned int rx_unicast_frames;
+       unsigned int rx_multicast_frames;
+       unsigned int rx_fragments;
+       unsigned int rx_unicast_octets;
+       unsigned int rx_multicast_octets;
+       unsigned int rx_fcs_errors;
+       unsigned int rx_discards_no_buffer;
+       unsigned int tx_discards_wrong_sa;
+       unsigned int rx_discards_undecryptable;
+       unsigned int rx_message_in_msg_fragments;
+       unsigned int rx_message_in_bad_msg_fragments;
+};
+
+struct ieee80211_device;
+
+#define SEC_KEY_1         (1<<0)
+#define SEC_KEY_2         (1<<1)
+#define SEC_KEY_3         (1<<2)
+#define SEC_KEY_4         (1<<3)
+#define SEC_ACTIVE_KEY    (1<<4)
+#define SEC_AUTH_MODE     (1<<5)
+#define SEC_UNICAST_GROUP (1<<6)
+#define SEC_LEVEL         (1<<7)
+#define SEC_ENABLED       (1<<8)
+
+#define SEC_LEVEL_0      0 /* None */
+#define SEC_LEVEL_1      1 /* WEP 40 and 104 bit */
+#define SEC_LEVEL_2      2 /* Level 1 + TKIP */
+#define SEC_LEVEL_2_CKIP 3 /* Level 1 + CKIP */
+#define SEC_LEVEL_3      4 /* Level 2 + CCMP */
+
+#define WEP_KEYS 4
+#define WEP_KEY_LEN 13
+
+struct ieee80211_security {
+       u16 active_key:2,
+            enabled:1,
+           auth_mode:2,
+            auth_algo:4,
+            unicast_uses_group:1;
+       u8 key_sizes[WEP_KEYS];
+       u8 keys[WEP_KEYS][WEP_KEY_LEN];
+       u8 level;
+       u16 flags;
+} __attribute__ ((packed));
+
+
+/*
+
+ 802.11 data frame from AP
+
+      ,-------------------------------------------------------------------.
+Bytes |  2   |  2   |    6    |    6    |    6    |  2   | 0..2312 |   4  |
+      |------|------|---------|---------|---------|------|---------|------|
+Desc. | ctrl | dura |  DA/RA  |   TA    |    SA   | Sequ |  frame  |  fcs |
+      |      | tion | (BSSID) |         |         | ence |  data   |      |
+      `-------------------------------------------------------------------'
+
+Total: 28-2340 bytes
+
+*/
+
+struct ieee80211_header_data {
+       u16 frame_ctl;
+       u16 duration_id;
+       u8 addr1[6];
+       u8 addr2[6];
+       u8 addr3[6];
+       u16 seq_ctrl;
+};
+
+#define BEACON_PROBE_SSID_ID_POSITION 12
+
+/* Management Frame Information Element Types */
+#define MFIE_TYPE_SSID       0
+#define MFIE_TYPE_RATES      1
+#define MFIE_TYPE_FH_SET     2
+#define MFIE_TYPE_DS_SET     3
+#define MFIE_TYPE_CF_SET     4
+#define MFIE_TYPE_TIM        5
+#define MFIE_TYPE_IBSS_SET   6
+#define MFIE_TYPE_CHALLENGE  16
+#define MFIE_TYPE_RSN       48
+#define MFIE_TYPE_RATES_EX   50
+#define MFIE_TYPE_GENERIC    221
+
+struct ieee80211_info_element_hdr {
+       u8 id;
+       u8 len;
+} __attribute__ ((packed));
+
+struct ieee80211_info_element {
+       u8 id;
+       u8 len;
+       u8 data[0];
+} __attribute__ ((packed));
+
+/*
+ * These are the data types that can make up management packets
+ *
+       u16 auth_algorithm;
+       u16 auth_sequence;
+       u16 beacon_interval;
+       u16 capability;
+       u8 current_ap[ETH_ALEN];
+       u16 listen_interval;
+       struct {
+               u16 association_id:14, reserved:2;
+       } __attribute__ ((packed));
+       u32 time_stamp[2];
+       u16 reason;
+       u16 status;
+*/
+
+struct ieee80211_authentication {
+       struct ieee80211_header_data header;
+       u16 algorithm;
+       u16 transaction;
+       u16 status;
+       struct ieee80211_info_element info_element;
+} __attribute__ ((packed));
+
+
+struct ieee80211_probe_response {
+       struct ieee80211_header_data header;
+       u32 time_stamp[2];
+       u16 beacon_interval;
+       u16 capability;
+       struct ieee80211_info_element info_element;
+} __attribute__ ((packed));
+
+struct ieee80211_assoc_request_frame {
+       u16 capability;
+       u16 listen_interval;
+       u8 current_ap[ETH_ALEN];
+       struct ieee80211_info_element info_element;
+} __attribute__ ((packed));
+
+struct ieee80211_assoc_response_frame {
+       struct ieee80211_hdr_3addr header;
+       u16 capability;
+       u16 status;
+       u16 aid;
+       struct ieee80211_info_element info_element; /* supported rates */
+} __attribute__ ((packed));
+
+
+struct ieee80211_txb {
+       u8 nr_frags;
+       u8 encrypted;
+       u16 reserved;
+       u16 frag_size;
+       u16 payload_size;
+       struct sk_buff *fragments[0];
+};
+
+
+/* SWEEP TABLE ENTRIES NUMBER*/
+#define MAX_SWEEP_TAB_ENTRIES            42
+#define MAX_SWEEP_TAB_ENTRIES_PER_PACKET  7
+/* MAX_RATES_LENGTH needs to be 12.  The spec says 8, and many APs
+ * only use 8, and then use extended rates for the remaining supported
+ * rates.  Other APs, however, stick all of their supported rates on the
+ * main rates information element... */
+#define MAX_RATES_LENGTH                  ((u8)12)
+#define MAX_RATES_EX_LENGTH               ((u8)16)
+#define MAX_NETWORK_COUNT                  128
+
+#define CRC_LENGTH                 4U
+
+#define MAX_WPA_IE_LEN 64
+
+#define NETWORK_EMPTY_ESSID (1<<0)
+#define NETWORK_HAS_OFDM    (1<<1)
+#define NETWORK_HAS_CCK     (1<<2)
+
+struct ieee80211_network {
+       /* These entries are used to identify a unique network */
+       u8 bssid[ETH_ALEN];
+       u8 channel;
+       /* Ensure null-terminated for any debug msgs */
+       u8 ssid[IW_ESSID_MAX_SIZE + 1];
+       u8 ssid_len;
+
+       /* These are network statistics */
+       struct ieee80211_rx_stats stats;
+       u16 capability;
+       u8 rates[MAX_RATES_LENGTH];
+       u8 rates_len;
+       u8 rates_ex[MAX_RATES_EX_LENGTH];
+       u8 rates_ex_len;
+       unsigned long last_scanned;
+       u8 mode;
+       u8 flags;
+       u32 last_associate;
+       u32 time_stamp[2];
+       u16 beacon_interval;
+       u16 listen_interval;
+       u16 atim_window;
+       u8 wpa_ie[MAX_WPA_IE_LEN];
+       size_t wpa_ie_len;
+       u8 rsn_ie[MAX_WPA_IE_LEN];
+       size_t rsn_ie_len;
+       struct list_head list;
+};
+
+enum ieee80211_state {
+       IEEE80211_UNINITIALIZED = 0,
+       IEEE80211_INITIALIZED,
+       IEEE80211_ASSOCIATING,
+       IEEE80211_ASSOCIATED,
+       IEEE80211_AUTHENTICATING,
+       IEEE80211_AUTHENTICATED,
+       IEEE80211_SHUTDOWN
+};
+
+#define DEFAULT_MAX_SCAN_AGE (15 * HZ)
+#define DEFAULT_FTS 2346
+#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
+#define MAC_ARG(x) ((u8*)(x))[0],((u8*)(x))[1],((u8*)(x))[2],((u8*)(x))[3],((u8*)(x))[4],((u8*)(x))[5]
+
+
+extern inline int is_broadcast_ether_addr(const u8 *addr)
+{
+       return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) &&   \
+               (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff));
+}
+
+#define CFG_IEEE80211_RESERVE_FCS (1<<0)
+#define CFG_IEEE80211_COMPUTE_FCS (1<<1)
+
+struct ieee80211_device {
+       struct net_device *dev;
+
+       /* Bookkeeping structures */
+       struct net_device_stats stats;
+       struct ieee80211_stats ieee_stats;
+
+       /* Probe / Beacon management */
+       struct list_head network_free_list;
+       struct list_head network_list;
+       struct ieee80211_network *networks;
+       int scans;
+       int scan_age;
+
+       int iw_mode; /* operating mode (IW_MODE_*) */
+
+       spinlock_t lock;
+
+       int tx_headroom; /* Set to size of any additional room needed at front
+                         * of allocated Tx SKBs */
+       u32 config;
+
+       /* WEP and other encryption related settings at the device level */
+       int open_wep; /* Set to 1 to allow unencrypted frames */
+
+       int reset_on_keychange; /* Set to 1 if the HW needs to be reset on
+                                * WEP key changes */
+
+       /* If the host performs {en,de}cryption, then set to 1 */
+       int host_encrypt;
+       int host_decrypt;
+       int ieee802_1x; /* is IEEE 802.1X used */
+
+       /* WPA data */
+       int wpa_enabled;
+       int drop_unencrypted;
+       int tkip_countermeasures;
+       int privacy_invoked;
+       size_t wpa_ie_len;
+       u8 *wpa_ie;
+
+       struct list_head crypt_deinit_list;
+       struct ieee80211_crypt_data *crypt[WEP_KEYS];
+       int tx_keyidx; /* default TX key index (crypt[tx_keyidx]) */
+       struct timer_list crypt_deinit_timer;
+
+       int bcrx_sta_key; /* use individual keys to override default keys even
+                          * with RX of broad/multicast frames */
+
+       /* Fragmentation structures */
+       struct ieee80211_frag_entry frag_cache[IEEE80211_FRAG_CACHE_LEN];
+       unsigned int frag_next_idx;
+       u16 fts; /* Fragmentation Threshold */
+
+       /* Association info */
+       u8 bssid[ETH_ALEN];
+
+       enum ieee80211_state state;
+
+       int mode;       /* A, B, G */
+       int modulation; /* CCK, OFDM */
+       int freq_band;  /* 2.4Ghz, 5.2Ghz, Mixed */
+       int abg_ture;   /* ABG flag              */
+
+       /* Callback functions */
+       void (*set_security)(struct net_device *dev,
+                            struct ieee80211_security *sec);
+       int (*hard_start_xmit)(struct ieee80211_txb *txb,
+                              struct net_device *dev);
+       int (*reset_port)(struct net_device *dev);
+
+       /* This must be the last item so that it points to the data
+        * allocated beyond this structure by alloc_ieee80211 */
+       u8 priv[0];
+};
+
+#define IEEE_A            (1<<0)
+#define IEEE_B            (1<<1)
+#define IEEE_G            (1<<2)
+#define IEEE_MODE_MASK    (IEEE_A|IEEE_B|IEEE_G)
+
+extern inline void *ieee80211_priv(struct net_device *dev)
+{
+       return ((struct ieee80211_device *)netdev_priv(dev))->priv;
+}
+
+extern inline int ieee80211_is_empty_essid(const char *essid, int essid_len)
+{
+       /* Single white space is for Linksys APs */
+       if (essid_len == 1 && essid[0] == ' ')
+               return 1;
+
+       /* Otherwise, if the entire essid is 0, we assume it is hidden */
+       while (essid_len) {
+               essid_len--;
+               if (essid[essid_len] != '\0')
+                       return 0;
+       }
+
+       return 1;
+}
+
+extern inline int ieee80211_is_valid_mode(struct ieee80211_device *ieee, int mode)
+{
+       /*
+        * It is possible for both access points and our device to support
+        * combinations of modes, so as long as there is one valid combination
+        * of ap/device supported modes, then return success
+        *
+        */
+       if ((mode & IEEE_A) &&
+           (ieee->modulation & IEEE80211_OFDM_MODULATION) &&
+           (ieee->freq_band & IEEE80211_52GHZ_BAND))
+               return 1;
+
+       if ((mode & IEEE_G) &&
+           (ieee->modulation & IEEE80211_OFDM_MODULATION) &&
+           (ieee->freq_band & IEEE80211_24GHZ_BAND))
+               return 1;
+
+       if ((mode & IEEE_B) &&
+           (ieee->modulation & IEEE80211_CCK_MODULATION) &&
+           (ieee->freq_band & IEEE80211_24GHZ_BAND))
+               return 1;
+
+       return 0;
+}
+
+extern inline int ieee80211_get_hdrlen(u16 fc)
+{
+       int hdrlen = 24;
+
+       switch (WLAN_FC_GET_TYPE(fc)) {
+       case IEEE80211_FTYPE_DATA:
+               if ((fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS))
+                       hdrlen = 30; /* Addr4 */
+               break;
+       case IEEE80211_FTYPE_CTL:
+               switch (WLAN_FC_GET_STYPE(fc)) {
+               case IEEE80211_STYPE_CTS:
+               case IEEE80211_STYPE_ACK:
+                       hdrlen = 10;
+                       break;
+               default:
+                       hdrlen = 16;
+                       break;
+               }
+               break;
+       }
+
+       return hdrlen;
+}
+
+
+
+/* ieee80211.c */
+extern void free_ieee80211(struct net_device *dev);
+extern struct net_device *alloc_ieee80211(int sizeof_priv);
+
+extern int ieee80211_set_encryption(struct ieee80211_device *ieee);
+
+/* ieee80211_tx.c */
+
+
+extern int ieee80211_xmit(struct sk_buff *skb,
+                         struct net_device *dev);
+extern void ieee80211_txb_free(struct ieee80211_txb *);
+
+
+/* ieee80211_rx.c */
+extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
+                       struct ieee80211_rx_stats *rx_stats);
+extern void ieee80211_rx_mgt(struct ieee80211_device *ieee,
+                            struct ieee80211_hdr *header,
+                            struct ieee80211_rx_stats *stats);
+
+/* iee80211_wx.c */
+extern int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
+                                struct iw_request_info *info,
+                                union iwreq_data *wrqu, char *key);
+extern int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
+                                  struct iw_request_info *info,
+                                  union iwreq_data *wrqu, char *key);
+extern int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
+                                  struct iw_request_info *info,
+                                  union iwreq_data *wrqu, char *key);
+
+
+extern inline void ieee80211_increment_scans(struct ieee80211_device *ieee)
+{
+       ieee->scans++;
+}
+
+extern inline int ieee80211_get_scans(struct ieee80211_device *ieee)
+{
+       return ieee->scans;
+}
+
+static inline const char *escape_essid(const char *essid, u8 essid_len) {
+       static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
+       const char *s = essid;
+       char *d = escaped;
+
+       if (ieee80211_is_empty_essid(essid, essid_len)) {
+               memcpy(escaped, "<hidden>", sizeof("<hidden>"));
+               return escaped;
+       }
+
+       essid_len = min(essid_len, (u8)IW_ESSID_MAX_SIZE);
+       while (essid_len--) {
+               if (*s == '\0') {
+                       *d++ = '\\';
+                       *d++ = '0';
+                       s++;
+               } else {
+                       *d++ = *s++;
+               }
+       }
+       *d = '\0';
+       return escaped;
+}
+
+#endif /* IEEE80211_H */
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
new file mode 100644 (file)
index 0000000..c3391b6
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * linux/kernel/seccomp.c
+ *
+ * Copyright 2004-2005  Andrea Arcangeli <andrea@cpushare.com>
+ *
+ * This defines a simple but solid secure-computing mode.
+ */
+
+#include <linux/seccomp.h>
+#include <linux/sched.h>
+
+/* #define SECCOMP_DEBUG 1 */
+
+/*
+ * Secure computing mode 1 allows only read/write/exit/sigreturn.
+ * To be fully secure this must be combined with rlimit
+ * to limit the stack allocations too.
+ */
+static int mode1_syscalls[] = {
+       __NR_seccomp_read, __NR_seccomp_write, __NR_seccomp_exit, __NR_seccomp_sigreturn,
+       0, /* null terminated */
+};
+
+#ifdef TIF_32BIT
+static int mode1_syscalls_32[] = {
+       __NR_seccomp_read_32, __NR_seccomp_write_32, __NR_seccomp_exit_32, __NR_seccomp_sigreturn_32,
+       0, /* null terminated */
+};
+#endif
+
+void __secure_computing(int this_syscall)
+{
+       int mode = current->seccomp.mode;
+       int * syscall;
+
+       switch (mode) {
+       case 1:
+               syscall = mode1_syscalls;
+#ifdef TIF_32BIT
+               if (test_thread_flag(TIF_32BIT))
+                       syscall = mode1_syscalls_32;
+#endif
+               do {
+                       if (*syscall == this_syscall)
+                               return;
+               } while (*++syscall);
+               break;
+       default:
+               BUG();
+       }
+
+#ifdef SECCOMP_DEBUG
+       dump_stack();
+#endif
+       do_exit(SIGKILL);
+}
diff --git a/lib/halfmd4.c b/lib/halfmd4.c
new file mode 100644 (file)
index 0000000..e11db26
--- /dev/null
@@ -0,0 +1,66 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/cryptohash.h>
+
+/* F, G and H are basic MD4 functions: selection, majority, parity */
+#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
+#define G(x, y, z) (((x) & (y)) + (((x) ^ (y)) & (z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+
+/*
+ * The generic round function.  The application is so specific that
+ * we don't bother protecting all the arguments with parens, as is generally
+ * good macro practice, in favor of extra legibility.
+ * Rotation is separate from addition to prevent recomputation
+ */
+#define ROUND(f, a, b, c, d, x, s)     \
+       (a += f(b, c, d) + x, a = (a << s) | (a >> (32 - s)))
+#define K1 0
+#define K2 013240474631UL
+#define K3 015666365641UL
+
+/*
+ * Basic cut-down MD4 transform.  Returns only 32 bits of result.
+ */
+__u32 half_md4_transform(__u32 buf[4], __u32 const in[8])
+{
+       __u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
+
+       /* Round 1 */
+       ROUND(F, a, b, c, d, in[0] + K1,  3);
+       ROUND(F, d, a, b, c, in[1] + K1,  7);
+       ROUND(F, c, d, a, b, in[2] + K1, 11);
+       ROUND(F, b, c, d, a, in[3] + K1, 19);
+       ROUND(F, a, b, c, d, in[4] + K1,  3);
+       ROUND(F, d, a, b, c, in[5] + K1,  7);
+       ROUND(F, c, d, a, b, in[6] + K1, 11);
+       ROUND(F, b, c, d, a, in[7] + K1, 19);
+
+       /* Round 2 */
+       ROUND(G, a, b, c, d, in[1] + K2,  3);
+       ROUND(G, d, a, b, c, in[3] + K2,  5);
+       ROUND(G, c, d, a, b, in[5] + K2,  9);
+       ROUND(G, b, c, d, a, in[7] + K2, 13);
+       ROUND(G, a, b, c, d, in[0] + K2,  3);
+       ROUND(G, d, a, b, c, in[2] + K2,  5);
+       ROUND(G, c, d, a, b, in[4] + K2,  9);
+       ROUND(G, b, c, d, a, in[6] + K2, 13);
+
+       /* Round 3 */
+       ROUND(H, a, b, c, d, in[3] + K3,  3);
+       ROUND(H, d, a, b, c, in[7] + K3,  9);
+       ROUND(H, c, d, a, b, in[2] + K3, 11);
+       ROUND(H, b, c, d, a, in[6] + K3, 15);
+       ROUND(H, a, b, c, d, in[1] + K3,  3);
+       ROUND(H, d, a, b, c, in[5] + K3,  9);
+       ROUND(H, c, d, a, b, in[0] + K3, 11);
+       ROUND(H, b, c, d, a, in[4] + K3, 15);
+
+       buf[0] += a;
+       buf[1] += b;
+       buf[2] += c;
+       buf[3] += d;
+
+       return buf[1]; /* "most hashed" word */
+}
+EXPORT_SYMBOL(half_md4_transform);
diff --git a/net/ipv4/multipath.c b/net/ipv4/multipath.c
new file mode 100644 (file)
index 0000000..4e9ca7c
--- /dev/null
@@ -0,0 +1,55 @@
+/* multipath.c: IPV4 multipath algorithm support.
+ *
+ * Copyright (C) 2004, 2005 Einar Lueck <elueck@de.ibm.com>
+ * Copyright (C) 2005 David S. Miller <davem@davemloft.net>
+ */
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/spinlock.h>
+
+#include <net/ip_mp_alg.h>
+
+static DEFINE_SPINLOCK(alg_table_lock);
+struct ip_mp_alg_ops *ip_mp_alg_table[IP_MP_ALG_MAX + 1];
+
+int multipath_alg_register(struct ip_mp_alg_ops *ops, enum ip_mp_alg n)
+{
+       struct ip_mp_alg_ops **slot;
+       int err;
+
+       if (n < IP_MP_ALG_NONE || n > IP_MP_ALG_MAX ||
+           !ops->mp_alg_select_route)
+               return -EINVAL;
+
+       spin_lock(&alg_table_lock);
+       slot = &ip_mp_alg_table[n];
+       if (*slot != NULL) {
+               err = -EBUSY;
+       } else {
+               *slot = ops;
+               err = 0;
+       }
+       spin_unlock(&alg_table_lock);
+
+       return err;
+}
+EXPORT_SYMBOL(multipath_alg_register);
+
+void multipath_alg_unregister(struct ip_mp_alg_ops *ops, enum ip_mp_alg n)
+{
+       struct ip_mp_alg_ops **slot;
+
+       if (n < IP_MP_ALG_NONE || n > IP_MP_ALG_MAX)
+               return;
+
+       spin_lock(&alg_table_lock);
+       slot = &ip_mp_alg_table[n];
+       if (*slot == ops)
+               *slot = NULL;
+       spin_unlock(&alg_table_lock);
+
+       synchronize_net();
+}
+EXPORT_SYMBOL(multipath_alg_unregister);
diff --git a/scripts/kconfig/.kxgettext.o.cmd b/scripts/kconfig/.kxgettext.o.cmd
new file mode 100644 (file)
index 0000000..1ef4182
--- /dev/null
@@ -0,0 +1,48 @@
+cmd_scripts/kconfig/kxgettext.o := gcc -Wp,-MD,scripts/kconfig/.kxgettext.o.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer       -c -o scripts/kconfig/kxgettext.o scripts/kconfig/kxgettext.c
+
+deps_scripts/kconfig/kxgettext.o := \
+  scripts/kconfig/kxgettext.c \
+  /usr/include/stdlib.h \
+  /usr/include/features.h \
+  /usr/include/sys/cdefs.h \
+  /usr/include/gnu/stubs.h \
+  /usr/lib/gcc/i386-redhat-linux/3.4.2/include/stddef.h \
+  /usr/include/sys/types.h \
+  /usr/include/bits/types.h \
+  /usr/include/bits/wordsize.h \
+  /usr/include/bits/typesizes.h \
+  /usr/include/time.h \
+  /usr/include/endian.h \
+  /usr/include/bits/endian.h \
+  /usr/include/sys/select.h \
+  /usr/include/bits/select.h \
+  /usr/include/bits/sigset.h \
+  /usr/include/bits/time.h \
+  /usr/include/sys/sysmacros.h \
+  /usr/include/bits/pthreadtypes.h \
+  /usr/include/bits/sched.h \
+  /usr/include/alloca.h \
+  /usr/include/string.h \
+  /usr/include/bits/string.h \
+  /usr/include/bits/string2.h \
+  scripts/kconfig/lkc.h \
+  scripts/kconfig/expr.h \
+  /usr/include/stdio.h \
+  /usr/include/libio.h \
+  /usr/include/_G_config.h \
+  /usr/include/wchar.h \
+  /usr/include/bits/wchar.h \
+  /usr/include/gconv.h \
+  /usr/lib/gcc/i386-redhat-linux/3.4.2/include/stdarg.h \
+  /usr/include/bits/stdio_lim.h \
+  /usr/include/bits/sys_errlist.h \
+  /usr/include/bits/stdio.h \
+  /usr/lib/gcc/i386-redhat-linux/3.4.2/include/stdbool.h \
+  /usr/include/libintl.h \
+  /usr/include/locale.h \
+  /usr/include/bits/locale.h \
+  scripts/kconfig/lkc_proto.h \
+
+scripts/kconfig/kxgettext.o: $(deps_scripts/kconfig/kxgettext.o)
+
+$(deps_scripts/kconfig/kxgettext.o):
diff --git a/scripts/kconfig/POTFILES.in b/scripts/kconfig/POTFILES.in
new file mode 100644 (file)
index 0000000..cc94e46
--- /dev/null
@@ -0,0 +1,5 @@
+scripts/kconfig/mconf.c
+scripts/kconfig/conf.c
+scripts/kconfig/confdata.c
+scripts/kconfig/gconf.c
+scripts/kconfig/qconf.cc
diff --git a/scripts/kconfig/kxgettext.c b/scripts/kconfig/kxgettext.c
new file mode 100644 (file)
index 0000000..1c88d7c
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ * Arnaldo Carvalho de Melo <acme@conectiva.com.br>, 2005
+ *
+ * Released under the terms of the GNU GPL v2.0
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#define LKC_DIRECT_LINK
+#include "lkc.h"
+
+static char *escape(const char* text, char *bf, int len)
+{
+       char *bfp = bf;
+       int multiline = strchr(text, '\n') != NULL;
+
+       *bfp++ = '"';
+       --len;
+
+       if (multiline) {
+               *bfp++ = '"';
+               *bfp++ = '\n';
+               *bfp++ = '"';
+               len -= 3;
+       }
+
+       while (*text != '\0' && len > 1) {
+               if (*text == '"')
+                       *bfp++ = '\\';
+               else if (*text == '\n') {
+                       *bfp++ = '\\';
+                       *bfp++ = 'n';
+                       *bfp++ = '"';
+                       *bfp++ = '\n';
+                       *bfp++ = '"';
+                       len -= 5;
+                       ++text;
+                       goto next;
+               }
+               *bfp++ = *text++;
+next:
+               --len;
+       }
+
+       if (multiline)
+               bfp -= 3;
+
+       *bfp++ = '"';
+       *bfp = '\0';
+
+       return bf;
+}
+
+struct file_line {
+       struct file_line *next;
+       char*            file;
+       int              lineno;
+};
+
+static struct file_line *file_line__new(char *file, int lineno)
+{
+       struct file_line *self = malloc(sizeof(*self));
+
+       if (self == NULL)
+               goto out;
+
+       self->file   = file;
+       self->lineno = lineno;
+       self->next   = NULL;
+out:
+       return self;
+}
+
+struct message {
+       const char       *msg;
+       const char       *option;
+       struct message   *next;
+       struct file_line *files;
+};
+
+static struct message *message__list;
+
+static struct message *message__new(const char *msg, char *option, char *file, int lineno)
+{
+       struct message *self = malloc(sizeof(*self));
+
+       if (self == NULL)
+               goto out;
+
+       self->files = file_line__new(file, lineno);
+       if (self->files == NULL)
+               goto out_fail;
+
+       self->msg = strdup(msg);
+       if (self->msg == NULL)
+               goto out_fail_msg;
+
+       self->option = option;
+       self->next = NULL;
+out:
+       return self;
+out_fail_msg:
+       free(self->files);
+out_fail:
+       free(self);
+       self = NULL;
+       goto out;
+}
+
+static struct message *mesage__find(const char *msg)
+{
+       struct message *m = message__list;
+
+       while (m != NULL) {
+               if (strcmp(m->msg, msg) == 0)
+                       break;
+               m = m->next;
+       }
+
+       return m;
+}
+
+static int message__add_file_line(struct message *self, char *file, int lineno)
+{
+       int rc = -1;
+       struct file_line *fl = file_line__new(file, lineno);
+
+       if (fl == NULL)
+               goto out;
+
+       fl->next    = self->files;
+       self->files = fl;
+       rc = 0;
+out:
+       return rc;
+}
+
+static int message__add(const char *msg, char *option, char *file, int lineno)
+{
+       int rc = 0;
+       char bf[16384];
+       char *escaped = escape(msg, bf, sizeof(bf));
+       struct message *m = mesage__find(escaped);
+
+       if (m != NULL)
+               rc = message__add_file_line(m, file, lineno);
+       else {
+               m = message__new(escaped, option, file, lineno);
+
+               if (m != NULL) {
+                       m->next       = message__list;
+                       message__list = m;
+               } else
+                       rc = -1;
+       }
+       return rc;
+}
+
+void menu_build_message_list(struct menu *menu)
+{
+       struct menu *child;
+
+       message__add(menu_get_prompt(menu), NULL,
+                    menu->file == NULL ? "Root Menu" : menu->file->name,
+                    menu->lineno);
+
+       if (menu->sym != NULL && menu->sym->help != NULL)
+               message__add(menu->sym->help, menu->sym->name,
+                            menu->file == NULL ? "Root Menu" : menu->file->name,
+                            menu->lineno);
+
+       for (child = menu->list; child != NULL; child = child->next)
+               if (child->prompt != NULL)
+                       menu_build_message_list(child);
+}
+
+static void message__print_file_lineno(struct message *self)
+{
+       struct file_line *fl = self->files;
+
+       printf("\n#: %s:%d", fl->file, fl->lineno);
+       fl = fl->next;
+
+       while (fl != NULL) {
+               printf(", %s:%d", fl->file, fl->lineno);
+               fl = fl->next;
+       }
+
+       if (self->option != NULL)
+               printf(", %s:00000", self->option);
+
+       putchar('\n');
+}
+
+static void message__print_gettext_msgid_msgstr(struct message *self)
+{
+       message__print_file_lineno(self);
+
+       printf("msgid %s\n"
+              "msgstr \"\"\n", self->msg);
+}
+
+void menu__xgettext(void)
+{
+       struct message *m = message__list;
+
+       while (m != NULL) {
+               message__print_gettext_msgid_msgstr(m);
+               m = m->next;
+       }
+}
+
+int main(int ac, char **av)
+{
+       conf_parse(av[1]);
+
+       menu_build_message_list(menu_get_root_menu(NULL));
+       menu__xgettext();
+       return 0;
+}
diff --git a/scripts/kconfig/kxgettext.o b/scripts/kconfig/kxgettext.o
new file mode 100644 (file)
index 0000000..e92d260
Binary files /dev/null and b/scripts/kconfig/kxgettext.o differ
diff --git a/scripts/show_delta b/scripts/show_delta
new file mode 100644 (file)
index 0000000..48a706a
--- /dev/null
@@ -0,0 +1,129 @@
+#!/usr/bin/env python
+#
+# show_deltas: Read list of printk messages instrumented with
+# time data, and format with time deltas.
+#
+# Also, you can show the times relative to a fixed point.
+#
+# Copyright 2003 Sony Corporation
+#
+# GPL 2.0 applies.
+
+import sys
+import string
+
+def usage():
+       print """usage: show_delta [<options>] <filename>
+
+This program parses the output from a set of printk message lines which
+have time data prefixed because the CONFIG_PRINTK_TIME option is set, or
+the kernel command line option "time" is specified. When run with no
+options, the time information is converted to show the time delta between
+each printk line and the next.  When run with the '-b' option, all times
+are relative to a single (base) point in time.
+
+Options:
+  -h            Show this usage help.
+  -b <base>    Specify a base for time references.
+               <base> can be a number or a string.
+               If it is a string, the first message line
+               which matches (at the beginning of the
+               line) is used as the time reference.
+
+ex: $ dmesg >timefile
+    $ show_delta -b NET4 timefile
+
+will show times relative to the line in the kernel output
+starting with "NET4".
+"""
+       sys.exit(1)
+
+# returns a tuple containing the seconds and text for each message line
+# seconds is returned as a float
+# raise an exception if no timing data was found
+def get_time(line):
+       if line[0]!="[":
+               raise ValueError
+
+       # split on closing bracket
+       (time_str, rest) = string.split(line[1:],']',1)
+       time = string.atof(time_str)
+
+       #print "time=", time
+       return (time, rest)
+
+
+# average line looks like:
+# [    0.084282] VFS: Mounted root (romfs filesystem) readonly
+# time data is expressed in seconds.useconds,
+# convert_line adds a delta for each line
+last_time = 0.0
+def convert_line(line, base_time):
+       global last_time
+
+       try:
+               (time, rest) = get_time(line)
+       except:
+               # if any problem parsing time, don't convert anything
+               return line
+
+       if base_time:
+               # show time from base
+               delta = time - base_time
+       else:
+               # just show time from last line
+               delta = time - last_time
+               last_time = time
+
+       return ("[%5.6f < %5.6f >]" % (time, delta)) + rest
+
+def main():
+       base_str = ""
+       filein = ""
+       for arg in sys.argv[1:]:
+               if arg=="-b":
+                       base_str = sys.argv[sys.argv.index("-b")+1]
+               elif arg=="-h":
+                       usage()
+               else:
+                       filein = arg
+
+       if not filein:
+               usage()
+
+       try:
+               lines = open(filein,"r").readlines()
+       except:
+               print "Problem opening file: %s" % filein
+               sys.exit(1)
+
+       if base_str:
+               print 'base= "%s"' % base_str
+               # assume a numeric base.  If that fails, try searching
+               # for a matching line.
+               try:
+                       base_time = float(base_str)
+               except:
+                       # search for line matching <base> string
+                       found = 0
+                       for line in lines:
+                               try:
+                                       (time, rest) = get_time(line)
+                               except:
+                                       continue
+                               if string.find(rest, base_str)==1:
+                                       base_time = time
+                                       found = 1
+                                       # stop at first match
+                                       break
+                       if not found:
+                               print 'Couldn\'t find line matching base pattern "%s"' % base_str
+                               sys.exit(1)
+       else:
+               base_time = 0.0
+
+       for line in lines:
+               print convert_line(line, base_time),
+
+main()
+
diff --git a/sound/core/rawmidi_compat.c b/sound/core/rawmidi_compat.c
new file mode 100644 (file)
index 0000000..d97631c
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ *   32bit -> 64bit ioctl wrapper for raw MIDI API
+ *   Copyright (c) by Takashi Iwai <tiwai@suse.de>
+ *
+ *   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
+ *
+ */
+
+/* This file included from rawmidi.c */
+
+#include <linux/compat.h>
+
+struct sndrv_rawmidi_params32 {
+       s32 stream;
+       u32 buffer_size;
+       u32 avail_min;
+       unsigned int no_active_sensing; /* avoid bit-field */
+       unsigned char reserved[16];
+} __attribute__((packed));
+
+static int snd_rawmidi_ioctl_params_compat(snd_rawmidi_file_t *rfile,
+                                          struct sndrv_rawmidi_params32 __user *src)
+{
+       snd_rawmidi_params_t params;
+       unsigned int val;
+
+       if (rfile->output == NULL)
+               return -EINVAL;
+       if (get_user(params.stream, &src->stream) ||
+           get_user(params.buffer_size, &src->buffer_size) ||
+           get_user(params.avail_min, &src->avail_min) ||
+           get_user(val, &src->no_active_sensing))
+               return -EFAULT;
+       params.no_active_sensing = val;
+       switch (params.stream) {
+       case SNDRV_RAWMIDI_STREAM_OUTPUT:
+               return snd_rawmidi_output_params(rfile->output, &params);
+       case SNDRV_RAWMIDI_STREAM_INPUT:
+               return snd_rawmidi_input_params(rfile->input, &params);
+       }
+       return -EINVAL;
+}
+
+struct sndrv_rawmidi_status32 {
+       s32 stream;
+       struct compat_timespec tstamp;
+       u32 avail;
+       u32 xruns;
+       unsigned char reserved[16];
+} __attribute__((packed));
+
+static int snd_rawmidi_ioctl_status_compat(snd_rawmidi_file_t *rfile,
+                                          struct sndrv_rawmidi_status32 __user *src)
+{
+       int err;
+       snd_rawmidi_status_t status;
+
+       if (rfile->output == NULL)
+               return -EINVAL;
+       if (get_user(status.stream, &src->stream))
+               return -EFAULT;
+
+       switch (status.stream) {
+       case SNDRV_RAWMIDI_STREAM_OUTPUT:
+               err = snd_rawmidi_output_status(rfile->output, &status);
+               break;
+       case SNDRV_RAWMIDI_STREAM_INPUT:
+               err = snd_rawmidi_input_status(rfile->input, &status);
+               break;
+       default:
+               return -EINVAL;
+       }
+       if (err < 0)
+               return err;
+
+       if (put_user(status.tstamp.tv_sec, &src->tstamp.tv_sec) ||
+           put_user(status.tstamp.tv_nsec, &src->tstamp.tv_nsec) ||
+           put_user(status.avail, &src->avail) ||
+           put_user(status.xruns, &src->xruns))
+               return -EFAULT;
+
+       return 0;
+}
+
+enum {
+       SNDRV_RAWMIDI_IOCTL_PARAMS32 = _IOWR('W', 0x10, struct sndrv_rawmidi_params32),
+       SNDRV_RAWMIDI_IOCTL_STATUS32 = _IOWR('W', 0x20, struct sndrv_rawmidi_status32),
+};
+
+static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
+{
+       snd_rawmidi_file_t *rfile;
+       void __user *argp = compat_ptr(arg);
+
+       rfile = file->private_data;
+       switch (cmd) {
+       case SNDRV_RAWMIDI_IOCTL_PVERSION:
+       case SNDRV_RAWMIDI_IOCTL_INFO:
+       case SNDRV_RAWMIDI_IOCTL_DROP:
+       case SNDRV_RAWMIDI_IOCTL_DRAIN:
+               return snd_rawmidi_ioctl(file, cmd, (unsigned long)argp);
+       case SNDRV_RAWMIDI_IOCTL_PARAMS32:
+               return snd_rawmidi_ioctl_params_compat(rfile, argp);
+       case SNDRV_RAWMIDI_IOCTL_STATUS32:
+               return snd_rawmidi_ioctl_status_compat(rfile, argp);
+       }
+       return -ENOIOCTLCMD;
+}
diff --git a/sound/core/seq/seq_compat.c b/sound/core/seq/seq_compat.c
new file mode 100644 (file)
index 0000000..902ad8b
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ *   32bit -> 64bit ioctl wrapper for sequencer API
+ *   Copyright (c) by Takashi Iwai <tiwai@suse.de>
+ *
+ *   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
+ *
+ */
+
+/* This file included from seq.c */
+
+#include <linux/compat.h>
+
+struct sndrv_seq_port_info32 {
+       struct sndrv_seq_addr addr;     /* client/port numbers */
+       char name[64];                  /* port name */
+
+       u32 capability; /* port capability bits */
+       u32 type;               /* port type bits */
+       s32 midi_channels;              /* channels per MIDI port */
+       s32 midi_voices;                /* voices per MIDI port */
+       s32 synth_voices;               /* voices per SYNTH port */
+
+       s32 read_use;                   /* R/O: subscribers for output (from this port) */
+       s32 write_use;                  /* R/O: subscribers for input (to this port) */
+
+       u32 kernel;                     /* reserved for kernel use (must be NULL) */
+       u32 flags;              /* misc. conditioning */
+       unsigned char time_queue;       /* queue # for timestamping */
+       char reserved[59];              /* for future use */
+};
+
+static int snd_seq_call_port_info_ioctl(client_t *client, unsigned int cmd,
+                                       struct sndrv_seq_port_info32 __user *data32)
+{
+       int err = -EFAULT;
+       snd_seq_port_info_t *data;
+       mm_segment_t fs;
+
+       data = kmalloc(sizeof(*data), GFP_KERNEL);
+       if (! data)
+               return -ENOMEM;
+
+       if (copy_from_user(data, data32, sizeof(*data32)) ||
+           get_user(data->flags, &data32->flags) ||
+           get_user(data->time_queue, &data32->time_queue))
+               goto error;
+       data->kernel = NULL;
+
+       fs = snd_enter_user();
+       err = snd_seq_do_ioctl(client, cmd, data);
+       snd_leave_user(fs);
+       if (err < 0)
+               goto error;
+
+       if (copy_to_user(data32, data, sizeof(*data32)) ||
+           put_user(data->flags, &data32->flags) ||
+           put_user(data->time_queue, &data32->time_queue))
+               err = -EFAULT;
+
+ error:
+       kfree(data);
+       return err;
+}
+
+
+
+/*
+ */
+
+enum {
+       SNDRV_SEQ_IOCTL_CREATE_PORT32 = _IOWR('S', 0x20, struct sndrv_seq_port_info32),
+       SNDRV_SEQ_IOCTL_DELETE_PORT32 = _IOW ('S', 0x21, struct sndrv_seq_port_info32),
+       SNDRV_SEQ_IOCTL_GET_PORT_INFO32 = _IOWR('S', 0x22, struct sndrv_seq_port_info32),
+       SNDRV_SEQ_IOCTL_SET_PORT_INFO32 = _IOW ('S', 0x23, struct sndrv_seq_port_info32),
+       SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT32 = _IOWR('S', 0x52, struct sndrv_seq_port_info32),
+};
+
+static long snd_seq_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
+{
+       client_t *client = (client_t *) file->private_data;
+       void __user *argp = compat_ptr(arg);
+
+       snd_assert(client != NULL, return -ENXIO);
+
+       switch (cmd) {
+       case SNDRV_SEQ_IOCTL_PVERSION:
+       case SNDRV_SEQ_IOCTL_CLIENT_ID:
+       case SNDRV_SEQ_IOCTL_SYSTEM_INFO:
+       case SNDRV_SEQ_IOCTL_GET_CLIENT_INFO:
+       case SNDRV_SEQ_IOCTL_SET_CLIENT_INFO:
+       case SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT:
+       case SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT:
+       case SNDRV_SEQ_IOCTL_CREATE_QUEUE:
+       case SNDRV_SEQ_IOCTL_DELETE_QUEUE:
+       case SNDRV_SEQ_IOCTL_GET_QUEUE_INFO:
+       case SNDRV_SEQ_IOCTL_SET_QUEUE_INFO:
+       case SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE:
+       case SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS:
+       case SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO:
+       case SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO:
+       case SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER:
+       case SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER:
+       case SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT:
+       case SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT:
+       case SNDRV_SEQ_IOCTL_GET_CLIENT_POOL:
+       case SNDRV_SEQ_IOCTL_SET_CLIENT_POOL:
+       case SNDRV_SEQ_IOCTL_REMOVE_EVENTS:
+       case SNDRV_SEQ_IOCTL_QUERY_SUBS:
+       case SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION:
+       case SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT:
+       case SNDRV_SEQ_IOCTL_RUNNING_MODE:
+               return snd_seq_do_ioctl(client, cmd, argp);
+       case SNDRV_SEQ_IOCTL_CREATE_PORT32:
+               return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_CREATE_PORT, argp);
+       case SNDRV_SEQ_IOCTL_DELETE_PORT32:
+               return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_DELETE_PORT, argp);
+       case SNDRV_SEQ_IOCTL_GET_PORT_INFO32:
+               return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_GET_PORT_INFO, argp);
+       case SNDRV_SEQ_IOCTL_SET_PORT_INFO32:
+               return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_SET_PORT_INFO, argp);
+       case SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT32:
+               return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT, argp);
+       }
+       return -ENOIOCTLCMD;
+}
diff --git a/sound/core/timer_compat.c b/sound/core/timer_compat.c
new file mode 100644 (file)
index 0000000..9fbc395
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ *   32bit -> 64bit ioctl wrapper for timer API
+ *   Copyright (c) by Takashi Iwai <tiwai@suse.de>
+ *
+ *   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
+ *
+ */
+
+/* This file included from timer.c */
+
+#include <linux/compat.h>
+
+struct sndrv_timer_info32 {
+       u32 flags;
+       s32 card;
+       unsigned char id[64];
+       unsigned char name[80];
+       u32 reserved0;
+       u32 resolution;
+       unsigned char reserved[64];
+};
+
+static int snd_timer_user_info_compat(struct file *file,
+                                     struct sndrv_timer_info32 __user *_info)
+{
+       snd_timer_user_t *tu;
+       struct sndrv_timer_info32 info;
+       snd_timer_t *t;
+
+       tu = file->private_data;
+       snd_assert(tu->timeri != NULL, return -ENXIO);
+       t = tu->timeri->timer;
+       snd_assert(t != NULL, return -ENXIO);
+       memset(&info, 0, sizeof(info));
+       info.card = t->card ? t->card->number : -1;
+       if (t->hw.flags & SNDRV_TIMER_HW_SLAVE)
+               info.flags |= SNDRV_TIMER_FLG_SLAVE;
+       strlcpy(info.id, t->id, sizeof(info.id));
+       strlcpy(info.name, t->name, sizeof(info.name));
+       info.resolution = t->hw.resolution;
+       if (copy_to_user(_info, &info, sizeof(*_info)))
+               return -EFAULT;
+       return 0;
+}
+
+struct sndrv_timer_status32 {
+       struct compat_timespec tstamp;
+       u32 resolution;
+       u32 lost;
+       u32 overrun;
+       u32 queue;
+       unsigned char reserved[64];
+};
+
+static int snd_timer_user_status_compat(struct file *file,
+                                       struct sndrv_timer_status32 __user *_status)
+{
+       snd_timer_user_t *tu;
+       snd_timer_status_t status;
+       
+       tu = file->private_data;
+       snd_assert(tu->timeri != NULL, return -ENXIO);
+       memset(&status, 0, sizeof(status));
+       status.tstamp = tu->tstamp;
+       status.resolution = snd_timer_resolution(tu->timeri);
+       status.lost = tu->timeri->lost;
+       status.overrun = tu->overrun;
+       spin_lock_irq(&tu->qlock);
+       status.queue = tu->qused;
+       spin_unlock_irq(&tu->qlock);
+       if (copy_to_user(_status, &status, sizeof(status)))
+               return -EFAULT;
+       return 0;
+}
+
+/*
+ */
+
+enum {
+       SNDRV_TIMER_IOCTL_INFO32 = _IOR('T', 0x11, struct sndrv_timer_info32),
+       SNDRV_TIMER_IOCTL_STATUS32 = _IOW('T', 0x14, struct sndrv_timer_status32),
+};
+
+static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
+{
+       void __user *argp = compat_ptr(arg);
+
+       switch (cmd) {
+       case SNDRV_TIMER_IOCTL_PVERSION:
+       case SNDRV_TIMER_IOCTL_TREAD:
+       case SNDRV_TIMER_IOCTL_GINFO:
+       case SNDRV_TIMER_IOCTL_GPARAMS:
+       case SNDRV_TIMER_IOCTL_GSTATUS:
+       case SNDRV_TIMER_IOCTL_SELECT:
+       case SNDRV_TIMER_IOCTL_PARAMS:
+       case SNDRV_TIMER_IOCTL_START:
+       case SNDRV_TIMER_IOCTL_STOP:
+       case SNDRV_TIMER_IOCTL_CONTINUE:
+       case SNDRV_TIMER_IOCTL_NEXT_DEVICE:
+               return snd_timer_user_ioctl(file, cmd, (unsigned long)argp);
+       case SNDRV_TIMER_IOCTL_INFO32:
+               return snd_timer_user_info_compat(file, argp);
+       case SNDRV_TIMER_IOCTL_STATUS32:
+               return snd_timer_user_status_compat(file, argp);
+       }
+       return -ENOIOCTLCMD;
+}
diff --git a/sound/parisc/harmony.h b/sound/parisc/harmony.h
new file mode 100644 (file)
index 0000000..ef77f9a
--- /dev/null
@@ -0,0 +1,151 @@
+/* Hewlett-Packard Harmony audio driver
+ * Copyright (C) 2004, Kyle McMartin <kyle@parisc-linux.org>
+ */
+
+#ifndef __HARMONY_H__
+#define __HARMONY_H__
+
+struct harmony_buffer {
+        unsigned long addr;
+        int buf;
+        int count;
+        int size;
+        int coherent;
+};
+
+typedef struct snd_card_harmony {
+        int irq;
+
+        unsigned long hpa; /* hard physical address */
+        void __iomem *iobase; /* remapped io address */
+
+        struct parisc_device *dev;
+
+        struct {
+                u32 gain;
+                u32 rate;
+                u32 format;
+                u32 stereo;
+               int playing;
+               int capturing;
+        } st;
+
+        struct snd_dma_device dma; /* playback/capture */
+        struct harmony_buffer pbuf;
+       struct harmony_buffer cbuf;
+
+        struct snd_dma_buffer gdma; /* graveyard */
+        struct snd_dma_buffer sdma; /* silence */
+
+        struct {
+                unsigned long play_intr;
+               unsigned long rec_intr;
+                unsigned long graveyard_intr;
+                unsigned long silence_intr;
+        } stats;
+
+        snd_pcm_t *pcm;
+        snd_card_t *card;
+        snd_pcm_substream_t *psubs;
+       snd_pcm_substream_t *csubs;
+        snd_info_entry_t *proc;
+
+        spinlock_t lock;
+        spinlock_t mixer_lock;
+} harmony_t;
+
+#define MAX_PCM_DEVICES     1
+#define MAX_PCM_SUBSTREAMS  4
+#define MAX_MIDI_DEVICES    0
+
+#define HARMONY_SIZE       64
+
+#define BUF_SIZE     PAGE_SIZE
+#define MAX_BUFS     10
+#define MAX_BUF_SIZE (MAX_BUFS * BUF_SIZE)
+
+#define PLAYBACK_BUFS    MAX_BUFS
+#define RECORD_BUFS      MAX_BUFS
+#define GRAVEYARD_BUFS   1
+#define GRAVEYARD_BUFSZ  (GRAVEYARD_BUFS*BUF_SIZE)
+#define SILENCE_BUFS     1
+#define SILENCE_BUFSZ    (SILENCE_BUFS*BUF_SIZE)
+
+#define HARMONY_ID       0x000
+#define HARMONY_RESET    0x004
+#define HARMONY_CNTL     0x008
+#define HARMONY_GAINCTL  0x00c
+#define HARMONY_PNXTADD  0x010
+#define HARMONY_PCURADD  0x014
+#define HARMONY_RNXTADD  0x018
+#define HARMONY_RCURADD  0x01c
+#define HARMONY_DSTATUS  0x020
+#define HARMONY_OV       0x024
+#define HARMONY_PIO      0x028
+#define HARMONY_DIAG     0x03c
+
+#define HARMONY_CNTL_C          0x80000000
+#define HARMONY_CNTL_ST         0x00000020
+#define HARMONY_CNTL_44100      0x00000015      /* HARMONY_SR_44KHZ */
+#define HARMONY_CNTL_8000       0x00000008      /* HARMONY_SR_8KHZ */
+
+#define HARMONY_DSTATUS_ID      0x00000000 /* interrupts off */
+#define HARMONY_DSTATUS_PN      0x00000200 /* playback fill */
+#define HARMONY_DSTATUS_RN      0x00000002 /* record fill */
+#define HARMONY_DSTATUS_IE      0x80000000 /* interrupts on */
+
+#define HARMONY_DF_16BIT_LINEAR 0x00000000
+#define HARMONY_DF_8BIT_ULAW    0x00000001
+#define HARMONY_DF_8BIT_ALAW    0x00000002
+
+#define HARMONY_SS_MONO         0x00000000
+#define HARMONY_SS_STEREO       0x00000001
+
+#define HARMONY_GAIN_SILENCE    0x00F00FFF
+#define HARMONY_GAIN_DEFAULT    0x0FF00000
+
+#define HARMONY_GAIN_HE_SHIFT   27
+#define HARMONY_GAIN_HE_MASK    (1 << HARMONY_GAIN_HE_SHIFT)
+#define HARMONY_GAIN_LE_SHIFT   26
+#define HARMONY_GAIN_LE_MASK    (1 << HARMONY_GAIN_LE_SHIFT)
+#define HARMONY_GAIN_SE_SHIFT   25
+#define HARMONY_GAIN_SE_MASK    (1 << HARMONY_GAIN_SE_SHIFT)
+#define HARMONY_GAIN_IS_SHIFT   24
+#define HARMONY_GAIN_IS_MASK    (1 << HARMONY_GAIN_IS_SHIFT)
+
+#define HARMONY_GAIN_MA         0x0f
+#define HARMONY_GAIN_MA_SHIFT   20
+#define HARMONY_GAIN_MA_MASK    (HARMONY_GAIN_MA << HARMONY_GAIN_MA_SHIFT)
+
+#define HARMONY_GAIN_IN         0x0f
+#define HARMONY_GAIN_LI_SHIFT   16
+#define HARMONY_GAIN_LI_MASK    (HARMONY_GAIN_IN << HARMONY_GAIN_LI_SHIFT)
+#define HARMONY_GAIN_RI_SHIFT   12
+#define HARMONY_GAIN_RI_MASK    (HARMONY_GAIN_IN << HARMONY_GAIN_RI_SHIFT)
+
+#define HARMONY_GAIN_OUT        0x3f
+#define HARMONY_GAIN_LO_SHIFT   6
+#define HARMONY_GAIN_LO_MASK    (HARMONY_GAIN_OUT << HARMONY_GAIN_LO_SHIFT)
+#define HARMONY_GAIN_RO_SHIFT   0
+#define HARMONY_GAIN_RO_MASK    (HARMONY_GAIN_OUT << HARMONY_GAIN_RO_SHIFT)
+
+#define HARMONY_MAX_OUT (HARMONY_GAIN_RO_MASK >> HARMONY_GAIN_RO_SHIFT)
+#define HARMONY_MAX_IN  (HARMONY_GAIN_RI_MASK >> HARMONY_GAIN_RI_SHIFT)
+#define HARMONY_MAX_MON (HARMONY_GAIN_MA_MASK >> HARMONY_GAIN_MA_SHIFT)
+
+#define HARMONY_SR_8KHZ         0x08
+#define HARMONY_SR_16KHZ        0x09
+#define HARMONY_SR_27KHZ        0x0A
+#define HARMONY_SR_32KHZ        0x0B
+#define HARMONY_SR_48KHZ        0x0E
+#define HARMONY_SR_9KHZ         0x0F
+#define HARMONY_SR_5KHZ         0x10
+#define HARMONY_SR_11KHZ        0x11
+#define HARMONY_SR_18KHZ        0x12
+#define HARMONY_SR_22KHZ        0x13
+#define HARMONY_SR_37KHZ        0x14
+#define HARMONY_SR_44KHZ        0x15
+#define HARMONY_SR_33KHZ        0x16
+#define HARMONY_SR_6KHZ         0x17
+
+#endif /* __HARMONY_H__ */
diff --git a/sound/pci/emu10k1/p16v.h b/sound/pci/emu10k1/p16v.h
new file mode 100644 (file)
index 0000000..1532149
--- /dev/null
@@ -0,0 +1,299 @@
+/*
+ *  Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk>
+ *  Driver p16v chips
+ *  Version: 0.21
+ *
+ *  FEATURES currently supported:
+ *    Output fixed at S32_LE, 2 channel to hw:0,0
+ *    Rates: 44.1, 48, 96, 192.
+ *
+ *  Changelog:
+ *  0.8
+ *    Use separate card based buffer for periods table.
+ *  0.9
+ *    Use 2 channel output streams instead of 8 channel.
+ *       (8 channel output streams might be good for ASIO type output)
+ *    Corrected speaker output, so Front -> Front etc.
+ *  0.10
+ *    Fixed missed interrupts.
+ *  0.11
+ *    Add Sound card model number and names.
+ *    Add Analog volume controls.
+ *  0.12
+ *    Corrected playback interrupts. Now interrupt per period, instead of half period.
+ *  0.13
+ *    Use single trigger for multichannel.
+ *  0.14
+ *    Mic capture now works at fixed: S32_LE, 96000Hz, Stereo.
+ *  0.15
+ *    Force buffer_size / period_size == INTEGER.
+ *  0.16
+ *    Update p16v.c to work with changed alsa api.
+ *  0.17
+ *    Update p16v.c to work with changed alsa api. Removed boot_devs.
+ *  0.18
+ *    Merging with snd-emu10k1 driver.
+ *  0.19
+ *    One stereo channel at 24bit now works.
+ *  0.20
+ *    Added better register defines.
+ *  0.21
+ *    Split from p16v.c
+ *
+ *
+ *  BUGS:
+ *    Some stability problems when unloading the snd-p16v kernel module.
+ *    --
+ *
+ *  TODO:
+ *    SPDIF out.
+ *    Find out how to change capture sample rates. E.g. To record SPDIF at 48000Hz.
+ *    Currently capture fixed at 48000Hz.
+ *
+ *    --
+ *  GENERAL INFO:
+ *    Model: SB0240
+ *    P16V Chip: CA0151-DBS
+ *    Audigy 2 Chip: CA0102-IAT
+ *    AC97 Codec: STAC 9721
+ *    ADC: Philips 1361T (Stereo 24bit)
+ *    DAC: CS4382-K (8-channel, 24bit, 192Khz)
+ *
+ *  This code was initally based on code from ALSA's emu10k1x.c which is:
+ *  Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+/********************************************************************************************************/
+/* Audigy2 P16V pointer-offset register set, accessed through the PTR2 and DATA2 registers                     */
+/********************************************************************************************************/
+                                                                                                                           
+/* The sample rate of the SPDIF outputs is set by modifying a register in the EMU10K2 PTR register A_SPDIF_SAMPLERATE.
+ * The sample rate is also controlled by the same registers that control the rate of the EMU10K2 sample rate converters.
+ */
+
+/* Initally all registers from 0x00 to 0x3f have zero contents. */
+#define PLAYBACK_LIST_ADDR     0x00            /* Base DMA address of a list of pointers to each period/size */
+                                               /* One list entry: 4 bytes for DMA address, 
+                                                * 4 bytes for period_size << 16.
+                                                * One list entry is 8 bytes long.
+                                                * One list entry for each period in the buffer.
+                                                */
+#define PLAYBACK_LIST_SIZE     0x01            /* Size of list in bytes << 16. E.g. 8 periods -> 0x00380000  */
+#define PLAYBACK_LIST_PTR      0x02            /* Pointer to the current period being played */
+#define PLAYBACK_UNKNOWN3      0x03            /* Not used */
+#define PLAYBACK_DMA_ADDR      0x04            /* Playback DMA addresss */
+#define PLAYBACK_PERIOD_SIZE   0x05            /* Playback period size. win2000 uses 0x04000000 */
+#define PLAYBACK_POINTER       0x06            /* Playback period pointer. Used with PLAYBACK_LIST_PTR to determine buffer position currently in DAC */
+#define PLAYBACK_FIFO_END_ADDRESS      0x07            /* Playback FIFO end address */
+#define PLAYBACK_FIFO_POINTER  0x08            /* Playback FIFO pointer and number of valid sound samples in cache */
+#define PLAYBACK_UNKNOWN9      0x09            /* Not used */
+#define CAPTURE_DMA_ADDR       0x10            /* Capture DMA address */
+#define CAPTURE_BUFFER_SIZE    0x11            /* Capture buffer size */
+#define CAPTURE_POINTER                0x12            /* Capture buffer pointer. Sample currently in ADC */
+#define CAPTURE_FIFO_POINTER   0x13            /* Capture FIFO pointer and number of valid sound samples in cache */
+#define CAPTURE_P16V_VOLUME1   0x14            /* Low: Capture volume 0xXXXX3030 */
+#define CAPTURE_P16V_VOLUME2   0x15            /* High:Has no effect on capture volume */
+#define CAPTURE_P16V_SOURCE     0x16            /* P16V source select. Set to 0x0700E4E5 for AC97 CAPTURE */
+                                               /* [0:1] Capture input 0 channel select. 0 = Capture output 0.
+                                                *                                       1 = Capture output 1.
+                                                *                                       2 = Capture output 2.
+                                                *                                       3 = Capture output 3.
+                                                * [3:2] Capture input 1 channel select. 0 = Capture output 0.
+                                                *                                       1 = Capture output 1.
+                                                *                                       2 = Capture output 2.
+                                                *                                       3 = Capture output 3.
+                                                * [5:4] Capture input 2 channel select. 0 = Capture output 0.
+                                                *                                       1 = Capture output 1.
+                                                *                                       2 = Capture output 2.
+                                                *                                       3 = Capture output 3.
+                                                * [7:6] Capture input 3 channel select. 0 = Capture output 0.
+                                                *                                       1 = Capture output 1.
+                                                *                                       2 = Capture output 2.
+                                                *                                       3 = Capture output 3.
+                                                * [9:8] Playback input 0 channel select. 0 = Play output 0.
+                                                *                                        1 = Play output 1.
+                                                *                                        2 = Play output 2.
+                                                *                                        3 = Play output 3.
+                                                * [11:10] Playback input 1 channel select. 0 = Play output 0.
+                                                *                                          1 = Play output 1.
+                                                *                                          2 = Play output 2.
+                                                *                                          3 = Play output 3.
+                                                * [13:12] Playback input 2 channel select. 0 = Play output 0.
+                                                *                                          1 = Play output 1.
+                                                *                                          2 = Play output 2.
+                                                *                                          3 = Play output 3.
+                                                * [15:14] Playback input 3 channel select. 0 = Play output 0.
+                                                *                                          1 = Play output 1.
+                                                *                                          2 = Play output 2.
+                                                *                                          3 = Play output 3.
+                                                * [19:16] Playback mixer output enable. 1 bit per channel.
+                                                * [23:20] Capture mixer output enable. 1 bit per channel.
+                                                * [26:24] FX engine channel capture 0 = 0x60-0x67.
+                                                *                                   1 = 0x68-0x6f.
+                                                *                                   2 = 0x70-0x77.
+                                                *                                   3 = 0x78-0x7f.
+                                                *                                   4 = 0x80-0x87.
+                                                *                                   5 = 0x88-0x8f.
+                                                *                                   6 = 0x90-0x97.
+                                                *                                   7 = 0x98-0x9f.
+                                                * [31:27] Not used.
+                                                */
+
+                                               /* 0x1 = capture on.
+                                                * 0x100 = capture off.
+                                                * 0x200 = capture off.
+                                                * 0x1000 = capture off.
+                                                */
+#define CAPTURE_RATE_STATUS            0x17            /* Capture sample rate. Read only */
+                                               /* [15:0] Not used.
+                                                * [18:16] Channel 0 Detected sample rate. 0 - 44.1khz
+                                                *                               1 - 48 khz
+                                                *                               2 - 96 khz
+                                                *                               3 - 192 khz
+                                                *                               7 - undefined rate.
+                                                * [19] Channel 0. 1 - Valid, 0 - Not Valid.
+                                                * [22:20] Channel 1 Detected sample rate. 
+                                                * [23] Channel 1. 1 - Valid, 0 - Not Valid.
+                                                * [26:24] Channel 2 Detected sample rate. 
+                                                * [27] Channel 2. 1 - Valid, 0 - Not Valid.
+                                                * [30:28] Channel 3 Detected sample rate. 
+                                                * [31] Channel 3. 1 - Valid, 0 - Not Valid.
+                                                */
+/* 0x18 - 0x1f unused */
+#define PLAYBACK_LAST_SAMPLE    0x20           /* The sample currently being played. Read only */
+/* 0x21 - 0x3f unused */
+#define BASIC_INTERRUPT         0x40           /* Used by both playback and capture interrupt handler */
+                                               /* Playback (0x1<<channel_id) Don't touch high 16bits. */
+                                               /* Capture  (0x100<<channel_id). not tested */
+                                               /* Start Playback [3:0] (one bit per channel)
+                                                * Start Capture [11:8] (one bit per channel)
+                                                * Record source select for channel 0 [18:16]
+                                                * Record source select for channel 1 [22:20]
+                                                * Record source select for channel 2 [26:24]
+                                                * Record source select for channel 3 [30:28]
+                                                * 0 - SPDIF channel.
+                                                * 1 - I2S channel.
+                                                * 2 - SRC48 channel.
+                                                * 3 - SRCMulti_SPDIF channel.
+                                                * 4 - SRCMulti_I2S channel.
+                                                * 5 - SPDIF channel.
+                                                * 6 - fxengine capture.
+                                                * 7 - AC97 capture.
+                                                */
+                                               /* Default 41110000.
+                                                * Writing 0xffffffff hangs the PC.
+                                                * Writing 0xffff0000 -> 77770000 so it must be some sort of route.
+                                                * bit 0x1 starts DMA playback on channel_id 0
+                                                */
+/* 0x41,42 take values from 0 - 0xffffffff, but have no effect on playback */
+/* 0x43,0x48 do not remember settings */
+/* 0x41-45 unused */
+#define WATERMARK            0x46              /* Test bit to indicate cache level usage */
+                                               /* Values it can have while playing on channel 0. 
+                                                * 0000f000, 0000f004, 0000f008, 0000f00c.
+                                                * Readonly.
+                                                */
+/* 0x47-0x4f unused */
+/* 0x50-0x5f Capture cache data */
+#define SRCSel                 0x60            /* SRCSel. Default 0x4. Bypass P16V 0x14 */
+                                               /* [0] 0 = 10K2 audio, 1 = SRC48 mixer output.
+                                                * [2] 0 = 10K2 audio, 1 = SRCMulti SPDIF mixer output.
+                                                * [4] 0 = 10K2 audio, 1 = SRCMulti I2S mixer output.
+                                                */
+                                               /* SRC48 converts samples rates 44.1, 48, 96, 192 to 48 khz. */
+                                               /* SRCMulti converts 48khz samples rates to 44.1, 48, 96, 192 to 48. */
+                                               /* SRC48 and SRCMULTI sample rate select and output select. */
+                                               /* 0xffffffff -> 0xC0000015
+                                                * 0xXXXXXXX4 = Enable Front Left/Right
+                                                * Enable PCMs
+                                                */
+
+/* 0x61 -> 0x6c are Volume controls */
+#define PLAYBACK_VOLUME_MIXER1  0x61           /* SRC48 Low to mixer input volume control. */
+#define PLAYBACK_VOLUME_MIXER2  0x62           /* SRC48 High to mixer input volume control. */
+#define PLAYBACK_VOLUME_MIXER3  0x63           /* SRCMULTI SPDIF Low to mixer input volume control. */
+#define PLAYBACK_VOLUME_MIXER4  0x64           /* SRCMULTI SPDIF High to mixer input volume control. */
+#define PLAYBACK_VOLUME_MIXER5  0x65           /* SRCMULTI I2S Low to mixer input volume control. */
+#define PLAYBACK_VOLUME_MIXER6  0x66           /* SRCMULTI I2S High to mixer input volume control. */
+#define PLAYBACK_VOLUME_MIXER7  0x67           /* P16V Low to SRCMULTI SPDIF mixer input volume control. */
+#define PLAYBACK_VOLUME_MIXER8  0x68           /* P16V High to SRCMULTI SPDIF mixer input volume control. */
+#define PLAYBACK_VOLUME_MIXER9  0x69           /* P16V Low to SRCMULTI I2S mixer input volume control. */
+                                               /* 0xXXXX3030 = PCM0 Volume (Front).
+                                                * 0x3030XXXX = PCM1 Volume (Center)
+                                                */
+#define PLAYBACK_VOLUME_MIXER10  0x6a          /* P16V High to SRCMULTI I2S mixer input volume control. */
+                                               /* 0x3030XXXX = PCM3 Volume (Rear). */
+#define PLAYBACK_VOLUME_MIXER11  0x6b          /* E10K2 Low to SRC48 mixer input volume control. */
+#define PLAYBACK_VOLUME_MIXER12 0x6c           /* E10K2 High to SRC48 mixer input volume control. */
+
+#define SRC48_ENABLE            0x6d            /* SRC48 input audio enable */
+                                               /* SRC48 converts samples rates 44.1, 48, 96, 192 to 48 khz. */
+                                               /* [23:16] The corresponding P16V channel to SRC48 enabled if == 1.
+                                                * [31:24] The corresponding E10K2 channel to SRC48 enabled.
+                                                */
+#define SRCMULTI_ENABLE         0x6e            /* SRCMulti input audio enable. Default 0xffffffff */
+                                               /* SRCMulti converts 48khz samples rates to 44.1, 48, 96, 192 to 48. */
+                                               /* [7:0] The corresponding P16V channel to SRCMulti_I2S enabled if == 1.
+                                                * [15:8] The corresponding E10K2 channel to SRCMulti I2S enabled.
+                                                * [23:16] The corresponding P16V channel to SRCMulti SPDIF enabled.
+                                                * [31:24] The corresponding E10K2 channel to SRCMulti SPDIF enabled.
+                                                */
+                                               /* Bypass P16V 0xff00ff00 
+                                                * Bitmap. 0 = Off, 1 = On.
+                                                * P16V playback outputs:
+                                                * 0xXXXXXXX1 = PCM0 Left. (Front)
+                                                * 0xXXXXXXX2 = PCM0 Right.
+                                                * 0xXXXXXXX4 = PCM1 Left. (Center/LFE)
+                                                * 0xXXXXXXX8 = PCM1 Right.
+                                                * 0xXXXXXX1X = PCM2 Left. (Unknown)
+                                                * 0xXXXXXX2X = PCM2 Right.
+                                                * 0xXXXXXX4X = PCM3 Left. (Rear)
+                                                * 0xXXXXXX8X = PCM3 Right.
+                                                */
+#define AUDIO_OUT_ENABLE        0x6f            /* Default: 000100FF */
+                                               /* [3:0] Does something, but not documented. Probably capture enable.
+                                                * [7:4] Playback channels enable. not documented.
+                                                * [16] AC97 output enable if == 1
+                                                * [30] 0 = SRCMulti_I2S input from fxengine 0x68-0x6f.
+                                                *      1 = SRCMulti_I2S input from SRC48 output.
+                                                * [31] 0 = SRCMulti_SPDIF input from fxengine 0x60-0x67.
+                                                *      1 = SRCMulti_SPDIF input from SRC48 output.
+                                                */
+                                               /* 0xffffffff -> C00100FF */
+                                               /* 0 -> Not playback sound, irq still running */
+                                               /* 0xXXXXXX10 = PCM0 Left/Right On. (Front)
+                                                * 0xXXXXXX20 = PCM1 Left/Right On. (Center/LFE)
+                                                * 0xXXXXXX40 = PCM2 Left/Right On. (Unknown)
+                                                * 0xXXXXXX80 = PCM3 Left/Right On. (Rear)
+                                                */
+#define PLAYBACK_SPDIF_SELECT     0x70          /* Default: 12030F00 */
+                                               /* 0xffffffff -> 3FF30FFF */
+                                               /* 0x00000001 pauses stream/irq fail. */
+                                               /* All other bits do not effect playback */
+#define PLAYBACK_SPDIF_SRC_SELECT 0x71          /* Default: 0000E4E4 */
+                                               /* 0xffffffff -> F33FFFFF */
+                                               /* All bits do not effect playback */
+#define PLAYBACK_SPDIF_USER_DATA0 0x72         /* SPDIF out user data 0 */
+#define PLAYBACK_SPDIF_USER_DATA1 0x73         /* SPDIF out user data 1 */
+/* 0x74-0x75 unknown */
+#define CAPTURE_SPDIF_CONTROL  0x76            /* SPDIF in control setting */
+#define CAPTURE_SPDIF_STATUS   0x77            /* SPDIF in status */
+#define CAPURE_SPDIF_USER_DATA0 0x78           /* SPDIF in user data 0 */
+#define CAPURE_SPDIF_USER_DATA1 0x79           /* SPDIF in user data 1 */
+#define CAPURE_SPDIF_USER_DATA2 0x7a           /* SPDIF in user data 2 */
+
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c
new file mode 100644 (file)
index 0000000..b7cc8e4
--- /dev/null
@@ -0,0 +1,621 @@
+/*
+ * Universal Interface for Intel High Definition Audio Codec
+ *
+ * HD audio interface patch for C-Media CMI9880
+ *
+ * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
+ *
+ *
+ *  This driver 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 driver 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 <sound/driver.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <sound/core.h>
+#include "hda_codec.h"
+#include "hda_local.h"
+
+
+/* board config type */
+enum {
+       CMI_MINIMAL,    /* back 3-jack */
+       CMI_MIN_FP,     /* back 3-jack + front-panel 2-jack */
+       CMI_FULL,       /* back 6-jack + front-panel 2-jack */
+       CMI_FULL_DIG,   /* back 6-jack + front-panel 2-jack + digital I/O */
+       CMI_ALLOUT,     /* back 5-jack + front-panel 2-jack + digital out */
+};
+
+struct cmi_spec {
+       int board_config;
+       unsigned int surr_switch: 1;    /* switchable line,mic */
+       unsigned int no_line_in: 1;     /* no line-in (5-jack) */
+       unsigned int front_panel: 1;    /* has front-panel 2-jack */
+
+       /* playback */
+       struct hda_multi_out multiout;
+
+       /* capture */
+       hda_nid_t *adc_nids;
+       hda_nid_t dig_in_nid;
+
+       /* capture source */
+       const struct hda_input_mux *input_mux;
+       unsigned int cur_mux[2];
+
+       /* channel mode */
+       unsigned int num_ch_modes;
+       unsigned int cur_ch_mode;
+       const struct cmi_channel_mode *channel_modes;
+
+       struct hda_pcm pcm_rec[2];      /* PCM information */
+};
+
+/*
+ * input MUX
+ */
+static int cmi_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct cmi_spec *spec = codec->spec;
+       return snd_hda_input_mux_info(spec->input_mux, uinfo);
+}
+
+static int cmi_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct cmi_spec *spec = codec->spec;
+       unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+
+       ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
+       return 0;
+}
+
+static int cmi_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct cmi_spec *spec = codec->spec;
+       unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+
+       return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
+                                    spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]);
+}
+
+/*
+ * shared line-in, mic for surrounds
+ */
+
+/* 3-stack / 2 channel */
+static struct hda_verb cmi9880_ch2_init[] = {
+       /* set line-in PIN for input */
+       { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+       /* set mic PIN for input, also enable vref */
+       { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+       /* route front PCM (DAC1) to HP */
+       { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
+       {}
+};
+
+/* 3-stack / 6 channel */
+static struct hda_verb cmi9880_ch6_init[] = {
+       /* set line-in PIN for output */
+       { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+       /* set mic PIN for output */
+       { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+       /* route front PCM (DAC1) to HP */
+       { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
+       {}
+};
+
+/* 3-stack+front / 8 channel */
+static struct hda_verb cmi9880_ch8_init[] = {
+       /* set line-in PIN for output */
+       { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+       /* set mic PIN for output */
+       { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+       /* route rear-surround PCM (DAC4) to HP */
+       { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x03 },
+       {}
+};
+
+struct cmi_channel_mode {
+       unsigned int channels;
+       const struct hda_verb *sequence;
+};
+
+static struct cmi_channel_mode cmi9880_channel_modes[3] = {
+       { 2, cmi9880_ch2_init },
+       { 6, cmi9880_ch6_init },
+       { 8, cmi9880_ch8_init },
+};
+
+static int cmi_ch_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct cmi_spec *spec = codec->spec;
+
+       snd_assert(spec->channel_modes, return -EINVAL);
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+       uinfo->count = 1;
+       uinfo->value.enumerated.items = spec->num_ch_modes;
+       if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+               uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
+       sprintf(uinfo->value.enumerated.name, "%dch",
+               spec->channel_modes[uinfo->value.enumerated.item].channels);
+       return 0;
+}
+
+static int cmi_ch_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct cmi_spec *spec = codec->spec;
+
+       ucontrol->value.enumerated.item[0] = spec->cur_ch_mode;
+       return 0;
+}
+
+static int cmi_ch_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct cmi_spec *spec = codec->spec;
+
+       snd_assert(spec->channel_modes, return -EINVAL);
+       if (ucontrol->value.enumerated.item[0] >= spec->num_ch_modes)
+               ucontrol->value.enumerated.item[0] = spec->num_ch_modes;
+       if (ucontrol->value.enumerated.item[0] == spec->cur_ch_mode &&
+           ! codec->in_resume)
+               return 0;
+
+       spec->cur_ch_mode = ucontrol->value.enumerated.item[0];
+       snd_hda_sequence_write(codec, spec->channel_modes[spec->cur_ch_mode].sequence);
+       spec->multiout.max_channels = spec->channel_modes[spec->cur_ch_mode].channels;
+       return 1;
+}
+
+/*
+ */
+static snd_kcontrol_new_t cmi9880_basic_mixer[] = {
+       /* CMI9880 has no playback volumes! */
+       HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT), /* front */
+       HDA_CODEC_MUTE("Surround Playback Switch", 0x04, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Side Playback Switch", 0x06, 0x0, HDA_OUTPUT),
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               /* The multiple "Capture Source" controls confuse alsamixer
+                * So call somewhat different..
+                * FIXME: the controls appear in the "playback" view!
+                */
+               /* .name = "Capture Source", */
+               .name = "Input Source",
+               .count = 2,
+               .info = cmi_mux_enum_info,
+               .get = cmi_mux_enum_get,
+               .put = cmi_mux_enum_put,
+       },
+       HDA_CODEC_VOLUME("Capture Volume", 0x08, 0, HDA_INPUT),
+       HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0, HDA_INPUT),
+       HDA_CODEC_MUTE("Capture Switch", 0x08, 0, HDA_INPUT),
+       HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0, HDA_INPUT),
+       HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x23, 0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x23, 0, HDA_OUTPUT),
+       { } /* end */
+};
+
+/*
+ * shared I/O pins
+ */
+static snd_kcontrol_new_t cmi9880_ch_mode_mixer[] = {
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "Channel Mode",
+               .info = cmi_ch_mode_info,
+               .get = cmi_ch_mode_get,
+               .put = cmi_ch_mode_put,
+       },
+       { } /* end */
+};
+
+/* AUD-in selections:
+ * 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x1f 0x20
+ */
+static struct hda_input_mux cmi9880_basic_mux = {
+       .num_items = 4,
+       .items = {
+               { "Front Mic", 0x5 },
+               { "Rear Mic", 0x2 },
+               { "Line", 0x1 },
+               { "CD", 0x7 },
+       }
+};
+
+static struct hda_input_mux cmi9880_no_line_mux = {
+       .num_items = 3,
+       .items = {
+               { "Front Mic", 0x5 },
+               { "Rear Mic", 0x2 },
+               { "CD", 0x7 },
+       }
+};
+
+/* front, rear, clfe, rear_surr */
+static hda_nid_t cmi9880_dac_nids[4] = {
+       0x03, 0x04, 0x05, 0x06
+};
+/* ADC0, ADC1 */
+static hda_nid_t cmi9880_adc_nids[2] = {
+       0x08, 0x09
+};
+
+#define CMI_DIG_OUT_NID        0x07
+#define CMI_DIG_IN_NID 0x0a
+
+/*
+ */
+static struct hda_verb cmi9880_basic_init[] = {
+       /* port-D for line out (rear panel) */
+       { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+       /* port-E for HP out (front panel) */
+       { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+       /* route front PCM to HP */
+       { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
+       /* port-A for surround (rear panel) */
+       { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+       /* port-G for CLFE (rear panel) */
+       { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+       /* port-H for side (rear panel) */
+       { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+       /* port-C for line-in (rear panel) */
+       { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+       /* port-B for mic-in (rear panel) with vref */
+       { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+       /* port-F for mic-in (front panel) with vref */
+       { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+       /* CD-in */
+       { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+       /* route front mic to ADC1/2 */
+       { 0x08, AC_VERB_SET_CONNECT_SEL, 0x05 },
+       { 0x09, AC_VERB_SET_CONNECT_SEL, 0x05 },
+       {} /* terminator */
+};
+
+static struct hda_verb cmi9880_allout_init[] = {
+       /* port-D for line out (rear panel) */
+       { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+       /* port-E for HP out (front panel) */
+       { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+       /* route front PCM to HP */
+       { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
+       /* port-A for side (rear panel) */
+       { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+       /* port-G for CLFE (rear panel) */
+       { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+       /* port-C for surround (rear panel) */
+       { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+       /* port-B for mic-in (rear panel) with vref */
+       { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+       /* port-F for mic-in (front panel) with vref */
+       { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+       /* CD-in */
+       { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+       /* route front mic to ADC1/2 */
+       { 0x08, AC_VERB_SET_CONNECT_SEL, 0x05 },
+       { 0x09, AC_VERB_SET_CONNECT_SEL, 0x05 },
+       {} /* terminator */
+};
+
+/*
+ */
+static int cmi9880_build_controls(struct hda_codec *codec)
+{
+       struct cmi_spec *spec = codec->spec;
+       int err;
+
+       err = snd_hda_add_new_ctls(codec, cmi9880_basic_mixer);
+       if (err < 0)
+               return err;
+       if (spec->surr_switch) {
+               err = snd_hda_add_new_ctls(codec, cmi9880_ch_mode_mixer);
+               if (err < 0)
+                       return err;
+       }
+       if (spec->multiout.dig_out_nid) {
+               err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
+               if (err < 0)
+                       return err;
+       }
+       if (spec->dig_in_nid) {
+               err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
+               if (err < 0)
+                       return err;
+       }
+       return 0;
+}
+
+static int cmi9880_init(struct hda_codec *codec)
+{
+       struct cmi_spec *spec = codec->spec;
+       if (spec->board_config == CMI_ALLOUT)
+               snd_hda_sequence_write(codec, cmi9880_allout_init);
+       else
+               snd_hda_sequence_write(codec, cmi9880_basic_init);
+       return 0;
+}
+
+#ifdef CONFIG_PM
+/*
+ * resume
+ */
+static int cmi9880_resume(struct hda_codec *codec)
+{
+       struct cmi_spec *spec = codec->spec;
+
+       cmi9880_init(codec);
+       snd_hda_resume_ctls(codec, cmi9880_basic_mixer);
+       if (spec->surr_switch)
+               snd_hda_resume_ctls(codec, cmi9880_ch_mode_mixer);
+       if (spec->multiout.dig_out_nid)
+               snd_hda_resume_spdif_out(codec);
+       if (spec->dig_in_nid)
+               snd_hda_resume_spdif_in(codec);
+
+       return 0;
+}
+#endif
+
+/*
+ * Analog playback callbacks
+ */
+static int cmi9880_playback_pcm_open(struct hda_pcm_stream *hinfo,
+                                    struct hda_codec *codec,
+                                    snd_pcm_substream_t *substream)
+{
+       struct cmi_spec *spec = codec->spec;
+       return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
+}
+
+static int cmi9880_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
+                                       struct hda_codec *codec,
+                                       unsigned int stream_tag,
+                                       unsigned int format,
+                                       snd_pcm_substream_t *substream)
+{
+       struct cmi_spec *spec = codec->spec;
+       return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
+                                               format, substream);
+}
+
+static int cmi9880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
+                                      struct hda_codec *codec,
+                                      snd_pcm_substream_t *substream)
+{
+       struct cmi_spec *spec = codec->spec;
+       return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
+}
+
+/*
+ * Digital out
+ */
+static int cmi9880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
+                                        struct hda_codec *codec,
+                                        snd_pcm_substream_t *substream)
+{
+       struct cmi_spec *spec = codec->spec;
+       return snd_hda_multi_out_dig_open(codec, &spec->multiout);
+}
+
+static int cmi9880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
+                                         struct hda_codec *codec,
+                                         snd_pcm_substream_t *substream)
+{
+       struct cmi_spec *spec = codec->spec;
+       return snd_hda_multi_out_dig_close(codec, &spec->multiout);
+}
+
+/*
+ * Analog capture
+ */
+static int cmi9880_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
+                                     struct hda_codec *codec,
+                                     unsigned int stream_tag,
+                                     unsigned int format,
+                                     snd_pcm_substream_t *substream)
+{
+       struct cmi_spec *spec = codec->spec;
+
+       snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
+                                  stream_tag, 0, format);
+       return 0;
+}
+
+static int cmi9880_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
+                                     struct hda_codec *codec,
+                                     snd_pcm_substream_t *substream)
+{
+       struct cmi_spec *spec = codec->spec;
+
+       snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 0, 0, 0);
+       return 0;
+}
+
+
+/*
+ */
+static struct hda_pcm_stream cmi9880_pcm_analog_playback = {
+       .substreams = 1,
+       .channels_min = 2,
+       .channels_max = 8,
+       .nid = 0x03, /* NID to query formats and rates */
+       .ops = {
+               .open = cmi9880_playback_pcm_open,
+               .prepare = cmi9880_playback_pcm_prepare,
+               .cleanup = cmi9880_playback_pcm_cleanup
+       },
+};
+
+static struct hda_pcm_stream cmi9880_pcm_analog_capture = {
+       .substreams = 2,
+       .channels_min = 2,
+       .channels_max = 2,
+       .nid = 0x08, /* NID to query formats and rates */
+       .ops = {
+               .prepare = cmi9880_capture_pcm_prepare,
+               .cleanup = cmi9880_capture_pcm_cleanup
+       },
+};
+
+static struct hda_pcm_stream cmi9880_pcm_digital_playback = {
+       .substreams = 1,
+       .channels_min = 2,
+       .channels_max = 2,
+       /* NID is set in cmi9880_build_pcms */
+       .ops = {
+               .open = cmi9880_dig_playback_pcm_open,
+               .close = cmi9880_dig_playback_pcm_close
+       },
+};
+
+static struct hda_pcm_stream cmi9880_pcm_digital_capture = {
+       .substreams = 1,
+       .channels_min = 2,
+       .channels_max = 2,
+       /* NID is set in cmi9880_build_pcms */
+};
+
+static int cmi9880_build_pcms(struct hda_codec *codec)
+{
+       struct cmi_spec *spec = codec->spec;
+       struct hda_pcm *info = spec->pcm_rec;
+
+       codec->num_pcms = 1;
+       codec->pcm_info = info;
+
+       info->name = "CMI9880";
+       info->stream[SNDRV_PCM_STREAM_PLAYBACK] = cmi9880_pcm_analog_playback;
+       info->stream[SNDRV_PCM_STREAM_CAPTURE] = cmi9880_pcm_analog_capture;
+
+       if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
+               codec->num_pcms++;
+               info++;
+               info->name = "CMI9880 Digital";
+               if (spec->multiout.dig_out_nid) {
+                       info->stream[SNDRV_PCM_STREAM_PLAYBACK] = cmi9880_pcm_digital_playback;
+                       info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
+               }
+               if (spec->dig_in_nid) {
+                       info->stream[SNDRV_PCM_STREAM_CAPTURE] = cmi9880_pcm_digital_capture;
+                       info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
+               }
+       }
+
+       return 0;
+}
+
+static void cmi9880_free(struct hda_codec *codec)
+{
+       kfree(codec->spec);
+}
+
+/*
+ */
+
+static struct hda_board_config cmi9880_cfg_tbl[] = {
+       { .modelname = "minimal", .config = CMI_MINIMAL },
+       { .modelname = "min_fp", .config = CMI_MIN_FP },
+       { .modelname = "full", .config = CMI_FULL },
+       { .modelname = "full_dig", .config = CMI_FULL_DIG },
+       { .modelname = "allout", .config = CMI_ALLOUT },
+       {} /* terminator */
+};
+
+static struct hda_codec_ops cmi9880_patch_ops = {
+       .build_controls = cmi9880_build_controls,
+       .build_pcms = cmi9880_build_pcms,
+       .init = cmi9880_init,
+       .free = cmi9880_free,
+#ifdef CONFIG_PM
+       .resume = cmi9880_resume,
+#endif
+};
+
+static int patch_cmi9880(struct hda_codec *codec)
+{
+       struct cmi_spec *spec;
+
+       spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+       if (spec == NULL)
+               return -ENOMEM;
+
+       codec->spec = spec;
+       spec->board_config = snd_hda_check_board_config(codec, cmi9880_cfg_tbl);
+       if (spec->board_config < 0) {
+               snd_printd(KERN_INFO "hda_codec: Unknown model for CMI9880\n");
+               spec->board_config = CMI_FULL_DIG; /* try everything */
+       }
+
+       switch (spec->board_config) {
+       case CMI_MINIMAL:
+       case CMI_MIN_FP:
+               spec->surr_switch = 1;
+               if (spec->board_config == CMI_MINIMAL)
+                       spec->num_ch_modes = 2;
+               else {
+                       spec->front_panel = 1;
+                       spec->num_ch_modes = 3;
+               }
+               spec->channel_modes = cmi9880_channel_modes;
+               spec->multiout.max_channels = cmi9880_channel_modes[0].channels;
+               spec->input_mux = &cmi9880_basic_mux;
+               break;
+       case CMI_FULL:
+       case CMI_FULL_DIG:
+               spec->front_panel = 1;
+               spec->multiout.max_channels = 8;
+               spec->input_mux = &cmi9880_basic_mux;
+               if (spec->board_config == CMI_FULL_DIG) {
+                       spec->multiout.dig_out_nid = CMI_DIG_OUT_NID;
+                       spec->dig_in_nid = CMI_DIG_IN_NID;
+               }
+               break;
+       case CMI_ALLOUT:
+               spec->front_panel = 1;
+               spec->multiout.max_channels = 8;
+               spec->no_line_in = 1;
+               spec->input_mux = &cmi9880_no_line_mux;
+               spec->multiout.dig_out_nid = CMI_DIG_OUT_NID;
+               break;
+       }
+
+       spec->multiout.num_dacs = 4;
+       spec->multiout.dac_nids = cmi9880_dac_nids;
+
+       spec->adc_nids = cmi9880_adc_nids;
+
+       codec->patch_ops = cmi9880_patch_ops;
+
+       return 0;
+}
+
+/*
+ * patch entries
+ */
+struct hda_codec_preset snd_hda_preset_cmedia[] = {
+       { .id = 0x13f69880, .name = "CMI9880", .patch = patch_cmi9880 },
+       { .id = 0x434d4980, .name = "CMI9880", .patch = patch_cmi9880 },
+       {} /* terminator */
+};
diff --git a/sound/pci/ice1712/juli.c b/sound/pci/ice1712/juli.c
new file mode 100644 (file)
index 0000000..3fb297b
--- /dev/null
@@ -0,0 +1,230 @@
+/*
+ *   ALSA driver for ICEnsemble VT1724 (Envy24HT)
+ *
+ *   Lowlevel functions for ESI Juli@ cards
+ *
+ *     Copyright (c) 2004 Jaroslav Kysela <perex@suse.cz>
+ *
+ *   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 <sound/driver.h>
+#include <asm/io.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+
+#include "ice1712.h"
+#include "envy24ht.h"
+#include "juli.h"
+
+/*
+ * chip addresses on I2C bus
+ */
+#define AK4114_ADDR            0x20            /* S/PDIF receiver */
+#define AK4358_ADDR            0x22            /* DAC */
+
+/*
+ * GPIO pins
+ */
+#define GPIO_FREQ_MASK         (3<<0)
+#define GPIO_FREQ_32KHZ                (0<<0)
+#define GPIO_FREQ_44KHZ                (1<<0)
+#define GPIO_FREQ_48KHZ                (2<<0)
+#define GPIO_MULTI_MASK                (3<<2)
+#define GPIO_MULTI_4X          (0<<2)
+#define GPIO_MULTI_2X          (1<<2)
+#define GPIO_MULTI_1X          (2<<2)          /* also external */
+#define GPIO_MULTI_HALF                (3<<2)
+#define GPIO_INTERNAL_CLOCK    (1<<4)
+#define GPIO_ANALOG_PRESENT    (1<<5)          /* RO only: 0 = present */
+#define GPIO_RXMCLK_SEL                (1<<7)          /* must be 0 */
+#define GPIO_AK5385A_CKS0      (1<<8)
+#define GPIO_AK5385A_DFS0      (1<<9)          /* swapped with DFS1 according doc? */
+#define GPIO_AK5385A_DFS1      (1<<10)
+#define GPIO_DIGOUT_MONITOR    (1<<11)         /* 1 = active */
+#define GPIO_DIGIN_MONITOR     (1<<12)         /* 1 = active */
+#define GPIO_ANAIN_MONITOR     (1<<13)         /* 1 = active */
+#define GPIO_AK5385A_MCLK      (1<<14)         /* must be 0 */
+#define GPIO_MUTE_CONTROL      (1<<15)         /* 0 = off, 1 = on */
+
+static void juli_ak4114_write(void *private_data, unsigned char reg, unsigned char val)
+{
+       snd_vt1724_write_i2c((ice1712_t *)private_data, AK4114_ADDR, reg, val);
+}
+        
+static unsigned char juli_ak4114_read(void *private_data, unsigned char reg)
+{
+       return snd_vt1724_read_i2c((ice1712_t *)private_data, AK4114_ADDR, reg);
+}
+
+/*
+ * AK4358 section
+ */
+
+static void juli_akm_lock(akm4xxx_t *ak, int chip)
+{
+}
+
+static void juli_akm_unlock(akm4xxx_t *ak, int chip)
+{
+}
+
+static void juli_akm_write(akm4xxx_t *ak, int chip,
+                          unsigned char addr, unsigned char data)
+{
+       ice1712_t *ice = ak->private_data[0];
+        
+       snd_assert(chip == 0, return);
+       snd_vt1724_write_i2c(ice, AK4358_ADDR, addr, data);
+}
+
+/*
+ * change the rate of envy24HT, AK4358
+ */
+static void juli_akm_set_rate_val(akm4xxx_t *ak, unsigned int rate)
+{
+       unsigned char old, tmp, dfs;
+
+       if (rate == 0)  /* no hint - S/PDIF input is master, simply return */
+               return;
+       
+       /* adjust DFS on codecs */
+       if (rate > 96000) 
+               dfs = 2;
+       else if (rate > 48000)
+               dfs = 1;
+       else
+               dfs = 0;
+       
+       tmp = snd_akm4xxx_get(ak, 0, 2);
+       old = (tmp >> 4) & 0x03;
+       if (old == dfs)
+               return;
+       /* reset DFS */
+       snd_akm4xxx_reset(ak, 1);
+       tmp = snd_akm4xxx_get(ak, 0, 2);
+       tmp &= ~(0x03 << 4);
+       tmp |= dfs << 4;
+       snd_akm4xxx_set(ak, 0, 2, tmp);
+       snd_akm4xxx_reset(ak, 0);
+}
+
+static akm4xxx_t akm_juli_dac __devinitdata = {
+       .type = SND_AK4358,
+       .num_dacs = 2,
+       .ops = {
+               .lock = juli_akm_lock,
+               .unlock = juli_akm_unlock,
+               .write = juli_akm_write,
+               .set_rate_val = juli_akm_set_rate_val
+       }
+};
+
+static int __devinit juli_add_controls(ice1712_t *ice)
+{
+       return snd_ice1712_akm4xxx_build_controls(ice);
+}
+
+/*
+ * initialize the chip
+ */
+static int __devinit juli_init(ice1712_t *ice)
+{
+       static unsigned char ak4114_init_vals[] = {
+               /* AK4117_REG_PWRDN */  AK4114_RST | AK4114_PWN | AK4114_OCKS0 | AK4114_OCKS1,
+               /* AK4114_REQ_FORMAT */ AK4114_DIF_I24I2S,
+               /* AK4114_REG_IO0 */    AK4114_TX1E,
+               /* AK4114_REG_IO1 */    AK4114_EFH_1024 | AK4114_DIT | AK4114_IPS(1),
+               /* AK4114_REG_INT0_MASK */ 0,
+               /* AK4114_REG_INT1_MASK */ 0
+       };
+       static unsigned char ak4114_init_txcsb[] = {
+               0x41, 0x02, 0x2c, 0x00, 0x00
+       };
+       int err;
+       akm4xxx_t *ak;
+
+#if 0
+       for (err = 0; err < 0x20; err++)
+               juli_ak4114_read(ice, err);
+       juli_ak4114_write(ice, 0, 0x0f);
+       juli_ak4114_read(ice, 0);
+       juli_ak4114_read(ice, 1);
+#endif
+       err = snd_ak4114_create(ice->card,
+                               juli_ak4114_read,
+                               juli_ak4114_write,
+                               ak4114_init_vals, ak4114_init_txcsb,
+                               ice, &ice->spec.juli.ak4114);
+       if (err < 0)
+               return err;
+
+       ice->spec.juli.analog = ice->gpio.get_data(ice) & GPIO_ANALOG_PRESENT;
+
+       if (ice->spec.juli.analog) {
+               printk(KERN_INFO "juli@: analog I/O detected\n");
+               ice->num_total_dacs = 2;
+               ice->num_total_adcs = 2;
+
+               ak = ice->akm = kcalloc(1, sizeof(akm4xxx_t), GFP_KERNEL);
+               if (! ak)
+                       return -ENOMEM;
+               ice->akm_codecs = 1;
+               if ((err = snd_ice1712_akm4xxx_init(ak, &akm_juli_dac, NULL, ice)) < 0)
+                       return err;
+       }
+       
+       return 0;
+}
+
+
+/*
+ * Juli@ boards don't provide the EEPROM data except for the vendor IDs.
+ * hence the driver needs to sets up it properly.
+ */
+
+static unsigned char juli_eeprom[] __devinitdata = {
+       0x20,   /* SYSCONF: clock 512, mpu401, 1xADC, 1xDACs */
+       0x80,   /* ACLINK: I2S */
+       0xf8,   /* I2S: vol, 96k, 24bit, 192k */
+       0xc3,   /* SPDIF: out-en, out-int, spdif-in */
+       0x9f,   /* GPIO_DIR */
+       0xff,   /* GPIO_DIR1 */
+       0x7f,   /* GPIO_DIR2 */
+       0x9f,   /* GPIO_MASK */
+       0xff,   /* GPIO_MASK1 */
+       0x7f,   /* GPIO_MASK2 */
+       0x16,   /* GPIO_STATE: internal clock, multiple 1x, 48kHz */
+       0x80,   /* GPIO_STATE1: mute */
+       0x00,   /* GPIO_STATE2 */
+};
+
+/* entry point */
+struct snd_ice1712_card_info snd_vt1724_juli_cards[] __devinitdata = {
+       {
+               .subvendor = VT1724_SUBDEVICE_JULI,
+               .name = "ESI Juli@",
+               .model = "juli",
+               .chip_init = juli_init,
+               .build_controls = juli_add_controls,
+               .eeprom_size = sizeof(juli_eeprom),
+               .eeprom_data = juli_eeprom,
+       },
+       { } /* terminator */
+};
diff --git a/sound/pci/ice1712/juli.h b/sound/pci/ice1712/juli.h
new file mode 100644 (file)
index 0000000..d9f8534
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef __SOUND_JULI_H
+#define __SOUND_JULI_H
+
+#define JULI_DEVICE_DESC               "{ESI,Juli@},"
+
+#define VT1724_SUBDEVICE_JULI          0x31305345      /* Juli@ */
+
+extern struct snd_ice1712_card_info  snd_vt1724_juli_cards[];
+
+#endif /* __SOUND_JULI_H */
diff --git a/sound/pci/ice1712/phase.h b/sound/pci/ice1712/phase.h
new file mode 100644 (file)
index 0000000..6230cf1
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef __SOUND_PHASE_H
+#define __SOUND_PHASE_H
+
+/*
+ *   ALSA driver for ICEnsemble ICE1712 (Envy24)
+ *
+ *   Lowlevel functions for Terratec PHASE 22
+ *
+ *     Copyright (c) 2005 Misha Zhilin <misha@epiphan.com>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */      
+
+#define PHASE_DEVICE_DESC "{Terratec,Phase 22},"
+
+#define VT1724_SUBDEVICE_PHASE22       0x3b155011
+
+/* entry point */
+extern struct snd_ice1712_card_info snd_vt1724_phase_cards[];
+
+#endif /* __SOUND_PHASE */