summary refs log tree commit diff
path: root/drivers
diff options
context:
space:
mode:
authorRussell King <rmk@dyn-67.arm.linux.org.uk>2006-01-07 14:40:05 +0000
committerRussell King <rmk+kernel@arm.linux.org.uk>2006-01-07 14:40:05 +0000
commit123656d4cc8c946f578ebd18c2050f5251720428 (patch)
tree3d5432eff034a3b9cfdc98b37e245abe5695342d /drivers
parenta62c80e559809e6c7851ec04d30575e85ad6f6ed (diff)
parent0aec63e67c69545ca757a73a66f5dcf05fa484bf (diff)
downloadlinux-123656d4cc8c946f578ebd18c2050f5251720428.tar.gz
Merge with Linus' kernel.
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acorn/char/pcf8583.c5
-rw-r--r--drivers/acpi/container.c8
-rw-r--r--drivers/acpi/processor_core.c8
-rw-r--r--drivers/acpi/scan.c14
-rw-r--r--drivers/base/Kconfig4
-rw-r--r--drivers/base/bus.c41
-rw-r--r--drivers/base/class.c66
-rw-r--r--drivers/base/core.c42
-rw-r--r--drivers/base/cpu.c4
-rw-r--r--drivers/base/dd.c15
-rw-r--r--drivers/base/firmware_class.c45
-rw-r--r--drivers/base/memory.c19
-rw-r--r--drivers/base/platform.c68
-rw-r--r--drivers/base/power/runtime.c3
-rw-r--r--drivers/block/DAC960.c2
-rw-r--r--drivers/block/Kconfig5
-rw-r--r--drivers/block/cciss.c2
-rw-r--r--drivers/block/cpqarray.c2
-rw-r--r--drivers/block/floppy.c2
-rw-r--r--drivers/block/loop.c23
-rw-r--r--drivers/block/nbd.c124
-rw-r--r--drivers/block/paride/Kconfig5
-rw-r--r--drivers/block/rd.c4
-rw-r--r--drivers/block/sx8.c2
-rw-r--r--drivers/block/ub.c439
-rw-r--r--drivers/block/viodasd.c2
-rw-r--r--drivers/bluetooth/bcm203x.c1
-rw-r--r--drivers/bluetooth/bfusb.c1
-rw-r--r--drivers/bluetooth/bluecard_cs.c109
-rw-r--r--drivers/bluetooth/bpa10x.c1
-rw-r--r--drivers/bluetooth/bt3c_cs.c110
-rw-r--r--drivers/bluetooth/btuart_cs.c110
-rw-r--r--drivers/bluetooth/dtl1_cs.c111
-rw-r--r--drivers/bluetooth/hci_usb.c1
-rw-r--r--drivers/cdrom/cdu31a.c2
-rw-r--r--drivers/char/.gitignore2
-rw-r--r--drivers/char/Kconfig2
-rw-r--r--drivers/char/hangcheck-timer.c2
-rw-r--r--drivers/char/hw_random.c70
-rw-r--r--drivers/char/ip2/i2pack.h2
-rw-r--r--drivers/char/ipmi/ipmi_msghandler.c4
-rw-r--r--drivers/char/mmtimer.c90
-rw-r--r--drivers/char/n_hdlc.c2
-rw-r--r--drivers/char/pcmcia/cm4000_cs.c162
-rw-r--r--drivers/char/pcmcia/cm4040_cs.c151
-rw-r--r--drivers/char/pcmcia/synclink_cs.c132
-rw-r--r--drivers/char/random.c10
-rw-r--r--drivers/char/watchdog/Kconfig2
-rw-r--r--drivers/char/watchdog/ixp4xx_wdt.c4
-rw-r--r--drivers/char/watchdog/pcwd_usb.c1
-rw-r--r--drivers/cpufreq/cpufreq.c24
-rw-r--r--drivers/cpufreq/cpufreq_conservative.c10
-rw-r--r--drivers/cpufreq/cpufreq_ondemand.c10
-rw-r--r--drivers/hwmon/Kconfig12
-rw-r--r--drivers/hwmon/Makefile1
-rw-r--r--drivers/hwmon/adm1021.c6
-rw-r--r--drivers/hwmon/adm1025.c10
-rw-r--r--drivers/hwmon/adm1026.c10
-rw-r--r--drivers/hwmon/adm1031.c6
-rw-r--r--drivers/hwmon/adm9240.c6
-rw-r--r--drivers/hwmon/asb100.c6
-rw-r--r--drivers/hwmon/atxp1.c6
-rw-r--r--drivers/hwmon/ds1621.c6
-rw-r--r--drivers/hwmon/fscher.c6
-rw-r--r--drivers/hwmon/fscpos.c6
-rw-r--r--drivers/hwmon/gl518sm.c6
-rw-r--r--drivers/hwmon/gl520sm.c6
-rw-r--r--drivers/hwmon/hwmon-vid.c69
-rw-r--r--drivers/hwmon/it87.c18
-rw-r--r--drivers/hwmon/lm63.c6
-rw-r--r--drivers/hwmon/lm75.c6
-rw-r--r--drivers/hwmon/lm77.c6
-rw-r--r--drivers/hwmon/lm78.c13
-rw-r--r--drivers/hwmon/lm80.c6
-rw-r--r--drivers/hwmon/lm83.c6
-rw-r--r--drivers/hwmon/lm85.c50
-rw-r--r--drivers/hwmon/lm87.c6
-rw-r--r--drivers/hwmon/lm90.c6
-rw-r--r--drivers/hwmon/lm92.c6
-rw-r--r--drivers/hwmon/max1619.c6
-rw-r--r--drivers/hwmon/pc87360.c7
-rw-r--r--drivers/hwmon/sis5595.c8
-rw-r--r--drivers/hwmon/smsc47b397.c8
-rw-r--r--drivers/hwmon/smsc47m1.c7
-rw-r--r--drivers/hwmon/via686a.c8
-rw-r--r--drivers/hwmon/vt8231.c862
-rw-r--r--drivers/hwmon/w83627ehf.c7
-rw-r--r--drivers/hwmon/w83627hf.c23
-rw-r--r--drivers/hwmon/w83781d.c13
-rw-r--r--drivers/hwmon/w83792d.c83
-rw-r--r--drivers/hwmon/w83l785ts.c6
-rw-r--r--drivers/i2c/busses/i2c-i801.c6
-rw-r--r--drivers/i2c/busses/i2c-ibm_iic.c1
-rw-r--r--drivers/i2c/busses/i2c-isa.c10
-rw-r--r--drivers/i2c/busses/i2c-mv64xxx.c33
-rw-r--r--drivers/i2c/busses/i2c-nforce2.c2
-rw-r--r--drivers/i2c/busses/i2c-parport.h12
-rw-r--r--drivers/i2c/chips/ds1337.c43
-rw-r--r--drivers/i2c/chips/ds1374.c6
-rw-r--r--drivers/i2c/chips/eeprom.c6
-rw-r--r--drivers/i2c/chips/isp1301_omap.c6
-rw-r--r--drivers/i2c/chips/m41t00.c6
-rw-r--r--drivers/i2c/chips/max6875.c6
-rw-r--r--drivers/i2c/chips/pca9539.c6
-rw-r--r--drivers/i2c/chips/pcf8574.c6
-rw-r--r--drivers/i2c/chips/pcf8591.c6
-rw-r--r--drivers/i2c/chips/rtc8564.c43
-rw-r--r--drivers/i2c/chips/tps65010.c6
-rw-r--r--drivers/i2c/chips/x1205.c6
-rw-r--r--drivers/i2c/i2c-core.c70
-rw-r--r--drivers/i2c/i2c-dev.c63
-rw-r--r--drivers/ide/ide-cd.c5
-rw-r--r--drivers/ide/ide-disk.c138
-rw-r--r--drivers/ide/ide-floppy.c1
-rw-r--r--drivers/ide/ide-io.c11
-rw-r--r--drivers/ide/ide-tape.c1
-rw-r--r--drivers/ide/ide.c60
-rw-r--r--drivers/ide/legacy/ide-cs.c132
-rw-r--r--drivers/ieee1394/.gitignore1
-rw-r--r--drivers/ieee1394/Kconfig23
-rw-r--r--drivers/ieee1394/Makefile2
-rw-r--r--drivers/ieee1394/csr1212.c21
-rw-r--r--drivers/ieee1394/csr1212.h2
-rw-r--r--drivers/ieee1394/dma.c73
-rw-r--r--drivers/ieee1394/dv1394.c13
-rw-r--r--drivers/ieee1394/eth1394.c20
-rw-r--r--drivers/ieee1394/highlevel.c18
-rw-r--r--drivers/ieee1394/hosts.c30
-rw-r--r--drivers/ieee1394/hosts.h162
-rw-r--r--drivers/ieee1394/ieee1394-ioctl.h8
-rw-r--r--drivers/ieee1394/ieee1394.h19
-rw-r--r--drivers/ieee1394/ieee1394_core.c827
-rw-r--r--drivers/ieee1394/ieee1394_core.h100
-rw-r--r--drivers/ieee1394/ieee1394_transactions.c389
-rw-r--r--drivers/ieee1394/iso.c102
-rw-r--r--drivers/ieee1394/nodemgr.c70
-rw-r--r--drivers/ieee1394/nodemgr.h18
-rw-r--r--drivers/ieee1394/ohci1394.c43
-rw-r--r--drivers/ieee1394/ohci1394.h4
-rw-r--r--drivers/ieee1394/pcilynx.c2
-rw-r--r--drivers/ieee1394/raw1394.c79
-rw-r--r--drivers/ieee1394/sbp2.c1040
-rw-r--r--drivers/ieee1394/sbp2.h70
-rw-r--r--drivers/ieee1394/video1394.c106
-rw-r--r--drivers/infiniband/core/sysfs.c16
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c2
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_multicast.c2
-rw-r--r--drivers/input/evdev.c2
-rw-r--r--drivers/input/input.c54
-rw-r--r--drivers/input/joystick/iforce/iforce-usb.c1
-rw-r--r--drivers/input/serio/serio.c22
-rw-r--r--drivers/isdn/hardware/avm/avm_cs.c145
-rw-r--r--drivers/isdn/hisax/avma1_cs.c150
-rw-r--r--drivers/isdn/hisax/elsa_cs.c158
-rw-r--r--drivers/isdn/hisax/hfc_usb.c1
-rw-r--r--drivers/isdn/hisax/sedlbauer_cs.c169
-rw-r--r--drivers/isdn/hisax/st5481_init.c1
-rw-r--r--drivers/isdn/hisax/teles_cs.c149
-rw-r--r--drivers/macintosh/macio_asic.c4
-rw-r--r--drivers/macintosh/therm_adt746x.c45
-rw-r--r--drivers/macintosh/therm_pm72.c13
-rw-r--r--drivers/macintosh/therm_windtunnel.c6
-rw-r--r--drivers/macintosh/windfarm_lm75_sensor.c13
-rw-r--r--drivers/md/.gitignore4
-rw-r--r--drivers/md/bitmap.c114
-rw-r--r--drivers/md/dm-crypt.c5
-rw-r--r--drivers/md/dm-io.h3
-rw-r--r--drivers/md/dm-ioctl.c21
-rw-r--r--drivers/md/dm-log.c2
-rw-r--r--drivers/md/dm-raid1.c13
-rw-r--r--drivers/md/dm-snap.c25
-rw-r--r--drivers/md/dm-table.c2
-rw-r--r--drivers/md/dm.c95
-rw-r--r--drivers/md/dm.h5
-rw-r--r--drivers/md/faulty.c9
-rw-r--r--drivers/md/kcopyd.c3
-rw-r--r--drivers/md/linear.c14
-rw-r--r--drivers/md/md.c893
-rw-r--r--drivers/md/multipath.c22
-rw-r--r--drivers/md/raid0.c26
-rw-r--r--drivers/md/raid1.c726
-rw-r--r--drivers/md/raid10.c544
-rw-r--r--drivers/md/raid5.c174
-rw-r--r--drivers/md/raid6main.c348
-rw-r--r--drivers/media/dvb/b2c2/flexcop-usb.c1
-rw-r--r--drivers/media/dvb/cinergyT2/cinergyT2.c3
-rw-r--r--drivers/media/dvb/dvb-usb/a800.c1
-rw-r--r--drivers/media/dvb/dvb-usb/cxusb.c1
-rw-r--r--drivers/media/dvb/dvb-usb/dibusb-mb.c1
-rw-r--r--drivers/media/dvb/dvb-usb/dibusb-mc.c1
-rw-r--r--drivers/media/dvb/dvb-usb/digitv.c1
-rw-r--r--drivers/media/dvb/dvb-usb/dtt200u.c1
-rw-r--r--drivers/media/dvb/dvb-usb/nova-t-usb2.c1
-rw-r--r--drivers/media/dvb/dvb-usb/umt-010.c1
-rw-r--r--drivers/media/dvb/dvb-usb/vp702x.c1
-rw-r--r--drivers/media/dvb/dvb-usb/vp7045.c1
-rw-r--r--drivers/media/dvb/ttpci/budget.h2
-rw-r--r--drivers/media/video/adv7170.c7
-rw-r--r--drivers/media/video/adv7175.c7
-rw-r--r--drivers/media/video/bt819.c7
-rw-r--r--drivers/media/video/bt832.c7
-rw-r--r--drivers/media/video/bt856.c7
-rw-r--r--drivers/media/video/bttv-i2c.c2
-rw-r--r--drivers/media/video/cpia_pp.c30
-rw-r--r--drivers/media/video/cpia_usb.c1
-rw-r--r--drivers/media/video/cs53l32a.c14
-rw-r--r--drivers/media/video/cx25840/cx25840-core.c7
-rw-r--r--drivers/media/video/cx25840/cx25840.h7
-rw-r--r--drivers/media/video/cx88/cx88-i2c.c2
-rw-r--r--drivers/media/video/em28xx/em28xx-i2c.c1
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c1
-rw-r--r--drivers/media/video/indycam.c6
-rw-r--r--drivers/media/video/ir-kbd-i2c.c5
-rw-r--r--drivers/media/video/msp3400.c20
-rw-r--r--drivers/media/video/ovcamchip/ovcamchip_core.c6
-rw-r--r--drivers/media/video/saa5246a.c13
-rw-r--r--drivers/media/video/saa5249.c13
-rw-r--r--drivers/media/video/saa6588.c7
-rw-r--r--drivers/media/video/saa7110.c7
-rw-r--r--drivers/media/video/saa7111.c7
-rw-r--r--drivers/media/video/saa7114.c7
-rw-r--r--drivers/media/video/saa7115.c14
-rw-r--r--drivers/media/video/saa711x.c7
-rw-r--r--drivers/media/video/saa7127.c17
-rw-r--r--drivers/media/video/saa7134/saa6752hs.c7
-rw-r--r--drivers/media/video/saa7134/saa7134-i2c.c4
-rw-r--r--drivers/media/video/saa7185.c7
-rw-r--r--drivers/media/video/saa7191.c6
-rw-r--r--drivers/media/video/tda7432.c6
-rw-r--r--drivers/media/video/tda9840.c8
-rw-r--r--drivers/media/video/tda9875.c6
-rw-r--r--drivers/media/video/tda9887.c5
-rw-r--r--drivers/media/video/tea6415c.c8
-rw-r--r--drivers/media/video/tea6420.c8
-rw-r--r--drivers/media/video/tuner-3036.c6
-rw-r--r--drivers/media/video/tuner-core.c7
-rw-r--r--drivers/media/video/tvaudio.c7
-rw-r--r--drivers/media/video/tveeprom.c7
-rw-r--r--drivers/media/video/tvmixer.c12
-rw-r--r--drivers/media/video/tvp5150.c7
-rw-r--r--drivers/media/video/vpx3220.c7
-rw-r--r--drivers/media/video/wm8775.c11
-rw-r--r--drivers/media/video/zoran_driver.c14
-rw-r--r--drivers/message/fusion/mptbase.c14
-rw-r--r--drivers/message/fusion/mptbase.h34
-rw-r--r--drivers/message/fusion/mptctl.c4
-rw-r--r--drivers/message/fusion/mptfc.c24
-rw-r--r--drivers/message/fusion/mptsas.c55
-rw-r--r--drivers/message/fusion/mptscsih.c968
-rw-r--r--drivers/message/fusion/mptscsih.h2
-rw-r--r--drivers/message/fusion/mptspi.c24
-rw-r--r--drivers/message/i2o/Kconfig12
-rw-r--r--drivers/message/i2o/bus-osm.c23
-rw-r--r--drivers/message/i2o/config-osm.c2
-rw-r--r--drivers/message/i2o/core.h20
-rw-r--r--drivers/message/i2o/device.c339
-rw-r--r--drivers/message/i2o/driver.c12
-rw-r--r--drivers/message/i2o/exec-osm.c114
-rw-r--r--drivers/message/i2o/i2o_block.c190
-rw-r--r--drivers/message/i2o/i2o_config.c196
-rw-r--r--drivers/message/i2o/i2o_lan.h38
-rw-r--r--drivers/message/i2o/i2o_proc.c2
-rw-r--r--drivers/message/i2o/i2o_scsi.c89
-rw-r--r--drivers/message/i2o/iop.c356
-rw-r--r--drivers/message/i2o/pci.c7
-rw-r--r--drivers/mmc/mmc_block.c4
-rw-r--r--drivers/mmc/mmc_sysfs.c4
-rw-r--r--drivers/mtd/maps/pcmciamtd.c121
-rw-r--r--drivers/net/8139too.c86
-rw-r--r--drivers/net/Kconfig17
-rw-r--r--drivers/net/Makefile7
-rw-r--r--drivers/net/bonding/Makefile2
-rw-r--r--drivers/net/bonding/bond_3ad.c106
-rw-r--r--drivers/net/bonding/bond_3ad.h13
-rw-r--r--drivers/net/bonding/bond_alb.c75
-rw-r--r--drivers/net/bonding/bond_alb.h9
-rw-r--r--drivers/net/bonding/bond_main.c781
-rw-r--r--drivers/net/bonding/bond_sysfs.c1358
-rw-r--r--drivers/net/bonding/bonding.h52
-rw-r--r--drivers/net/chelsio/sge.c19
-rw-r--r--drivers/net/chelsio/sge.h2
-rw-r--r--drivers/net/e1000/e1000.h4
-rw-r--r--drivers/net/e1000/e1000_ethtool.c111
-rw-r--r--drivers/net/e1000/e1000_hw.c67
-rw-r--r--drivers/net/e1000/e1000_hw.h4
-rw-r--r--drivers/net/e1000/e1000_main.c64
-rw-r--r--drivers/net/gianfar.c231
-rw-r--r--drivers/net/gianfar.h69
-rw-r--r--drivers/net/gianfar_ethtool.c2
-rw-r--r--drivers/net/gianfar_mii.h1
-rw-r--r--drivers/net/gianfar_sysfs.c311
-rw-r--r--drivers/net/irda/irda-usb.c1
-rw-r--r--drivers/net/irda/stir4200.c1
-rw-r--r--drivers/net/ixp2000/Kconfig6
-rw-r--r--drivers/net/ixp2000/Makefile3
-rw-r--r--drivers/net/ixp2000/caleb.c137
-rw-r--r--drivers/net/ixp2000/caleb.h22
-rw-r--r--drivers/net/ixp2000/enp2611.c245
-rw-r--r--drivers/net/ixp2000/ixp2400-msf.c213
-rw-r--r--drivers/net/ixp2000/ixp2400-msf.h115
-rw-r--r--drivers/net/ixp2000/ixp2400_rx.uc408
-rw-r--r--drivers/net/ixp2000/ixp2400_rx.ucode130
-rw-r--r--drivers/net/ixp2000/ixp2400_tx.uc272
-rw-r--r--drivers/net/ixp2000/ixp2400_tx.ucode98
-rw-r--r--drivers/net/ixp2000/ixpdev.c421
-rw-r--r--drivers/net/ixp2000/ixpdev.h27
-rw-r--r--drivers/net/ixp2000/ixpdev_priv.h57
-rw-r--r--drivers/net/ixp2000/pm3386.c334
-rw-r--r--drivers/net/ixp2000/pm3386.h28
-rw-r--r--drivers/net/ns83820.c1
-rw-r--r--drivers/net/pcmcia/3c574_cs.c124
-rw-r--r--drivers/net/pcmcia/3c589_cs.c136
-rw-r--r--drivers/net/pcmcia/axnet_cs.c128
-rw-r--r--drivers/net/pcmcia/com20020_cs.c142
-rw-r--r--drivers/net/pcmcia/fmvj18x_cs.c128
-rw-r--r--drivers/net/pcmcia/ibmtr_cs.c152
-rw-r--r--drivers/net/pcmcia/nmclan_cs.c134
-rw-r--r--drivers/net/pcmcia/pcnet_cs.c129
-rw-r--r--drivers/net/pcmcia/smc91c92_cs.c195
-rw-r--r--drivers/net/pcmcia/xirc2ps_cs.c158
-rw-r--r--drivers/net/phy/Kconfig2
-rw-r--r--drivers/net/plip.c2
-rw-r--r--drivers/net/pppoe.c31
-rw-r--r--drivers/net/pppox.c10
-rw-r--r--drivers/net/s2io.c200
-rw-r--r--drivers/net/s2io.h3
-rw-r--r--drivers/net/sis900.c73
-rw-r--r--drivers/net/sis900.h45
-rw-r--r--drivers/net/sk98lin/Makefile3
-rw-r--r--drivers/net/sk98lin/h/skdrv2nd.h9
-rw-r--r--drivers/net/sk98lin/h/skvpd.h8
-rw-r--r--drivers/net/sk98lin/skethtool.c48
-rw-r--r--drivers/net/sk98lin/skge.c213
-rw-r--r--drivers/net/sk98lin/skproc.c265
-rw-r--r--drivers/net/skge.c81
-rw-r--r--drivers/net/skge.h73
-rw-r--r--drivers/net/sky2.c3262
-rw-r--r--drivers/net/sky2.h1922
-rw-r--r--drivers/net/tg3.c3
-rw-r--r--drivers/net/tlan.c4
-rw-r--r--drivers/net/wan/.gitignore1
-rw-r--r--drivers/net/wan/lmc/lmc_prot.h15
-rw-r--r--drivers/net/wireless/Kconfig6
-rw-r--r--drivers/net/wireless/airo.c15
-rw-r--r--drivers/net/wireless/airo_cs.c161
-rw-r--r--drivers/net/wireless/atmel.c1490
-rw-r--r--drivers/net/wireless/atmel_cs.c156
-rw-r--r--drivers/net/wireless/hostap/Makefile1
-rw-r--r--drivers/net/wireless/hostap/hostap_cs.c156
-rw-r--r--drivers/net/wireless/hostap/hostap_main.c (renamed from drivers/net/wireless/hostap/hostap.c)0
-rw-r--r--drivers/net/wireless/ipw2100.c40
-rw-r--r--drivers/net/wireless/ipw2100.h2
-rw-r--r--drivers/net/wireless/ipw2200.c36
-rw-r--r--drivers/net/wireless/ipw2200.h6
-rw-r--r--drivers/net/wireless/netwave_cs.c184
-rw-r--r--drivers/net/wireless/orinoco_cs.c208
-rw-r--r--drivers/net/wireless/ray_cs.c154
-rw-r--r--drivers/net/wireless/spectrum_cs.c175
-rw-r--r--drivers/net/wireless/wavelan_cs.c183
-rw-r--r--drivers/net/wireless/wavelan_cs.p.h11
-rw-r--r--drivers/net/wireless/wl3501_cs.c133
-rw-r--r--drivers/parport/Kconfig2
-rw-r--r--drivers/parport/daisy.c51
-rw-r--r--drivers/parport/ieee1284_ops.c62
-rw-r--r--drivers/parport/parport_cs.c120
-rw-r--r--drivers/parport/parport_pc.c30
-rw-r--r--drivers/parport/probe.c199
-rw-r--r--drivers/parport/share.c1
-rw-r--r--drivers/pci/hotplug.c44
-rw-r--r--drivers/pci/pci-driver.c6
-rw-r--r--drivers/pci/pci.h4
-rw-r--r--drivers/pci/quirks.c30
-rw-r--r--drivers/pcmcia/Kconfig32
-rw-r--r--drivers/pcmcia/au1000_generic.c21
-rw-r--r--drivers/pcmcia/cistpl.c36
-rw-r--r--drivers/pcmcia/cs.c112
-rw-r--r--drivers/pcmcia/cs_internal.h4
-rw-r--r--drivers/pcmcia/ds.c401
-rw-r--r--drivers/pcmcia/hd64465_ss.c13
-rw-r--r--drivers/pcmcia/i82092.c73
-rw-r--r--drivers/pcmcia/i82092aa.h1
-rw-r--r--drivers/pcmcia/i82365.c83
-rw-r--r--drivers/pcmcia/m32r_cfc.c32
-rw-r--r--drivers/pcmcia/m32r_pcc.c20
-rw-r--r--drivers/pcmcia/m8xx_pcmcia.c114
-rw-r--r--drivers/pcmcia/pd6729.c74
-rw-r--r--drivers/pcmcia/pxa2xx_mainstone.c3
-rw-r--r--drivers/pcmcia/pxa2xx_sharpsl.c3
-rw-r--r--drivers/pcmcia/rsrc_mgr.c108
-rw-r--r--drivers/pcmcia/rsrc_nonstatic.c140
-rw-r--r--drivers/pcmcia/soc_common.c23
-rw-r--r--drivers/pcmcia/socket_sysfs.c30
-rw-r--r--drivers/pcmcia/tcic.c61
-rw-r--r--drivers/pcmcia/ti113x.h4
-rw-r--r--drivers/pcmcia/vrc4171_card.c70
-rw-r--r--drivers/pcmcia/vrc4173_cardu.c43
-rw-r--r--drivers/pcmcia/yenta_socket.c140
-rw-r--r--drivers/pnp/card.c25
-rw-r--r--drivers/pnp/driver.c47
-rw-r--r--drivers/pnp/manager.c78
-rw-r--r--drivers/pnp/pnpbios/bioscalls.c45
-rw-r--r--drivers/pnp/pnpbios/core.c8
-rw-r--r--drivers/s390/Makefile2
-rw-r--r--drivers/s390/block/Kconfig8
-rw-r--r--drivers/s390/block/dasd.c34
-rw-r--r--drivers/s390/block/dasd_diag.c11
-rw-r--r--drivers/s390/block/dasd_diag.h31
-rw-r--r--drivers/s390/block/dasd_eckd.c9
-rw-r--r--drivers/s390/block/dasd_fba.c6
-rw-r--r--drivers/s390/block/dasd_int.h3
-rw-r--r--drivers/s390/block/dasd_ioctl.c5
-rw-r--r--drivers/s390/block/dcssblk.c2
-rw-r--r--drivers/s390/block/xpram.c4
-rw-r--r--drivers/s390/char/sclp_cpi.c2
-rw-r--r--drivers/s390/char/sclp_quiesce.c2
-rw-r--r--drivers/s390/char/tape_block.c4
-rw-r--r--drivers/s390/char/vmwatchdog.c2
-rw-r--r--drivers/s390/cio/blacklist.c234
-rw-r--r--drivers/s390/cio/blacklist.h2
-rw-r--r--drivers/s390/cio/ccwgroup.c10
-rw-r--r--drivers/s390/cio/chsc.c473
-rw-r--r--drivers/s390/cio/chsc.h13
-rw-r--r--drivers/s390/cio/cio.c168
-rw-r--r--drivers/s390/cio/cio.h11
-rw-r--r--drivers/s390/cio/cmf.c8
-rw-r--r--drivers/s390/cio/css.c297
-rw-r--r--drivers/s390/cio/css.h43
-rw-r--r--drivers/s390/cio/device.c51
-rw-r--r--drivers/s390/cio/device.h1
-rw-r--r--drivers/s390/cio/device_fsm.c29
-rw-r--r--drivers/s390/cio/device_id.c26
-rw-r--r--drivers/s390/cio/device_ops.c4
-rw-r--r--drivers/s390/cio/device_pgid.c56
-rw-r--r--drivers/s390/cio/device_status.c14
-rw-r--r--drivers/s390/cio/ioasm.h86
-rw-r--r--drivers/s390/cio/qdio.c713
-rw-r--r--drivers/s390/cio/qdio.h144
-rw-r--r--drivers/s390/cio/schid.h26
-rw-r--r--drivers/s390/crypto/z90common.h9
-rw-r--r--drivers/s390/crypto/z90crypt.h13
-rw-r--r--drivers/s390/crypto/z90hardware.c309
-rw-r--r--drivers/s390/crypto/z90main.c112
-rw-r--r--drivers/s390/net/Kconfig2
-rw-r--r--drivers/s390/net/claw.c6
-rw-r--r--drivers/s390/net/cu3088.c3
-rw-r--r--drivers/s390/net/iucv.c10
-rw-r--r--drivers/s390/net/qeth_main.c21
-rw-r--r--drivers/s390/s390_rdev.c53
-rw-r--r--drivers/s390/s390mach.c66
-rw-r--r--drivers/s390/sysinfo.c2
-rw-r--r--drivers/scsi/.gitignore3
-rw-r--r--drivers/scsi/53c700.c6
-rw-r--r--drivers/scsi/53c700.h22
-rw-r--r--drivers/scsi/53c7xx.c7
-rw-r--r--drivers/scsi/Kconfig23
-rw-r--r--drivers/scsi/NCR5380.c7
-rw-r--r--drivers/scsi/aha152x.c7
-rw-r--r--drivers/scsi/ahci.c15
-rw-r--r--drivers/scsi/aic7xxx/.gitignore6
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.c11
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.c18
-rw-r--r--drivers/scsi/arm/Kconfig1
-rw-r--r--drivers/scsi/arm/acornscsi.c7
-rw-r--r--drivers/scsi/ata_piix.c132
-rw-r--r--drivers/scsi/atari_NCR5380.c7
-rw-r--r--drivers/scsi/ch.c4
-rw-r--r--drivers/scsi/constants.c118
-rw-r--r--drivers/scsi/hosts.c9
-rw-r--r--drivers/scsi/ide-scsi.c4
-rw-r--r--drivers/scsi/ipr.c19
-rw-r--r--drivers/scsi/ipr.h5
-rw-r--r--drivers/scsi/iscsi_tcp.c121
-rw-r--r--drivers/scsi/iscsi_tcp.h3
-rw-r--r--drivers/scsi/libata-core.c507
-rw-r--r--drivers/scsi/libata-scsi.c72
-rw-r--r--drivers/scsi/libata.h5
-rw-r--r--drivers/scsi/lpfc/lpfc.h14
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c92
-rw-r--r--drivers/scsi/lpfc/lpfc_crtn.h3
-rw-r--r--drivers/scsi/lpfc/lpfc_disc.h2
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c4
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c18
-rw-r--r--drivers/scsi/lpfc/lpfc_hw.h40
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c183
-rw-r--r--drivers/scsi/lpfc/lpfc_nportdisc.c69
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c295
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c217
-rw-r--r--drivers/scsi/lpfc/lpfc_version.h2
-rw-r--r--drivers/scsi/megaraid.c27
-rw-r--r--drivers/scsi/megaraid/Kconfig.megaraid2
-rw-r--r--drivers/scsi/megaraid/megaraid_mbox.c82
-rw-r--r--drivers/scsi/megaraid/megaraid_mbox.h4
-rw-r--r--drivers/scsi/ncr53c8xx.c749
-rw-r--r--drivers/scsi/ncr53c8xx.h1263
-rw-r--r--drivers/scsi/pcmcia/aha152x_stub.c99
-rw-r--r--drivers/scsi/pcmcia/fdomain_stub.c117
-rw-r--r--drivers/scsi/pcmcia/nsp_cs.c167
-rw-r--r--drivers/scsi/pcmcia/nsp_cs.h4
-rw-r--r--drivers/scsi/pcmcia/qlogic_stub.c127
-rw-r--r--drivers/scsi/pcmcia/sym53c500_cs.c133
-rw-r--r--drivers/scsi/pdc_adma.c11
-rw-r--r--drivers/scsi/qla2xxx/Kconfig69
-rw-r--r--drivers/scsi/qla2xxx/Makefile5
-rw-r--r--drivers/scsi/qla2xxx/ql2400.c111
-rw-r--r--drivers/scsi/qla2xxx/ql2400_fw.c12376
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h24
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h4
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c248
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c196
-rw-r--r--drivers/scsi/raid_class.c2
-rw-r--r--drivers/scsi/sata_mv.c12
-rw-r--r--drivers/scsi/sata_nv.c1
-rw-r--r--drivers/scsi/sata_promise.c21
-rw-r--r--drivers/scsi/sata_qstor.c9
-rw-r--r--drivers/scsi/sata_sil.c3
-rw-r--r--drivers/scsi/sata_sil24.c16
-rw-r--r--drivers/scsi/sata_sis.c1
-rw-r--r--drivers/scsi/sata_svw.c1
-rw-r--r--drivers/scsi/sata_sx4.c18
-rw-r--r--drivers/scsi/sata_uli.c1
-rw-r--r--drivers/scsi/sata_via.c1
-rw-r--r--drivers/scsi/sata_vsc.c1
-rw-r--r--drivers/scsi/scsi_devinfo.c5
-rw-r--r--drivers/scsi/scsi_error.c47
-rw-r--r--drivers/scsi/scsi_lib.c310
-rw-r--r--drivers/scsi/scsi_priv.h4
-rw-r--r--drivers/scsi/scsi_scan.c2
-rw-r--r--drivers/scsi/scsi_sysfs.c35
-rw-r--r--drivers/scsi/scsi_transport_fc.c8
-rw-r--r--drivers/scsi/scsi_transport_spi.c136
-rw-r--r--drivers/scsi/sd.c91
-rw-r--r--drivers/scsi/sg.c686
-rw-r--r--drivers/scsi/sr.c4
-rw-r--r--drivers/scsi/sr_vendor.c4
-rw-r--r--drivers/scsi/st.c279
-rw-r--r--drivers/scsi/st.h14
-rw-r--r--drivers/scsi/sun3_NCR5380.c7
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_defs.h2
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_fw.c18
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_fw.h6
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_fw1.h48
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_fw2.h52
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_glue.c117
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_glue.h2
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_hipd.c164
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_hipd.h104
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_malloc.c4
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_nvram.c29
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_nvram.h4
-rw-r--r--drivers/scsi/sym53c8xx_comm.h792
-rw-r--r--drivers/scsi/sym53c8xx_defs.h1320
-rw-r--r--drivers/serial/mpc52xx_uart.c28
-rw-r--r--drivers/serial/serial_cs.c119
-rw-r--r--drivers/telephony/ixj_pcmcia.c112
-rw-r--r--drivers/usb/Makefile1
-rw-r--r--drivers/usb/atm/Kconfig13
-rw-r--r--drivers/usb/atm/Makefile1
-rw-r--r--drivers/usb/atm/cxacru.c1
-rw-r--r--drivers/usb/atm/speedtch.c1
-rw-r--r--drivers/usb/atm/ueagle-atm.c1820
-rw-r--r--drivers/usb/atm/usbatm.c4
-rw-r--r--drivers/usb/atm/xusbatm.c1
-rw-r--r--drivers/usb/class/audio.c1
-rw-r--r--drivers/usb/class/cdc-acm.c232
-rw-r--r--drivers/usb/class/cdc-acm.h33
-rw-r--r--drivers/usb/class/usb-midi.c1
-rw-r--r--drivers/usb/class/usblp.c47
-rw-r--r--drivers/usb/core/Makefile2
-rw-r--r--drivers/usb/core/buffer.c3
-rw-r--r--drivers/usb/core/devices.c24
-rw-r--r--drivers/usb/core/devio.c3
-rw-r--r--drivers/usb/core/driver.c472
-rw-r--r--drivers/usb/core/hcd.c10
-rw-r--r--drivers/usb/core/hcd.h1
-rw-r--r--drivers/usb/core/hub.c486
-rw-r--r--drivers/usb/core/hub.h3
-rw-r--r--drivers/usb/core/message.c6
-rw-r--r--drivers/usb/core/usb.c544
-rw-r--r--drivers/usb/core/usb.h6
-rw-r--r--drivers/usb/gadget/dummy_hcd.c91
-rw-r--r--drivers/usb/gadget/file_storage.c93
-rw-r--r--drivers/usb/gadget/serial.c2
-rw-r--r--drivers/usb/host/Makefile4
-rw-r--r--drivers/usb/host/ehci-hcd.c9
-rw-r--r--drivers/usb/host/ehci-hub.c4
-rw-r--r--drivers/usb/host/ehci-pci.c20
-rw-r--r--drivers/usb/host/ehci-q.c14
-rw-r--r--drivers/usb/host/hc_crisv10.c2
-rw-r--r--drivers/usb/host/isp116x-hcd.c422
-rw-r--r--drivers/usb/host/isp116x.h83
-rw-r--r--drivers/usb/host/ohci-hcd.c14
-rw-r--r--drivers/usb/host/ohci-hub.c2
-rw-r--r--drivers/usb/host/ohci-pxa27x.c121
-rw-r--r--drivers/usb/host/pci-quirks.c6
-rw-r--r--drivers/usb/host/sl811-hcd.c14
-rw-r--r--drivers/usb/host/sl811_cs.c115
-rw-r--r--drivers/usb/host/uhci-debug.c14
-rw-r--r--drivers/usb/host/uhci-hcd.c32
-rw-r--r--drivers/usb/host/uhci-hcd.h32
-rw-r--r--drivers/usb/host/uhci-q.c30
-rw-r--r--drivers/usb/image/mdc800.c1
-rw-r--r--drivers/usb/image/microtek.c1
-rw-r--r--drivers/usb/input/Kconfig14
-rw-r--r--drivers/usb/input/Makefile1
-rw-r--r--drivers/usb/input/acecad.c1
-rw-r--r--drivers/usb/input/aiptek.c7
-rw-r--r--drivers/usb/input/appletouch.c1
-rw-r--r--drivers/usb/input/ati_remote.c22
-rw-r--r--drivers/usb/input/ati_remote2.c477
-rw-r--r--drivers/usb/input/fixp-arith.h2
-rw-r--r--drivers/usb/input/hid-core.c3
-rw-r--r--drivers/usb/input/hid-input.c4
-rw-r--r--drivers/usb/input/hiddev.c1
-rw-r--r--drivers/usb/input/itmtouch.c1
-rw-r--r--drivers/usb/input/kbtab.c1
-rw-r--r--drivers/usb/input/keyspan_remote.c3
-rw-r--r--drivers/usb/input/mtouchusb.c1
-rw-r--r--drivers/usb/input/powermate.c1
-rw-r--r--drivers/usb/input/touchkitusb.c149
-rw-r--r--drivers/usb/input/usbkbd.c1
-rw-r--r--drivers/usb/input/usbmouse.c1
-rw-r--r--drivers/usb/input/wacom.c1
-rw-r--r--drivers/usb/input/xpad.c7
-rw-r--r--drivers/usb/input/yealink.c1
-rw-r--r--drivers/usb/media/dabusb.c1
-rw-r--r--drivers/usb/media/dsbr100.c1
-rw-r--r--drivers/usb/media/ibmcam.c2
-rw-r--r--drivers/usb/media/konicawc.c6
-rw-r--r--drivers/usb/media/ov511.c3
-rw-r--r--drivers/usb/media/pwc/pwc-ctrl.c2
-rw-r--r--drivers/usb/media/pwc/pwc-if.c1
-rw-r--r--drivers/usb/media/se401.c1
-rw-r--r--drivers/usb/media/sn9c102_core.c24
-rw-r--r--drivers/usb/media/stv680.c1
-rw-r--r--drivers/usb/media/stv680.h6
-rw-r--r--drivers/usb/media/usbvideo.c4
-rw-r--r--drivers/usb/media/vicam.c1
-rw-r--r--drivers/usb/media/w9968cf.c11
-rw-r--r--drivers/usb/misc/auerswald.c5
-rw-r--r--drivers/usb/misc/cytherm.c1
-rw-r--r--drivers/usb/misc/emi26.c1
-rw-r--r--drivers/usb/misc/emi62.c1
-rw-r--r--drivers/usb/misc/idmouse.c1
-rw-r--r--drivers/usb/misc/ldusb.c1
-rw-r--r--drivers/usb/misc/legousbtower.c1
-rw-r--r--drivers/usb/misc/phidgetkit.c1
-rw-r--r--drivers/usb/misc/phidgetservo.c1
-rw-r--r--drivers/usb/misc/rio500.c5
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb.c11
-rw-r--r--drivers/usb/misc/usblcd.c1
-rw-r--r--drivers/usb/misc/usbled.c1
-rw-r--r--drivers/usb/misc/usbtest.c1
-rw-r--r--drivers/usb/misc/uss720.c1
-rw-r--r--drivers/usb/mon/mon_text.c19
-rw-r--r--drivers/usb/net/asix.c5
-rw-r--r--drivers/usb/net/catc.c1
-rw-r--r--drivers/usb/net/cdc_ether.c1
-rw-r--r--drivers/usb/net/cdc_subset.c1
-rw-r--r--drivers/usb/net/gl620a.c1
-rw-r--r--drivers/usb/net/kaweth.c1
-rw-r--r--drivers/usb/net/net1080.c1
-rw-r--r--drivers/usb/net/pegasus.c144
-rw-r--r--drivers/usb/net/plusb.c1
-rw-r--r--drivers/usb/net/rndis_host.c1
-rw-r--r--drivers/usb/net/rtl8150.c1
-rw-r--r--drivers/usb/net/zaurus.c1
-rw-r--r--drivers/usb/net/zd1201.c11
-rw-r--r--drivers/usb/serial/airprime.c2
-rw-r--r--drivers/usb/serial/anydata.c2
-rw-r--r--drivers/usb/serial/belkin_sa.c2
-rw-r--r--drivers/usb/serial/cp2101.c2
-rw-r--r--drivers/usb/serial/cyberjack.c2
-rw-r--r--drivers/usb/serial/cypress_m8.c1
-rw-r--r--drivers/usb/serial/digi_acceleport.c2
-rw-r--r--drivers/usb/serial/empeg.c2
-rw-r--r--drivers/usb/serial/ftdi_sio.c6
-rw-r--r--drivers/usb/serial/ftdi_sio.h15
-rw-r--r--drivers/usb/serial/garmin_gps.c2
-rw-r--r--drivers/usb/serial/generic.c2
-rw-r--r--drivers/usb/serial/hp4x.c2
-rw-r--r--drivers/usb/serial/io_edgeport.c6
-rw-r--r--drivers/usb/serial/io_edgeport.h3
-rw-r--r--drivers/usb/serial/io_fw_boot2.h2
-rw-r--r--drivers/usb/serial/io_ti.c4
-rw-r--r--drivers/usb/serial/ipaq.c2
-rw-r--r--drivers/usb/serial/ipw.c2
-rw-r--r--drivers/usb/serial/ir-usb.c2
-rw-r--r--drivers/usb/serial/keyspan.h2
-rw-r--r--drivers/usb/serial/keyspan_pda.c2
-rw-r--r--drivers/usb/serial/kl5kusb105.c2
-rw-r--r--drivers/usb/serial/kobil_sct.c2
-rw-r--r--drivers/usb/serial/mct_u232.c2
-rw-r--r--drivers/usb/serial/omninet.c2
-rw-r--r--drivers/usb/serial/option.c2
-rw-r--r--drivers/usb/serial/pl2303.c4
-rw-r--r--drivers/usb/serial/safe_serial.c6
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.c9
-rw-r--r--drivers/usb/serial/usb-serial.c48
-rw-r--r--drivers/usb/serial/usb-serial.h4
-rw-r--r--drivers/usb/serial/visor.c2
-rw-r--r--drivers/usb/serial/whiteheat.c2
-rw-r--r--drivers/usb/storage/Kconfig23
-rw-r--r--drivers/usb/storage/Makefile5
-rw-r--r--drivers/usb/storage/alauda.c1119
-rw-r--r--drivers/usb/storage/alauda.h100
-rw-r--r--drivers/usb/storage/debug.c1
-rw-r--r--drivers/usb/storage/initializers.h4
-rw-r--r--drivers/usb/storage/libusual.c266
-rw-r--r--drivers/usb/storage/onetouch.c27
-rw-r--r--drivers/usb/storage/protocol.h14
-rw-r--r--drivers/usb/storage/sddr09.c214
-rw-r--r--drivers/usb/storage/sddr09.h15
-rw-r--r--drivers/usb/storage/transport.h31
-rw-r--r--drivers/usb/storage/unusual_devs.h74
-rw-r--r--drivers/usb/storage/usb.c160
-rw-r--r--drivers/usb/storage/usb.h40
-rw-r--r--drivers/usb/usb-skeleton.c29
-rw-r--r--drivers/video/aty/atyfb_base.c2
-rw-r--r--drivers/video/aty/radeon_base.c16
-rw-r--r--drivers/video/matrox/matroxfb_maven.c11
-rw-r--r--drivers/w1/dscore.c1
-rw-r--r--drivers/w1/w1.c14
723 files changed, 47108 insertions, 20220 deletions
diff --git a/drivers/acorn/char/pcf8583.c b/drivers/acorn/char/pcf8583.c
index e26f007a1417..9b49f316ae92 100644
--- a/drivers/acorn/char/pcf8583.c
+++ b/drivers/acorn/char/pcf8583.c
@@ -257,9 +257,10 @@ pcf8583_command(struct i2c_client *client, unsigned int cmd, void *arg)
 }
 
 static struct i2c_driver pcf8583_driver = {
-	.name		= "PCF8583",
+	.driver = {
+		.name	= "PCF8583",
+	},
 	.id		= I2C_DRIVERID_PCF8583,
-	.flags		= I2C_DF_NOTIFY,
 	.attach_adapter	= pcf8583_probe,
 	.detach_client	= pcf8583_detach,
 	.command	= pcf8583_command
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c
index 27ec12c1fab0..b69a8cad82b7 100644
--- a/drivers/acpi/container.c
+++ b/drivers/acpi/container.c
@@ -172,21 +172,21 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context)
 			if (ACPI_FAILURE(status) || !device) {
 				result = container_device_add(&device, handle);
 				if (!result)
-					kobject_hotplug(&device->kobj,
-							KOBJ_ONLINE);
+					kobject_uevent(&device->kobj,
+						       KOBJ_ONLINE);
 				else
 					printk("Failed to add container\n");
 			}
 		} else {
 			if (ACPI_SUCCESS(status)) {
 				/* device exist and this is a remove request */
-				kobject_hotplug(&device->kobj, KOBJ_OFFLINE);
+				kobject_uevent(&device->kobj, KOBJ_OFFLINE);
 			}
 		}
 		break;
 	case ACPI_NOTIFY_EJECT_REQUEST:
 		if (!acpi_bus_get_device(handle, &device) && device) {
-			kobject_hotplug(&device->kobj, KOBJ_OFFLINE);
+			kobject_uevent(&device->kobj, KOBJ_OFFLINE);
 		}
 		break;
 	default:
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index 0c561c571f29..1278aca96fe3 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -748,7 +748,7 @@ int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device)
 		return_VALUE(-ENODEV);
 
 	if ((pr->id >= 0) && (pr->id < NR_CPUS)) {
-		kobject_hotplug(&(*device)->kobj, KOBJ_ONLINE);
+		kobject_uevent(&(*device)->kobj, KOBJ_ONLINE);
 	}
 	return_VALUE(0);
 }
@@ -788,13 +788,13 @@ acpi_processor_hotplug_notify(acpi_handle handle, u32 event, void *data)
 		}
 
 		if (pr->id >= 0 && (pr->id < NR_CPUS)) {
-			kobject_hotplug(&device->kobj, KOBJ_OFFLINE);
+			kobject_uevent(&device->kobj, KOBJ_OFFLINE);
 			break;
 		}
 
 		result = acpi_processor_start(device);
 		if ((!result) && ((pr->id >= 0) && (pr->id < NR_CPUS))) {
-			kobject_hotplug(&device->kobj, KOBJ_ONLINE);
+			kobject_uevent(&device->kobj, KOBJ_ONLINE);
 		} else {
 			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
 					  "Device [%s] failed to start\n",
@@ -818,7 +818,7 @@ acpi_processor_hotplug_notify(acpi_handle handle, u32 event, void *data)
 		}
 
 		if ((pr->id < NR_CPUS) && (cpu_present(pr->id)))
-			kobject_hotplug(&device->kobj, KOBJ_OFFLINE);
+			kobject_uevent(&device->kobj, KOBJ_OFFLINE);
 		break;
 	default:
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 31218e1d2a18..0745d20afb8c 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -78,7 +78,7 @@ static struct kobj_type ktype_acpi_ns = {
 	.release = acpi_device_release,
 };
 
-static int namespace_hotplug(struct kset *kset, struct kobject *kobj,
+static int namespace_uevent(struct kset *kset, struct kobject *kobj,
 			     char **envp, int num_envp, char *buffer,
 			     int buffer_size)
 {
@@ -89,8 +89,8 @@ static int namespace_hotplug(struct kset *kset, struct kobject *kobj,
 	if (!dev->driver)
 		return 0;
 
-	if (add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, &len,
-				"PHYSDEVDRIVER=%s", dev->driver->name))
+	if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len,
+			   "PHYSDEVDRIVER=%s", dev->driver->name))
 		return -ENOMEM;
 
 	envp[i] = NULL;
@@ -98,8 +98,8 @@ static int namespace_hotplug(struct kset *kset, struct kobject *kobj,
 	return 0;
 }
 
-static struct kset_hotplug_ops namespace_hotplug_ops = {
-	.hotplug = &namespace_hotplug,
+static struct kset_uevent_ops namespace_uevent_ops = {
+	.uevent = &namespace_uevent,
 };
 
 static struct kset acpi_namespace_kset = {
@@ -108,7 +108,7 @@ static struct kset acpi_namespace_kset = {
 		 },
 	.subsys = &acpi_subsys,
 	.ktype = &ktype_acpi_ns,
-	.hotplug_ops = &namespace_hotplug_ops,
+	.uevent_ops = &namespace_uevent_ops,
 };
 
 static void acpi_device_register(struct acpi_device *device,
@@ -347,7 +347,7 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
 }
 
 /* --------------------------------------------------------------------------
-		ACPI hotplug sysfs device file support
+		ACPI sysfs device file support
    -------------------------------------------------------------------------- */
 static ssize_t acpi_eject_store(struct acpi_device *device,
 				const char *buf, size_t count);
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index 934149c1512b..f0eff3dac58d 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -19,11 +19,11 @@ config PREVENT_FIRMWARE_BUILD
 	  If unsure say Y here.
 
 config FW_LOADER
-	tristate "Hotplug firmware loading support"
+	tristate "Userspace firmware loading support"
 	select HOTPLUG
 	---help---
 	  This option is provided for the case where no in-kernel-tree modules
-	  require hotplug firmware loading support, but a module built outside
+	  require userspace firmware loading support, but a module built outside
 	  the kernel tree does.
 
 config DEBUG_DRIVER
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index fa601b085eba..29f6af554e71 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -152,7 +152,11 @@ static ssize_t driver_unbind(struct device_driver *drv,
 
 	dev = bus_find_device(bus, NULL, (void *)buf, driver_helper);
 	if (dev && dev->driver == drv) {
+		if (dev->parent)	/* Needed for USB */
+			down(&dev->parent->sem);
 		device_release_driver(dev);
+		if (dev->parent)
+			up(&dev->parent->sem);
 		err = count;
 	}
 	put_device(dev);
@@ -175,9 +179,13 @@ static ssize_t driver_bind(struct device_driver *drv,
 
 	dev = bus_find_device(bus, NULL, (void *)buf, driver_helper);
 	if (dev && dev->driver == NULL) {
+		if (dev->parent)	/* Needed for USB */
+			down(&dev->parent->sem);
 		down(&dev->sem);
 		err = driver_probe_device(drv, dev);
 		up(&dev->sem);
+		if (dev->parent)
+			up(&dev->parent->sem);
 	}
 	put_device(dev);
 	put_bus(bus);
@@ -420,6 +428,26 @@ static void driver_remove_attrs(struct bus_type * bus, struct device_driver * dr
 	}
 }
 
+#ifdef CONFIG_HOTPLUG
+/*
+ * Thanks to drivers making their tables __devinit, we can't allow manual
+ * bind and unbind from userspace unless CONFIG_HOTPLUG is enabled.
+ */
+static void add_bind_files(struct device_driver *drv)
+{
+	driver_create_file(drv, &driver_attr_unbind);
+	driver_create_file(drv, &driver_attr_bind);
+}
+
+static void remove_bind_files(struct device_driver *drv)
+{
+	driver_remove_file(drv, &driver_attr_bind);
+	driver_remove_file(drv, &driver_attr_unbind);
+}
+#else
+static inline void add_bind_files(struct device_driver *drv) {}
+static inline void remove_bind_files(struct device_driver *drv) {}
+#endif
 
 /**
  *	bus_add_driver - Add a driver to the bus.
@@ -449,8 +477,7 @@ int bus_add_driver(struct device_driver * drv)
 		module_add_driver(drv->owner, drv);
 
 		driver_add_attrs(bus, drv);
-		driver_create_file(drv, &driver_attr_unbind);
-		driver_create_file(drv, &driver_attr_bind);
+		add_bind_files(drv);
 	}
 	return error;
 }
@@ -468,8 +495,7 @@ int bus_add_driver(struct device_driver * drv)
 void bus_remove_driver(struct device_driver * drv)
 {
 	if (drv->bus) {
-		driver_remove_file(drv, &driver_attr_bind);
-		driver_remove_file(drv, &driver_attr_unbind);
+		remove_bind_files(drv);
 		driver_remove_attrs(drv->bus, drv);
 		klist_remove(&drv->knode_bus);
 		pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name);
@@ -484,8 +510,13 @@ void bus_remove_driver(struct device_driver * drv)
 /* Helper for bus_rescan_devices's iter */
 static int bus_rescan_devices_helper(struct device *dev, void *data)
 {
-	if (!dev->driver)
+	if (!dev->driver) {
+		if (dev->parent)	/* Needed for USB */
+			down(&dev->parent->sem);
 		device_attach(dev);
+		if (dev->parent)
+			up(&dev->parent->sem);
+	}
 	return 0;
 }
 
diff --git a/drivers/base/class.c b/drivers/base/class.c
index db65fd0babe9..df7fdabd0730 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -178,7 +178,7 @@ static void class_device_create_release(struct class_device *class_dev)
 }
 
 /* needed to allow these devices to have parent class devices */
-static int class_device_create_hotplug(struct class_device *class_dev,
+static int class_device_create_uevent(struct class_device *class_dev,
 				       char **envp, int num_envp,
 				       char *buffer, int buffer_size)
 {
@@ -331,7 +331,7 @@ static struct kobj_type ktype_class_device = {
 	.release	= class_dev_release,
 };
 
-static int class_hotplug_filter(struct kset *kset, struct kobject *kobj)
+static int class_uevent_filter(struct kset *kset, struct kobject *kobj)
 {
 	struct kobj_type *ktype = get_ktype(kobj);
 
@@ -343,14 +343,14 @@ static int class_hotplug_filter(struct kset *kset, struct kobject *kobj)
 	return 0;
 }
 
-static const char *class_hotplug_name(struct kset *kset, struct kobject *kobj)
+static const char *class_uevent_name(struct kset *kset, struct kobject *kobj)
 {
 	struct class_device *class_dev = to_class_dev(kobj);
 
 	return class_dev->class->name;
 }
 
-static int class_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
+static int class_uevent(struct kset *kset, struct kobject *kobj, char **envp,
 			 int num_envp, char *buffer, int buffer_size)
 {
 	struct class_device *class_dev = to_class_dev(kobj);
@@ -365,29 +365,29 @@ static int class_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
 		struct device *dev = class_dev->dev;
 		char *path = kobject_get_path(&dev->kobj, GFP_KERNEL);
 
-		add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size,
-				    &length, "PHYSDEVPATH=%s", path);
+		add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
+			       &length, "PHYSDEVPATH=%s", path);
 		kfree(path);
 
 		if (dev->bus)
-			add_hotplug_env_var(envp, num_envp, &i,
-					    buffer, buffer_size, &length,
-					    "PHYSDEVBUS=%s", dev->bus->name);
+			add_uevent_var(envp, num_envp, &i,
+				       buffer, buffer_size, &length,
+				       "PHYSDEVBUS=%s", dev->bus->name);
 
 		if (dev->driver)
-			add_hotplug_env_var(envp, num_envp, &i,
-					    buffer, buffer_size, &length,
-					    "PHYSDEVDRIVER=%s", dev->driver->name);
+			add_uevent_var(envp, num_envp, &i,
+				       buffer, buffer_size, &length,
+				       "PHYSDEVDRIVER=%s", dev->driver->name);
 	}
 
 	if (MAJOR(class_dev->devt)) {
-		add_hotplug_env_var(envp, num_envp, &i,
-				    buffer, buffer_size, &length,
-				    "MAJOR=%u", MAJOR(class_dev->devt));
+		add_uevent_var(envp, num_envp, &i,
+			       buffer, buffer_size, &length,
+			       "MAJOR=%u", MAJOR(class_dev->devt));
 
-		add_hotplug_env_var(envp, num_envp, &i,
-				    buffer, buffer_size, &length,
-				    "MINOR=%u", MINOR(class_dev->devt));
+		add_uevent_var(envp, num_envp, &i,
+			       buffer, buffer_size, &length,
+			       "MINOR=%u", MINOR(class_dev->devt));
 	}
 
 	/* terminate, set to next free slot, shrink available space */
@@ -397,30 +397,30 @@ static int class_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
 	buffer = &buffer[length];
 	buffer_size -= length;
 
-	if (class_dev->hotplug) {
+	if (class_dev->uevent) {
 		/* have the class device specific function add its stuff */
-		retval = class_dev->hotplug(class_dev, envp, num_envp,
+		retval = class_dev->uevent(class_dev, envp, num_envp,
 					    buffer, buffer_size);
 		if (retval)
-			pr_debug("class_dev->hotplug() returned %d\n", retval);
-	} else if (class_dev->class->hotplug) {
+			pr_debug("class_dev->uevent() returned %d\n", retval);
+	} else if (class_dev->class->uevent) {
 		/* have the class specific function add its stuff */
-		retval = class_dev->class->hotplug(class_dev, envp, num_envp,
+		retval = class_dev->class->uevent(class_dev, envp, num_envp,
 						   buffer, buffer_size);
 		if (retval)
-			pr_debug("class->hotplug() returned %d\n", retval);
+			pr_debug("class->uevent() returned %d\n", retval);
 	}
 
 	return retval;
 }
 
-static struct kset_hotplug_ops class_hotplug_ops = {
-	.filter =	class_hotplug_filter,
-	.name =		class_hotplug_name,
-	.hotplug =	class_hotplug,
+static struct kset_uevent_ops class_uevent_ops = {
+	.filter =	class_uevent_filter,
+	.name =		class_uevent_name,
+	.uevent =	class_uevent,
 };
 
-static decl_subsys(class_obj, &ktype_class_device, &class_hotplug_ops);
+static decl_subsys(class_obj, &ktype_class_device, &class_uevent_ops);
 
 
 static int class_device_add_attrs(struct class_device * cd)
@@ -464,7 +464,7 @@ static ssize_t show_dev(struct class_device *class_dev, char *buf)
 static ssize_t store_uevent(struct class_device *class_dev,
 			    const char *buf, size_t count)
 {
-	kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
+	kobject_uevent(&class_dev->kobj, KOBJ_ADD);
 	return count;
 }
 
@@ -559,7 +559,7 @@ int class_device_add(struct class_device *class_dev)
 				  class_name);
 	}
 
-	kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
+	kobject_uevent(&class_dev->kobj, KOBJ_ADD);
 
 	/* notify any interfaces this device is now here */
 	if (parent_class) {
@@ -632,7 +632,7 @@ struct class_device *class_device_create(struct class *cls,
 	class_dev->class = cls;
 	class_dev->parent = parent;
 	class_dev->release = class_device_create_release;
-	class_dev->hotplug = class_device_create_hotplug;
+	class_dev->uevent = class_device_create_uevent;
 
 	va_start(args, fmt);
 	vsnprintf(class_dev->class_id, BUS_ID_SIZE, fmt, args);
@@ -674,7 +674,7 @@ void class_device_del(struct class_device *class_dev)
 		class_device_remove_file(class_dev, class_dev->devt_attr);
 	class_device_remove_attrs(class_dev);
 
-	kobject_hotplug(&class_dev->kobj, KOBJ_REMOVE);
+	kobject_uevent(&class_dev->kobj, KOBJ_REMOVE);
 	kobject_del(&class_dev->kobj);
 
 	class_device_put(parent_device);
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 8615b42b517a..fd8059920dbf 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -90,7 +90,7 @@ static struct kobj_type ktype_device = {
 };
 
 
-static int dev_hotplug_filter(struct kset *kset, struct kobject *kobj)
+static int dev_uevent_filter(struct kset *kset, struct kobject *kobj)
 {
 	struct kobj_type *ktype = get_ktype(kobj);
 
@@ -102,14 +102,14 @@ static int dev_hotplug_filter(struct kset *kset, struct kobject *kobj)
 	return 0;
 }
 
-static const char *dev_hotplug_name(struct kset *kset, struct kobject *kobj)
+static const char *dev_uevent_name(struct kset *kset, struct kobject *kobj)
 {
 	struct device *dev = to_dev(kobj);
 
 	return dev->bus->name;
 }
 
-static int dev_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
+static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp,
 			int num_envp, char *buffer, int buffer_size)
 {
 	struct device *dev = to_dev(kobj);
@@ -119,15 +119,15 @@ static int dev_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
 
 	/* add bus name of physical device */
 	if (dev->bus)
-		add_hotplug_env_var(envp, num_envp, &i,
-				    buffer, buffer_size, &length,
-				    "PHYSDEVBUS=%s", dev->bus->name);
+		add_uevent_var(envp, num_envp, &i,
+			       buffer, buffer_size, &length,
+			       "PHYSDEVBUS=%s", dev->bus->name);
 
 	/* add driver name of physical device */
 	if (dev->driver)
-		add_hotplug_env_var(envp, num_envp, &i,
-				    buffer, buffer_size, &length,
-				    "PHYSDEVDRIVER=%s", dev->driver->name);
+		add_uevent_var(envp, num_envp, &i,
+			       buffer, buffer_size, &length,
+			       "PHYSDEVDRIVER=%s", dev->driver->name);
 
 	/* terminate, set to next free slot, shrink available space */
 	envp[i] = NULL;
@@ -136,11 +136,11 @@ static int dev_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
 	buffer = &buffer[length];
 	buffer_size -= length;
 
-	if (dev->bus && dev->bus->hotplug) {
+	if (dev->bus && dev->bus->uevent) {
 		/* have the bus specific function add its stuff */
-		retval = dev->bus->hotplug (dev, envp, num_envp, buffer, buffer_size);
+		retval = dev->bus->uevent(dev, envp, num_envp, buffer, buffer_size);
 			if (retval) {
-			pr_debug ("%s - hotplug() returned %d\n",
+			pr_debug ("%s - uevent() returned %d\n",
 				  __FUNCTION__, retval);
 		}
 	}
@@ -148,16 +148,16 @@ static int dev_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
 	return retval;
 }
 
-static struct kset_hotplug_ops device_hotplug_ops = {
-	.filter =	dev_hotplug_filter,
-	.name =		dev_hotplug_name,
-	.hotplug =	dev_hotplug,
+static struct kset_uevent_ops device_uevent_ops = {
+	.filter =	dev_uevent_filter,
+	.name =		dev_uevent_name,
+	.uevent =	dev_uevent,
 };
 
 static ssize_t store_uevent(struct device *dev, struct device_attribute *attr,
 			    const char *buf, size_t count)
 {
-	kobject_hotplug(&dev->kobj, KOBJ_ADD);
+	kobject_uevent(&dev->kobj, KOBJ_ADD);
 	return count;
 }
 
@@ -165,7 +165,7 @@ static ssize_t store_uevent(struct device *dev, struct device_attribute *attr,
  *	device_subsys - structure to be registered with kobject core.
  */
 
-decl_subsys(devices, &ktype_device, &device_hotplug_ops);
+decl_subsys(devices, &ktype_device, &device_uevent_ops);
 
 
 /**
@@ -274,7 +274,7 @@ int device_add(struct device *dev)
 	dev->uevent_attr.store = store_uevent;
 	device_create_file(dev, &dev->uevent_attr);
 
-	kobject_hotplug(&dev->kobj, KOBJ_ADD);
+	kobject_uevent(&dev->kobj, KOBJ_ADD);
 	if ((error = device_pm_add(dev)))
 		goto PMError;
 	if ((error = bus_add_device(dev)))
@@ -291,7 +291,7 @@ int device_add(struct device *dev)
  BusError:
 	device_pm_remove(dev);
  PMError:
-	kobject_hotplug(&dev->kobj, KOBJ_REMOVE);
+	kobject_uevent(&dev->kobj, KOBJ_REMOVE);
 	kobject_del(&dev->kobj);
  Error:
 	if (parent)
@@ -374,7 +374,7 @@ void device_del(struct device * dev)
 		platform_notify_remove(dev);
 	bus_remove_device(dev);
 	device_pm_remove(dev);
-	kobject_hotplug(&dev->kobj, KOBJ_REMOVE);
+	kobject_uevent(&dev->kobj, KOBJ_REMOVE);
 	kobject_del(&dev->kobj);
 	if (parent)
 		put_device(parent);
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index a95844790f7b..281d26784d25 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -41,14 +41,14 @@ static ssize_t store_online(struct sys_device *dev, const char *buf,
 	case '0':
 		ret = cpu_down(cpu->sysdev.id);
 		if (!ret)
-			kobject_hotplug(&dev->kobj, KOBJ_OFFLINE);
+			kobject_uevent(&dev->kobj, KOBJ_OFFLINE);
 		break;
 	case '1':
 		ret = smp_prepare_cpu(cpu->sysdev.id);
 		if (!ret)
 			ret = cpu_up(cpu->sysdev.id);
 		if (!ret)
-			kobject_hotplug(&dev->kobj, KOBJ_ONLINE);
+			kobject_uevent(&dev->kobj, KOBJ_ONLINE);
 		break;
 	default:
 		ret = -EINVAL;
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 3b419c9a1e7e..2b905016664d 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -65,7 +65,8 @@ void device_bind_driver(struct device * dev)
  *	This function returns 1 if a match is found, an error if one
  *	occurs (that is not -ENODEV or -ENXIO), and 0 otherwise.
  *
- *	This function must be called with @dev->sem held.
+ *	This function must be called with @dev->sem held.  When called
+ *	for a USB interface, @dev->parent->sem must be held as well.
  */
 int driver_probe_device(struct device_driver * drv, struct device * dev)
 {
@@ -123,6 +124,8 @@ static int __device_attach(struct device_driver * drv, void * data)
  *
  *	Returns 1 if the device was bound to a driver;
  *	0 if no matching device was found; error code otherwise.
+ *
+ *	When called for a USB interface, @dev->parent->sem must be held.
  */
 int device_attach(struct device * dev)
 {
@@ -152,10 +155,14 @@ static int __driver_attach(struct device * dev, void * data)
 	 * is an error.
 	 */
 
+	if (dev->parent)	/* Needed for USB */
+		down(&dev->parent->sem);
 	down(&dev->sem);
 	if (!dev->driver)
 		driver_probe_device(drv, dev);
 	up(&dev->sem);
+	if (dev->parent)
+		up(&dev->parent->sem);
 
 	return 0;
 }
@@ -181,6 +188,8 @@ void driver_attach(struct device_driver * drv)
  *	Manually detach device from driver.
  *
  *	__device_release_driver() must be called with @dev->sem held.
+ *	When called for a USB interface, @dev->parent->sem must be held
+ *	as well.
  */
 
 static void __device_release_driver(struct device * dev)
@@ -233,10 +242,14 @@ void driver_detach(struct device_driver * drv)
 		get_device(dev);
 		spin_unlock(&drv->klist_devices.k_lock);
 
+		if (dev->parent)	/* Needed for USB */
+			down(&dev->parent->sem);
 		down(&dev->sem);
 		if (dev->driver == drv)
 			__device_release_driver(dev);
 		up(&dev->sem);
+		if (dev->parent)
+			up(&dev->parent->sem);
 		put_device(dev);
 	}
 }
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 59dacb6552c0..5b3d5e9ddcb6 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -85,17 +85,17 @@ firmware_timeout_store(struct class *class, const char *buf, size_t count)
 static CLASS_ATTR(timeout, 0644, firmware_timeout_show, firmware_timeout_store);
 
 static void  fw_class_dev_release(struct class_device *class_dev);
-int firmware_class_hotplug(struct class_device *dev, char **envp,
+int firmware_class_uevent(struct class_device *dev, char **envp,
 			   int num_envp, char *buffer, int buffer_size);
 
 static struct class firmware_class = {
 	.name		= "firmware",
-	.hotplug	= firmware_class_hotplug,
+	.uevent	= firmware_class_uevent,
 	.release	= fw_class_dev_release,
 };
 
 int
-firmware_class_hotplug(struct class_device *class_dev, char **envp,
+firmware_class_uevent(struct class_device *class_dev, char **envp,
 		       int num_envp, char *buffer, int buffer_size)
 {
 	struct firmware_priv *fw_priv = class_get_devdata(class_dev);
@@ -104,13 +104,12 @@ firmware_class_hotplug(struct class_device *class_dev, char **envp,
 	if (!test_bit(FW_STATUS_READY, &fw_priv->status))
 		return -ENODEV;
 
-	if (add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, &len,
-			"FIRMWARE=%s", fw_priv->fw_id))
+	if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len,
+			   "FIRMWARE=%s", fw_priv->fw_id))
 		return -ENOMEM;
-	if (add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, &len,
-			"TIMEOUT=%i", loading_timeout))
+	if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len,
+			   "TIMEOUT=%i", loading_timeout))
 		return -ENOMEM;
-
 	envp[i] = NULL;
 
 	return 0;
@@ -352,7 +351,7 @@ error_kfree:
 
 static int
 fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p,
-		      const char *fw_name, struct device *device, int hotplug)
+		      const char *fw_name, struct device *device, int uevent)
 {
 	struct class_device *class_dev;
 	struct firmware_priv *fw_priv;
@@ -384,7 +383,7 @@ fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p,
 		goto error_unreg;
 	}
 
-	if (hotplug)
+	if (uevent)
                 set_bit(FW_STATUS_READY, &fw_priv->status);
         else
                 set_bit(FW_STATUS_READY_NOHOTPLUG, &fw_priv->status);
@@ -399,7 +398,7 @@ out:
 
 static int
 _request_firmware(const struct firmware **firmware_p, const char *name,
-		 struct device *device, int hotplug)
+		 struct device *device, int uevent)
 {
 	struct class_device *class_dev;
 	struct firmware_priv *fw_priv;
@@ -418,19 +417,19 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
 	}
 
 	retval = fw_setup_class_device(firmware, &class_dev, name, device,
-		hotplug);
+				       uevent);
 	if (retval)
 		goto error_kfree_fw;
 
 	fw_priv = class_get_devdata(class_dev);
 
-	if (hotplug) {
+	if (uevent) {
 		if (loading_timeout > 0) {
 			fw_priv->timeout.expires = jiffies + loading_timeout * HZ;
 			add_timer(&fw_priv->timeout);
 		}
 
-		kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
+		kobject_uevent(&class_dev->kobj, KOBJ_ADD);
 		wait_for_completion(&fw_priv->completion);
 		set_bit(FW_STATUS_DONE, &fw_priv->status);
 		del_timer_sync(&fw_priv->timeout);
@@ -456,7 +455,7 @@ out:
 }
 
 /**
- * request_firmware: - request firmware to hotplug and wait for it
+ * request_firmware: - send firmware request and wait for it
  * @firmware_p: pointer to firmware image
  * @name: name of firmware file
  * @device: device for which firmware is being loaded
@@ -466,7 +465,7 @@ out:
  *
  *      Should be called from user context where sleeping is allowed.
  *
- *      @name will be used as $FIRMWARE in the hotplug environment and
+ *      @name will be used as $FIRMWARE in the uevent environment and
  *      should be distinctive enough not to be confused with any other
  *      firmware image for this or any other device.
  **/
@@ -474,8 +473,8 @@ int
 request_firmware(const struct firmware **firmware_p, const char *name,
                  struct device *device)
 {
-        int hotplug = 1;
-        return _request_firmware(firmware_p, name, device, hotplug);
+        int uevent = 1;
+        return _request_firmware(firmware_p, name, device, uevent);
 }
 
 /**
@@ -518,7 +517,7 @@ struct firmware_work {
 	struct device *device;
 	void *context;
 	void (*cont)(const struct firmware *fw, void *context);
-	int hotplug;
+	int uevent;
 };
 
 static int
@@ -533,7 +532,7 @@ request_firmware_work_func(void *arg)
 	}
 	daemonize("%s/%s", "firmware", fw_work->name);
 	ret = _request_firmware(&fw, fw_work->name, fw_work->device,
-		fw_work->hotplug);
+		fw_work->uevent);
 	if (ret < 0)
 		fw_work->cont(NULL, fw_work->context);
 	else {
@@ -548,7 +547,7 @@ request_firmware_work_func(void *arg)
 /**
  * request_firmware_nowait: asynchronous version of request_firmware
  * @module: module requesting the firmware
- * @hotplug: invokes hotplug event to copy the firmware image if this flag
+ * @uevent: sends uevent to copy the firmware image if this flag
  *	is non-zero else the firmware copy must be done manually.
  * @name: name of firmware file
  * @device: device for which firmware is being loaded
@@ -562,7 +561,7 @@ request_firmware_work_func(void *arg)
  **/
 int
 request_firmware_nowait(
-	struct module *module, int hotplug,
+	struct module *module, int uevent,
 	const char *name, struct device *device, void *context,
 	void (*cont)(const struct firmware *fw, void *context))
 {
@@ -583,7 +582,7 @@ request_firmware_nowait(
 		.device = device,
 		.context = context,
 		.cont = cont,
-		.hotplug = hotplug,
+		.uevent = uevent,
 	};
 
 	ret = kernel_thread(request_firmware_work_func, fw_work,
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index bc3ca6a656b2..58801d718cc2 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -29,12 +29,12 @@ static struct sysdev_class memory_sysdev_class = {
 	set_kset_name(MEMORY_CLASS_NAME),
 };
 
-static char *memory_hotplug_name(struct kset *kset, struct kobject *kobj)
+static const char *memory_uevent_name(struct kset *kset, struct kobject *kobj)
 {
 	return MEMORY_CLASS_NAME;
 }
 
-static int memory_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
+static int memory_uevent(struct kset *kset, struct kobject *kobj, char **envp,
 			int num_envp, char *buffer, int buffer_size)
 {
 	int retval = 0;
@@ -42,19 +42,19 @@ static int memory_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
 	return retval;
 }
 
-static struct kset_hotplug_ops memory_hotplug_ops = {
-	.name		= memory_hotplug_name,
-	.hotplug	= memory_hotplug,
+static struct kset_uevent_ops memory_uevent_ops = {
+	.name		= memory_uevent_name,
+	.uevent		= memory_uevent,
 };
 
 static struct notifier_block *memory_chain;
 
-static int register_memory_notifier(struct notifier_block *nb)
+int register_memory_notifier(struct notifier_block *nb)
 {
         return notifier_chain_register(&memory_chain, nb);
 }
 
-static void unregister_memory_notifier(struct notifier_block *nb)
+void unregister_memory_notifier(struct notifier_block *nb)
 {
         notifier_chain_unregister(&memory_chain, nb);
 }
@@ -62,8 +62,7 @@ static void unregister_memory_notifier(struct notifier_block *nb)
 /*
  * register_memory - Setup a sysfs device for a memory block
  */
-static int
-register_memory(struct memory_block *memory, struct mem_section *section,
+int register_memory(struct memory_block *memory, struct mem_section *section,
 		struct node *root)
 {
 	int error;
@@ -431,7 +430,7 @@ int __init memory_dev_init(void)
 	unsigned int i;
 	int ret;
 
-	memory_sysdev_class.kset.hotplug_ops = &memory_hotplug_ops;
+	memory_sysdev_class.kset.uevent_ops = &memory_uevent_ops;
 	ret = sysdev_class_register(&memory_sysdev_class);
 
 	/*
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 8827dafba945..0f81731bdfa8 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -25,6 +25,7 @@
 struct device platform_bus = {
 	.bus_id		= "platform",
 };
+EXPORT_SYMBOL_GPL(platform_bus);
 
 /**
  *	platform_get_resource - get a resource for a device
@@ -49,6 +50,7 @@ platform_get_resource(struct platform_device *dev, unsigned int type,
 	}
 	return NULL;
 }
+EXPORT_SYMBOL_GPL(platform_get_resource);
 
 /**
  *	platform_get_irq - get an IRQ for a device
@@ -61,6 +63,7 @@ int platform_get_irq(struct platform_device *dev, unsigned int num)
 
 	return r ? r->start : 0;
 }
+EXPORT_SYMBOL_GPL(platform_get_irq);
 
 /**
  *	platform_get_resource_byname - get a resource for a device by name
@@ -84,6 +87,7 @@ platform_get_resource_byname(struct platform_device *dev, unsigned int type,
 	}
 	return NULL;
 }
+EXPORT_SYMBOL_GPL(platform_get_resource_byname);
 
 /**
  *	platform_get_irq - get an IRQ for a device
@@ -96,6 +100,7 @@ int platform_get_irq_byname(struct platform_device *dev, char *name)
 
 	return r ? r->start : 0;
 }
+EXPORT_SYMBOL_GPL(platform_get_irq_byname);
 
 /**
  *	platform_add_devices - add a numbers of platform devices
@@ -117,6 +122,7 @@ int platform_add_devices(struct platform_device **devs, int num)
 
 	return ret;
 }
+EXPORT_SYMBOL_GPL(platform_add_devices);
 
 struct platform_object {
 	struct platform_device pdev;
@@ -168,7 +174,7 @@ struct platform_device *platform_device_alloc(const char *name, unsigned int id)
 		pa->pdev.dev.release = platform_device_release;
 	}
 
-	return pa ? &pa->pdev : NULL;	
+	return pa ? &pa->pdev : NULL;
 }
 EXPORT_SYMBOL_GPL(platform_device_alloc);
 
@@ -257,7 +263,7 @@ int platform_device_add(struct platform_device *pdev)
 				p = &ioport_resource;
 		}
 
-		if (p && request_resource(p, r)) {
+		if (p && insert_resource(p, r)) {
 			printk(KERN_ERR
 			       "%s: failed to claim resource %d\n",
 			       pdev->dev.bus_id, i);
@@ -282,24 +288,13 @@ int platform_device_add(struct platform_device *pdev)
 EXPORT_SYMBOL_GPL(platform_device_add);
 
 /**
- *	platform_device_register - add a platform-level device
- *	@pdev:	platform device we're adding
- *
- */
-int platform_device_register(struct platform_device * pdev)
-{
-	device_initialize(&pdev->dev);
-	return platform_device_add(pdev);
-}
-
-/**
- *	platform_device_unregister - remove a platform-level device
+ *	platform_device_del - remove a platform-level device
  *	@pdev:	platform device we're removing
  *
  *	Note that this function will also release all memory- and port-based
  *	resources owned by the device (@dev->resource).
  */
-void platform_device_unregister(struct platform_device * pdev)
+void platform_device_del(struct platform_device *pdev)
 {
 	int i;
 
@@ -310,9 +305,37 @@ void platform_device_unregister(struct platform_device * pdev)
 				release_resource(r);
 		}
 
-		device_unregister(&pdev->dev);
+		device_del(&pdev->dev);
 	}
 }
+EXPORT_SYMBOL_GPL(platform_device_del);
+
+/**
+ *	platform_device_register - add a platform-level device
+ *	@pdev:	platform device we're adding
+ *
+ */
+int platform_device_register(struct platform_device * pdev)
+{
+	device_initialize(&pdev->dev);
+	return platform_device_add(pdev);
+}
+EXPORT_SYMBOL_GPL(platform_device_register);
+
+/**
+ *	platform_device_unregister - unregister a platform-level device
+ *	@pdev:	platform device we're unregistering
+ *
+ *	Unregistration is done in 2 steps. Fisrt we release all resources
+ *	and remove it from the sybsystem, then we drop reference count by
+ *	calling platform_device_put().
+ */
+void platform_device_unregister(struct platform_device * pdev)
+{
+	platform_device_del(pdev);
+	platform_device_put(pdev);
+}
+EXPORT_SYMBOL_GPL(platform_device_unregister);
 
 /**
  *	platform_device_register_simple
@@ -355,6 +378,7 @@ error:
 	platform_device_put(pdev);
 	return ERR_PTR(retval);
 }
+EXPORT_SYMBOL_GPL(platform_device_register_simple);
 
 static int platform_drv_probe(struct device *_dev)
 {
@@ -476,6 +500,7 @@ struct bus_type platform_bus_type = {
 	.suspend	= platform_suspend,
 	.resume		= platform_resume,
 };
+EXPORT_SYMBOL_GPL(platform_bus_type);
 
 int __init platform_bus_init(void)
 {
@@ -504,14 +529,3 @@ u64 dma_get_required_mask(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(dma_get_required_mask);
 #endif
-
-EXPORT_SYMBOL_GPL(platform_bus);
-EXPORT_SYMBOL_GPL(platform_bus_type);
-EXPORT_SYMBOL_GPL(platform_add_devices);
-EXPORT_SYMBOL_GPL(platform_device_register);
-EXPORT_SYMBOL_GPL(platform_device_register_simple);
-EXPORT_SYMBOL_GPL(platform_device_unregister);
-EXPORT_SYMBOL_GPL(platform_get_irq);
-EXPORT_SYMBOL_GPL(platform_get_resource);
-EXPORT_SYMBOL_GPL(platform_get_irq_byname);
-EXPORT_SYMBOL_GPL(platform_get_resource_byname);
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index adbc3148c039..96370ec1d673 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -62,8 +62,10 @@ int dpm_runtime_suspend(struct device * dev, pm_message_t state)
 	up(&dpm_sem);
 	return error;
 }
+EXPORT_SYMBOL(dpm_runtime_suspend);
 
 
+#if 0
 /**
  *	dpm_set_power_state - Update power_state field.
  *	@dev:	Device.
@@ -80,3 +82,4 @@ void dpm_set_power_state(struct device * dev, pm_message_t state)
 	dev->power.power_state = state;
 	up(&dpm_sem);
 }
+#endif  /*  0  */
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index 70eaa5c7ac08..21097a39a057 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -3471,7 +3471,7 @@ static inline boolean DAC960_ProcessCompletedRequest(DAC960_Command_T *Command,
 
 	 if (!end_that_request_first(Request, UpToDate, Command->BlockCount)) {
 
- 	 	end_that_request_last(Request);
+ 	 	end_that_request_last(Request, UpToDate);
 
 		if (Command->Completion) {
 			complete(Command->Completion);
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index 7b1cd93892be..139cbba76180 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -117,7 +117,7 @@ config BLK_DEV_XD
 
 config PARIDE
 	tristate "Parallel port IDE device support"
-	depends on PARPORT
+	depends on PARPORT_PC
 	---help---
 	  There are many external CD-ROM and disk devices that connect through
 	  your computer's parallel port. Most of them are actually IDE devices
@@ -358,7 +358,8 @@ config BLK_DEV_UB
 	  This driver supports certain USB attached storage devices
 	  such as flash keys.
 
-	  Warning: Enabling this cripples the usb-storage driver.
+	  If you enable this driver, it is recommended to avoid conflicts
+	  with usb-storage by enabling USB_LIBUSUAL.
 
 	  If unsure, say N.
 
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index c3441b3f086e..d2815b7a9150 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -2310,7 +2310,7 @@ static inline void complete_command( ctlr_info_t *h, CommandList_struct *cmd,
 	printk("Done with %p\n", cmd->rq);
 #endif /* CCISS_DEBUG */ 
 
-	end_that_request_last(cmd->rq);
+	end_that_request_last(cmd->rq, status ? 1 : -EIO);
 	cmd_free(h,cmd,1);
 }
 
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
index cf1822a6361c..9bddb6874873 100644
--- a/drivers/block/cpqarray.c
+++ b/drivers/block/cpqarray.c
@@ -1036,7 +1036,7 @@ static inline void complete_command(cmdlist_t *cmd, int timeout)
 	complete_buffers(cmd->rq->bio, ok);
 
         DBGPX(printk("Done with %p\n", cmd->rq););
-	end_that_request_last(cmd->rq);
+	end_that_request_last(cmd->rq, ok ? 1 : -EIO);
 }
 
 /*
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index f7e765a1d313..a5b857c5c4b8 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -2301,7 +2301,7 @@ static void floppy_end_request(struct request *req, int uptodate)
 	add_disk_randomness(req->rq_disk);
 	floppy_off((long)req->rq_disk->private_data);
 	blkdev_dequeue_request(req);
-	end_that_request_last(req);
+	end_that_request_last(req, uptodate);
 
 	/* We're done with the request */
 	current_req = NULL;
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 96c664af8d06..a452b13620a2 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -213,7 +213,7 @@ static int do_lo_send_aops(struct loop_device *lo, struct bio_vec *bvec,
 	struct address_space_operations *aops = mapping->a_ops;
 	pgoff_t index;
 	unsigned offset, bv_offs;
-	int len, ret = 0;
+	int len, ret;
 
 	down(&mapping->host->i_sem);
 	index = pos >> PAGE_CACHE_SHIFT;
@@ -232,9 +232,15 @@ static int do_lo_send_aops(struct loop_device *lo, struct bio_vec *bvec,
 		page = grab_cache_page(mapping, index);
 		if (unlikely(!page))
 			goto fail;
-		if (unlikely(aops->prepare_write(file, page, offset,
-				offset + size)))
+		ret = aops->prepare_write(file, page, offset,
+					  offset + size);
+		if (unlikely(ret)) {
+			if (ret == AOP_TRUNCATED_PAGE) {
+				page_cache_release(page);
+				continue;
+			}
 			goto unlock;
+		}
 		transfer_result = lo_do_transfer(lo, WRITE, page, offset,
 				bvec->bv_page, bv_offs, size, IV);
 		if (unlikely(transfer_result)) {
@@ -251,9 +257,15 @@ static int do_lo_send_aops(struct loop_device *lo, struct bio_vec *bvec,
 			kunmap_atomic(kaddr, KM_USER0);
 		}
 		flush_dcache_page(page);
-		if (unlikely(aops->commit_write(file, page, offset,
-				offset + size)))
+		ret = aops->commit_write(file, page, offset,
+					 offset + size);
+		if (unlikely(ret)) {
+			if (ret == AOP_TRUNCATED_PAGE) {
+				page_cache_release(page);
+				continue;
+			}
 			goto unlock;
+		}
 		if (unlikely(transfer_result))
 			goto unlock;
 		bv_offs += size;
@@ -264,6 +276,7 @@ static int do_lo_send_aops(struct loop_device *lo, struct bio_vec *bvec,
 		unlock_page(page);
 		page_cache_release(page);
 	}
+	ret = 0;
 out:
 	up(&mapping->host->i_sem);
 	return ret;
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 9e268ddedfbd..33d6f237b2ed 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -54,11 +54,15 @@
 #include <linux/errno.h>
 #include <linux/file.h>
 #include <linux/ioctl.h>
+#include <linux/compiler.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
 #include <net/sock.h>
 
 #include <linux/devfs_fs_kernel.h>
 
 #include <asm/uaccess.h>
+#include <asm/system.h>
 #include <asm/types.h>
 
 #include <linux/nbd.h>
@@ -136,7 +140,7 @@ static void nbd_end_request(struct request *req)
 
 	spin_lock_irqsave(q->queue_lock, flags);
 	if (!end_that_request_first(req, uptodate, req->nr_sectors)) {
-		end_that_request_last(req);
+		end_that_request_last(req, uptodate);
 	}
 	spin_unlock_irqrestore(q->queue_lock, flags);
 }
@@ -230,14 +234,6 @@ static int nbd_send_req(struct nbd_device *lo, struct request *req)
 	request.len = htonl(size);
 	memcpy(request.handle, &req, sizeof(req));
 
-	down(&lo->tx_lock);
-
-	if (!sock || !lo->sock) {
-		printk(KERN_ERR "%s: Attempted send on closed socket\n",
-				lo->disk->disk_name);
-		goto error_out;
-	}
-
 	dprintk(DBG_TX, "%s: request %p: sending control (%s@%llu,%luB)\n",
 			lo->disk->disk_name, req,
 			nbdcmd_to_ascii(nbd_cmd(req)),
@@ -276,11 +272,9 @@ static int nbd_send_req(struct nbd_device *lo, struct request *req)
 			}
 		}
 	}
-	up(&lo->tx_lock);
 	return 0;
 
 error_out:
-	up(&lo->tx_lock);
 	return 1;
 }
 
@@ -289,9 +283,14 @@ static struct request *nbd_find_request(struct nbd_device *lo, char *handle)
 	struct request *req;
 	struct list_head *tmp;
 	struct request *xreq;
+	int err;
 
 	memcpy(&xreq, handle, sizeof(xreq));
 
+	err = wait_event_interruptible(lo->active_wq, lo->active_req != xreq);
+	if (unlikely(err))
+		goto out;
+
 	spin_lock(&lo->queue_lock);
 	list_for_each(tmp, &lo->queue_head) {
 		req = list_entry(tmp, struct request, queuelist);
@@ -302,7 +301,11 @@ static struct request *nbd_find_request(struct nbd_device *lo, char *handle)
 		return req;
 	}
 	spin_unlock(&lo->queue_lock);
-	return NULL;
+
+	err = -ENOENT;
+
+out:
+	return ERR_PTR(err);
 }
 
 static inline int sock_recv_bvec(struct socket *sock, struct bio_vec *bvec)
@@ -331,7 +334,11 @@ static struct request *nbd_read_stat(struct nbd_device *lo)
 		goto harderror;
 	}
 	req = nbd_find_request(lo, reply.handle);
-	if (req == NULL) {
+	if (unlikely(IS_ERR(req))) {
+		result = PTR_ERR(req);
+		if (result != -ENOENT)
+			goto harderror;
+
 		printk(KERN_ERR "%s: Unexpected reply (%p)\n",
 				lo->disk->disk_name, reply.handle);
 		result = -EBADR;
@@ -395,19 +402,24 @@ static void nbd_clear_que(struct nbd_device *lo)
 
 	BUG_ON(lo->magic != LO_MAGIC);
 
-	do {
-		req = NULL;
-		spin_lock(&lo->queue_lock);
-		if (!list_empty(&lo->queue_head)) {
-			req = list_entry(lo->queue_head.next, struct request, queuelist);
-			list_del_init(&req->queuelist);
-		}
-		spin_unlock(&lo->queue_lock);
-		if (req) {
-			req->errors++;
-			nbd_end_request(req);
-		}
-	} while (req);
+	/*
+	 * Because we have set lo->sock to NULL under the tx_lock, all
+	 * modifications to the list must have completed by now.  For
+	 * the same reason, the active_req must be NULL.
+	 *
+	 * As a consequence, we don't need to take the spin lock while
+	 * purging the list here.
+	 */
+	BUG_ON(lo->sock);
+	BUG_ON(lo->active_req);
+
+	while (!list_empty(&lo->queue_head)) {
+		req = list_entry(lo->queue_head.next, struct request,
+				 queuelist);
+		list_del_init(&req->queuelist);
+		req->errors++;
+		nbd_end_request(req);
+	}
 }
 
 /*
@@ -435,11 +447,6 @@ static void do_nbd_request(request_queue_t * q)
 
 		BUG_ON(lo->magic != LO_MAGIC);
 
-		if (!lo->file) {
-			printk(KERN_ERR "%s: Request when not-ready\n",
-					lo->disk->disk_name);
-			goto error_out;
-		}
 		nbd_cmd(req) = NBD_CMD_READ;
 		if (rq_data_dir(req) == WRITE) {
 			nbd_cmd(req) = NBD_CMD_WRITE;
@@ -453,32 +460,34 @@ static void do_nbd_request(request_queue_t * q)
 		req->errors = 0;
 		spin_unlock_irq(q->queue_lock);
 
-		spin_lock(&lo->queue_lock);
-
-		if (!lo->file) {
-			spin_unlock(&lo->queue_lock);
-			printk(KERN_ERR "%s: failed between accept and semaphore, file lost\n",
-					lo->disk->disk_name);
+		down(&lo->tx_lock);
+		if (unlikely(!lo->sock)) {
+			up(&lo->tx_lock);
+			printk(KERN_ERR "%s: Attempted send on closed socket\n",
+			       lo->disk->disk_name);
 			req->errors++;
 			nbd_end_request(req);
 			spin_lock_irq(q->queue_lock);
 			continue;
 		}
 
-		list_add(&req->queuelist, &lo->queue_head);
-		spin_unlock(&lo->queue_lock);
+		lo->active_req = req;
 
 		if (nbd_send_req(lo, req) != 0) {
 			printk(KERN_ERR "%s: Request send failed\n",
 					lo->disk->disk_name);
-			if (nbd_find_request(lo, (char *)&req) != NULL) {
-				/* we still own req */
-				req->errors++;
-				nbd_end_request(req);
-			} else /* we're racing with nbd_clear_que */
-				printk(KERN_DEBUG "nbd: can't find req\n");
+			req->errors++;
+			nbd_end_request(req);
+		} else {
+			spin_lock(&lo->queue_lock);
+			list_add(&req->queuelist, &lo->queue_head);
+			spin_unlock(&lo->queue_lock);
 		}
 
+		lo->active_req = NULL;
+		up(&lo->tx_lock);
+		wake_up_all(&lo->active_wq);
+
 		spin_lock_irq(q->queue_lock);
 		continue;
 
@@ -529,17 +538,10 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
 		down(&lo->tx_lock);
 		lo->sock = NULL;
 		up(&lo->tx_lock);
-		spin_lock(&lo->queue_lock);
 		file = lo->file;
 		lo->file = NULL;
-		spin_unlock(&lo->queue_lock);
 		nbd_clear_que(lo);
-		spin_lock(&lo->queue_lock);
-		if (!list_empty(&lo->queue_head)) {
-			printk(KERN_ERR "nbd: disconnect: some requests are in progress -> please try again.\n");
-			error = -EBUSY;
-		}
-		spin_unlock(&lo->queue_lock);
+		BUG_ON(!list_empty(&lo->queue_head));
 		if (file)
 			fput(file);
 		return error;
@@ -598,24 +600,19 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
 			lo->sock = NULL;
 		}
 		up(&lo->tx_lock);
-		spin_lock(&lo->queue_lock);
 		file = lo->file;
 		lo->file = NULL;
-		spin_unlock(&lo->queue_lock);
 		nbd_clear_que(lo);
 		printk(KERN_WARNING "%s: queue cleared\n", lo->disk->disk_name);
 		if (file)
 			fput(file);
 		return lo->harderror;
 	case NBD_CLEAR_QUE:
-		down(&lo->tx_lock);
-		if (lo->sock) {
-			up(&lo->tx_lock);
-			return 0; /* probably should be error, but that would
-				   * break "nbd-client -d", so just return 0 */
-		}
-		up(&lo->tx_lock);
-		nbd_clear_que(lo);
+		/*
+		 * This is for compatibility only.  The queue is always cleared
+		 * by NBD_DO_IT or NBD_CLEAR_SOCK.
+		 */
+		BUG_ON(!lo->sock && !list_empty(&lo->queue_head));
 		return 0;
 	case NBD_PRINT_DEBUG:
 		printk(KERN_INFO "%s: next = %p, prev = %p, head = %p\n",
@@ -688,6 +685,7 @@ static int __init nbd_init(void)
 		spin_lock_init(&nbd_dev[i].queue_lock);
 		INIT_LIST_HEAD(&nbd_dev[i].queue_head);
 		init_MUTEX(&nbd_dev[i].tx_lock);
+		init_waitqueue_head(&nbd_dev[i].active_wq);
 		nbd_dev[i].blksize = 1024;
 		nbd_dev[i].bytesize = 0x7ffffc00ULL << 10; /* 2TB */
 		disk->major = NBD_MAJOR;
diff --git a/drivers/block/paride/Kconfig b/drivers/block/paride/Kconfig
index 17ff40561257..c0d2854dd097 100644
--- a/drivers/block/paride/Kconfig
+++ b/drivers/block/paride/Kconfig
@@ -4,11 +4,12 @@
 # PARIDE doesn't need PARPORT, but if PARPORT is configured as a module,
 # PARIDE must also be a module.  The bogus CONFIG_PARIDE_PARPORT option
 # controls the choices given to the user ...
+# PARIDE only supports PC style parports. Tough for USB or other parports...
 config PARIDE_PARPORT
 	tristate
 	depends on PARIDE!=n
-	default m if PARPORT=m
-	default y if PARPORT!=m
+	default m if PARPORT_PC=m
+	default y if PARPORT_PC!=m
 
 comment "Parallel IDE high-level drivers"
 	depends on PARIDE
diff --git a/drivers/block/rd.c b/drivers/block/rd.c
index 68c60a5bcdab..ffd6abd6d5a0 100644
--- a/drivers/block/rd.c
+++ b/drivers/block/rd.c
@@ -154,7 +154,7 @@ static int ramdisk_commit_write(struct file *file, struct page *page,
 
 /*
  * ->writepage to the the blockdev's mapping has to redirty the page so that the
- * VM doesn't go and steal it.  We return WRITEPAGE_ACTIVATE so that the VM
+ * VM doesn't go and steal it.  We return AOP_WRITEPAGE_ACTIVATE so that the VM
  * won't try to (pointlessly) write the page again for a while.
  *
  * Really, these pages should not be on the LRU at all.
@@ -165,7 +165,7 @@ static int ramdisk_writepage(struct page *page, struct writeback_control *wbc)
 		make_page_uptodate(page);
 	SetPageDirty(page);
 	if (wbc->for_reclaim)
-		return WRITEPAGE_ACTIVATE;
+		return AOP_WRITEPAGE_ACTIVATE;
 	unlock_page(page);
 	return 0;
 }
diff --git a/drivers/block/sx8.c b/drivers/block/sx8.c
index 1ded3b433459..9251f4131b53 100644
--- a/drivers/block/sx8.c
+++ b/drivers/block/sx8.c
@@ -770,7 +770,7 @@ static inline void carm_end_request_queued(struct carm_host *host,
 	rc = end_that_request_first(req, uptodate, req->hard_nr_sectors);
 	assert(rc == 0);
 
-	end_that_request_last(req);
+	end_that_request_last(req, uptodate);
 
 	rc = carm_put_request(host, crq);
 	assert(rc == 0);
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index bfb23d543ff7..a05fe5843e6c 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -9,7 +9,6 @@
  *
  * TODO (sorted by decreasing priority)
  *  -- Kill first_open (Al Viro fixed the block layer now)
- *  -- Do resets with usb_device_reset (needs a thread context, use khubd)
  *  -- set readonly flag for CDs, set removable flag for CF readers
  *  -- do inquiry and verify we got a disk and not a tape (for LUN mismatch)
  *  -- special case some senses, e.g. 3a/0 -> no media present, reduce retries
@@ -29,6 +28,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/usb.h>
+#include <linux/usb_usual.h>
 #include <linux/blkdev.h>
 #include <linux/devfs_fs_kernel.h>
 #include <linux/timer.h>
@@ -107,16 +107,6 @@
  */
 
 /*
- * Definitions which have to be scattered once we understand the layout better.
- */
-
-/* Transport (despite PR in the name) */
-#define US_PR_BULK	0x50		/* bulk only */
-
-/* Protocol */
-#define US_SC_SCSI	0x06		/* Transparent */
-
-/*
  * This many LUNs per USB device.
  * Every one of them takes a host, see UB_MAX_HOSTS.
  */
@@ -125,7 +115,7 @@
 /*
  */
 
-#define UB_MINORS_PER_MAJOR	8
+#define UB_PARTS_PER_LUN      8
 
 #define UB_MAX_CDB_SIZE      16		/* Corresponds to Bulk */
 
@@ -245,6 +235,13 @@ struct ub_scsi_cmd {
 	void *back;
 };
 
+struct ub_request {
+	struct request *rq;
+	unsigned int current_try;
+	unsigned int nsg;		/* sgv[nsg] */
+	struct scatterlist sgv[UB_MAX_REQ_SG];
+};
+
 /*
  */
 struct ub_capacity {
@@ -340,6 +337,8 @@ struct ub_lun {
 	int readonly;
 	int first_open;			/* Kludge. See ub_bd_open. */
 
+	struct ub_request urq;
+
 	/* Use Ingo's mempool if or when we have more than one command. */
 	/*
 	 * Currently we never need more than one command for the whole device.
@@ -360,6 +359,7 @@ struct ub_dev {
 	atomic_t poison;		/* The USB device is disconnected */
 	int openc;			/* protected by ub_lock! */
 					/* kref is too implicit for our taste */
+	int reset;			/* Reset is running */
 	unsigned int tagcnt;
 	char name[12];
 	struct usb_device *dev;
@@ -387,6 +387,9 @@ struct ub_dev {
 	struct bulk_cs_wrap work_bcs;
 	struct usb_ctrlrequest work_cr;
 
+	struct work_struct reset_work;
+	wait_queue_head_t reset_wait;
+
 	int sg_stat[6];
 	struct ub_scsi_trace tr;
 };
@@ -395,12 +398,14 @@ struct ub_dev {
  */
 static void ub_cleanup(struct ub_dev *sc);
 static int ub_request_fn_1(struct ub_lun *lun, struct request *rq);
-static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
-    struct ub_scsi_cmd *cmd, struct request *rq);
-static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun,
-    struct ub_scsi_cmd *cmd, struct request *rq);
+static void ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
+    struct ub_scsi_cmd *cmd, struct ub_request *urq);
+static void ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun,
+    struct ub_scsi_cmd *cmd, struct ub_request *urq);
 static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
 static void ub_end_rq(struct request *rq, int uptodate);
+static int ub_rw_cmd_retry(struct ub_dev *sc, struct ub_lun *lun,
+    struct ub_request *urq, struct ub_scsi_cmd *cmd);
 static int ub_submit_scsi(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
 static void ub_urb_complete(struct urb *urb, struct pt_regs *pt);
 static void ub_scsi_action(unsigned long _dev);
@@ -415,6 +420,8 @@ static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
 static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
     int stalled_pipe);
 static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd);
+static void ub_reset_enter(struct ub_dev *sc);
+static void ub_reset_task(void *arg);
 static int ub_sync_tur(struct ub_dev *sc, struct ub_lun *lun);
 static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun,
     struct ub_capacity *ret);
@@ -422,13 +429,18 @@ static int ub_probe_lun(struct ub_dev *sc, int lnum);
 
 /*
  */
+#ifdef CONFIG_USB_LIBUSUAL
+
+#define ub_usb_ids  storage_usb_ids
+#else
+
 static struct usb_device_id ub_usb_ids[] = {
-	// { USB_DEVICE_VER(0x0781, 0x0002, 0x0009, 0x0009) },	/* SDDR-31 */
 	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_BULK) },
 	{ }
 };
 
 MODULE_DEVICE_TABLE(usb, ub_usb_ids);
+#endif /* CONFIG_USB_LIBUSUAL */
 
 /*
  * Find me a way to identify "next free minor" for add_disk(),
@@ -522,6 +534,9 @@ static ssize_t ub_diag_show(struct device *dev, struct device_attribute *attr,
 	spin_lock_irqsave(&sc->lock, flags);
 
 	cnt += sprintf(page + cnt,
+	    "poison %d reset %d\n",
+	    atomic_read(&sc->poison), sc->reset);
+	cnt += sprintf(page + cnt,
 	    "qlen %d qmax %d\n",
 	    sc->cmd_queue.qlen, sc->cmd_queue.qmax);
 	cnt += sprintf(page + cnt,
@@ -770,7 +785,8 @@ static int ub_request_fn_1(struct ub_lun *lun, struct request *rq)
 {
 	struct ub_dev *sc = lun->udev;
 	struct ub_scsi_cmd *cmd;
-	int rc;
+	struct ub_request *urq;
+	int n_elem;
 
 	if (atomic_read(&sc->poison) || lun->changed) {
 		blkdev_dequeue_request(rq);
@@ -778,65 +794,70 @@ static int ub_request_fn_1(struct ub_lun *lun, struct request *rq)
 		return 0;
 	}
 
+	if (lun->urq.rq != NULL)
+		return -1;
 	if ((cmd = ub_get_cmd(lun)) == NULL)
 		return -1;
 	memset(cmd, 0, sizeof(struct ub_scsi_cmd));
 
 	blkdev_dequeue_request(rq);
+
+	urq = &lun->urq;
+	memset(urq, 0, sizeof(struct ub_request));
+	urq->rq = rq;
+
+	/*
+	 * get scatterlist from block layer
+	 */
+	n_elem = blk_rq_map_sg(lun->disk->queue, rq, &urq->sgv[0]);
+	if (n_elem < 0) {
+		printk(KERN_INFO "%s: failed request map (%d)\n",
+		    lun->name, n_elem); /* P3 */
+		goto drop;
+	}
+	if (n_elem > UB_MAX_REQ_SG) {	/* Paranoia */
+		printk(KERN_WARNING "%s: request with %d segments\n",
+		    lun->name, n_elem);
+		goto drop;
+	}
+	urq->nsg = n_elem;
+	sc->sg_stat[n_elem < 5 ? n_elem : 5]++;
+
 	if (blk_pc_request(rq)) {
-		rc = ub_cmd_build_packet(sc, lun, cmd, rq);
+		ub_cmd_build_packet(sc, lun, cmd, urq);
 	} else {
-		rc = ub_cmd_build_block(sc, lun, cmd, rq);
-	}
-	if (rc != 0) {
-		ub_put_cmd(lun, cmd);
-		ub_end_rq(rq, 0);
-		return 0;
+		ub_cmd_build_block(sc, lun, cmd, urq);
 	}
 	cmd->state = UB_CMDST_INIT;
 	cmd->lun = lun;
 	cmd->done = ub_rw_cmd_done;
-	cmd->back = rq;
+	cmd->back = urq;
 
 	cmd->tag = sc->tagcnt++;
-	if (ub_submit_scsi(sc, cmd) != 0) {
-		ub_put_cmd(lun, cmd);
-		ub_end_rq(rq, 0);
-		return 0;
-	}
+	if (ub_submit_scsi(sc, cmd) != 0)
+		goto drop;
 
 	return 0;
+
+drop:
+	ub_put_cmd(lun, cmd);
+	ub_end_rq(rq, 0);
+	return 0;
 }
 
-static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
-    struct ub_scsi_cmd *cmd, struct request *rq)
+static void ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
+    struct ub_scsi_cmd *cmd, struct ub_request *urq)
 {
-	int ub_dir;
-	int n_elem;
+	struct request *rq = urq->rq;
 	unsigned int block, nblks;
 
 	if (rq_data_dir(rq) == WRITE)
-		ub_dir = UB_DIR_WRITE;
+		cmd->dir = UB_DIR_WRITE;
 	else
-		ub_dir = UB_DIR_READ;
-	cmd->dir = ub_dir;
+		cmd->dir = UB_DIR_READ;
 
-	/*
-	 * get scatterlist from block layer
-	 */
-	n_elem = blk_rq_map_sg(lun->disk->queue, rq, &cmd->sgv[0]);
-	if (n_elem <= 0) {
-		printk(KERN_INFO "%s: failed request map (%d)\n",
-		    sc->name, n_elem); /* P3 */
-		return -1;		/* request with no s/g entries? */
-	}
-	if (n_elem > UB_MAX_REQ_SG) {	/* Paranoia */
-		printk(KERN_WARNING "%s: request with %d segments\n",
-		    sc->name, n_elem);
-		return -1;
-	}
-	cmd->nsg = n_elem;
-	sc->sg_stat[n_elem < 5 ? n_elem : 5]++;
+	cmd->nsg = urq->nsg;
+	memcpy(cmd->sgv, urq->sgv, sizeof(struct scatterlist) * cmd->nsg);
 
 	/*
 	 * build the command
@@ -847,7 +868,7 @@ static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
 	block = rq->sector >> lun->capacity.bshift;
 	nblks = rq->nr_sectors >> lun->capacity.bshift;
 
-	cmd->cdb[0] = (ub_dir == UB_DIR_READ)? READ_10: WRITE_10;
+	cmd->cdb[0] = (cmd->dir == UB_DIR_READ)? READ_10: WRITE_10;
 	/* 10-byte uses 4 bytes of LBA: 2147483648KB, 2097152MB, 2048GB */
 	cmd->cdb[2] = block >> 24;
 	cmd->cdb[3] = block >> 16;
@@ -858,14 +879,12 @@ static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
 	cmd->cdb_len = 10;
 
 	cmd->len = rq->nr_sectors * 512;
-
-	return 0;
 }
 
-static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun,
-    struct ub_scsi_cmd *cmd, struct request *rq)
+static void ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun,
+    struct ub_scsi_cmd *cmd, struct ub_request *urq)
 {
-	int n_elem;
+	struct request *rq = urq->rq;
 
 	if (rq->data_len == 0) {
 		cmd->dir = UB_DIR_NONE;
@@ -874,40 +893,26 @@ static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun,
 			cmd->dir = UB_DIR_WRITE;
 		else
 			cmd->dir = UB_DIR_READ;
-
 	}
 
-	/*
-	 * get scatterlist from block layer
-	 */
-	n_elem = blk_rq_map_sg(lun->disk->queue, rq, &cmd->sgv[0]);
-	if (n_elem < 0) {
-		printk(KERN_INFO "%s: failed request map (%d)\n",
-		    sc->name, n_elem); /* P3 */
-		return -1;
-	}
-	if (n_elem > UB_MAX_REQ_SG) {	/* Paranoia */
-		printk(KERN_WARNING "%s: request with %d segments\n",
-		    sc->name, n_elem);
-		return -1;
-	}
-	cmd->nsg = n_elem;
-	sc->sg_stat[n_elem < 5 ? n_elem : 5]++;
+	cmd->nsg = urq->nsg;
+	memcpy(cmd->sgv, urq->sgv, sizeof(struct scatterlist) * cmd->nsg);
 
 	memcpy(&cmd->cdb, rq->cmd, rq->cmd_len);
 	cmd->cdb_len = rq->cmd_len;
 
 	cmd->len = rq->data_len;
-
-	return 0;
 }
 
 static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
 {
-	struct request *rq = cmd->back;
 	struct ub_lun *lun = cmd->lun;
+	struct ub_request *urq = cmd->back;
+	struct request *rq;
 	int uptodate;
 
+	rq = urq->rq;
+
 	if (cmd->error == 0) {
 		uptodate = 1;
 
@@ -928,9 +933,16 @@ static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
 				rq->errors = SAM_STAT_CHECK_CONDITION;
 			else
 				rq->errors = DID_ERROR << 16;
+		} else {
+			if (cmd->error == -EIO) {
+				if (ub_rw_cmd_retry(sc, lun, urq, cmd) == 0)
+					return;
+			}
 		}
 	}
 
+	urq->rq = NULL;
+
 	ub_put_cmd(lun, cmd);
 	ub_end_rq(rq, uptodate);
 	blk_start_queue(lun->disk->queue);
@@ -938,11 +950,43 @@ static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
 
 static void ub_end_rq(struct request *rq, int uptodate)
 {
-	int rc;
+	end_that_request_first(rq, uptodate, rq->hard_nr_sectors);
+	end_that_request_last(rq, uptodate);
+}
+
+static int ub_rw_cmd_retry(struct ub_dev *sc, struct ub_lun *lun,
+    struct ub_request *urq, struct ub_scsi_cmd *cmd)
+{
+
+	if (atomic_read(&sc->poison))
+		return -ENXIO;
+
+	ub_reset_enter(sc);
 
-	rc = end_that_request_first(rq, uptodate, rq->hard_nr_sectors);
-	// assert(rc == 0);
-	end_that_request_last(rq);
+	if (urq->current_try >= 3)
+		return -EIO;
+	urq->current_try++;
+	/* P3 */ printk("%s: dir %c len/act %d/%d "
+	    "[sense %x %02x %02x] retry %d\n",
+	    sc->name, UB_DIR_CHAR(cmd->dir), cmd->len, cmd->act_len,
+	    cmd->key, cmd->asc, cmd->ascq, urq->current_try);
+
+	memset(cmd, 0, sizeof(struct ub_scsi_cmd));
+	ub_cmd_build_block(sc, lun, cmd, urq);
+
+	cmd->state = UB_CMDST_INIT;
+	cmd->lun = lun;
+	cmd->done = ub_rw_cmd_done;
+	cmd->back = urq;
+
+	cmd->tag = sc->tagcnt++;
+
+#if 0 /* Wasteful */
+	return ub_submit_scsi(sc, cmd);
+#else
+	ub_cmdq_add(sc, cmd);
+	return 0;
+#endif
 }
 
 /*
@@ -1075,7 +1119,7 @@ static void ub_scsi_dispatch(struct ub_dev *sc)
 	struct ub_scsi_cmd *cmd;
 	int rc;
 
-	while ((cmd = ub_cmdq_peek(sc)) != NULL) {
+	while (!sc->reset && (cmd = ub_cmdq_peek(sc)) != NULL) {
 		if (cmd->state == UB_CMDST_DONE) {
 			ub_cmdq_pop(sc);
 			(*cmd->done)(sc, cmd);
@@ -1098,11 +1142,12 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
 {
 	struct urb *urb = &sc->work_urb;
 	struct bulk_cs_wrap *bcs;
+	int len;
 	int rc;
 
 	if (atomic_read(&sc->poison)) {
-		/* A little too simplistic, I feel... */
-		goto Bad_End;
+		ub_state_done(sc, cmd, -ENODEV);
+		return;
 	}
 
 	if (cmd->state == UB_CMDST_CLEAR) {
@@ -1110,7 +1155,6 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
 			/*
 			 * STALL while clearning STALL.
 			 * The control pipe clears itself - nothing to do.
-			 * XXX Might try to reset the device here and retry.
 			 */
 			printk(KERN_NOTICE "%s: stall on control pipe\n",
 			    sc->name);
@@ -1129,11 +1173,6 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
 
 	} else if (cmd->state == UB_CMDST_CLR2STS) {
 		if (urb->status == -EPIPE) {
-			/*
-			 * STALL while clearning STALL.
-			 * The control pipe clears itself - nothing to do.
-			 * XXX Might try to reset the device here and retry.
-			 */
 			printk(KERN_NOTICE "%s: stall on control pipe\n",
 			    sc->name);
 			goto Bad_End;
@@ -1151,11 +1190,6 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
 
 	} else if (cmd->state == UB_CMDST_CLRRS) {
 		if (urb->status == -EPIPE) {
-			/*
-			 * STALL while clearning STALL.
-			 * The control pipe clears itself - nothing to do.
-			 * XXX Might try to reset the device here and retry.
-			 */
 			printk(KERN_NOTICE "%s: stall on control pipe\n",
 			    sc->name);
 			goto Bad_End;
@@ -1172,7 +1206,12 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
 		ub_state_stat_counted(sc, cmd);
 
 	} else if (cmd->state == UB_CMDST_CMD) {
-		if (urb->status == -EPIPE) {
+		switch (urb->status) {
+		case 0:
+			break;
+		case -EOVERFLOW:
+			goto Bad_End;
+		case -EPIPE:
 			rc = ub_submit_clear_stall(sc, cmd, sc->last_pipe);
 			if (rc != 0) {
 				printk(KERN_NOTICE "%s: "
@@ -1182,17 +1221,20 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
 				 * This is typically ENOMEM or some other such shit.
 				 * Retrying is pointless. Just do Bad End on it...
 				 */
-				goto Bad_End;
+				ub_state_done(sc, cmd, rc);
+				return;
 			}
 			cmd->state = UB_CMDST_CLEAR;
 			ub_cmdtr_state(sc, cmd);
 			return;
-		}
-		if (urb->status != 0) {
+		case -ESHUTDOWN:	/* unplug */
+		case -EILSEQ:		/* unplug timeout on uhci */
+			ub_state_done(sc, cmd, -ENODEV);
+			return;
+		default:
 			goto Bad_End;
 		}
 		if (urb->actual_length != US_BULK_CB_WRAP_LEN) {
-			/* XXX Must do reset here to unconfuse the device */
 			goto Bad_End;
 		}
 
@@ -1211,11 +1253,8 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
 				printk(KERN_NOTICE "%s: "
 				    "unable to submit clear (%d)\n",
 				    sc->name, rc);
-				/*
-				 * This is typically ENOMEM or some other such shit.
-				 * Retrying is pointless. Just do Bad End on it...
-				 */
-				goto Bad_End;
+				ub_state_done(sc, cmd, rc);
+				return;
 			}
 			cmd->state = UB_CMDST_CLR2STS;
 			ub_cmdtr_state(sc, cmd);
@@ -1224,14 +1263,50 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
 		if (urb->status == -EOVERFLOW) {
 			/*
 			 * A babble? Failure, but we must transfer CSW now.
-			 * XXX This is going to end in perpetual babble. Reset.
 			 */
 			cmd->error = -EOVERFLOW;	/* A cheap trick... */
 			ub_state_stat(sc, cmd);
 			return;
 		}
-		if (urb->status != 0)
-			goto Bad_End;
+
+		if (cmd->dir == UB_DIR_WRITE) {
+			/*
+			 * Do not continue writes in case of a failure.
+			 * Doing so would cause sectors to be mixed up,
+			 * which is worse than sectors lost.
+			 *
+			 * We must try to read the CSW, or many devices
+			 * get confused.
+			 */
+			len = urb->actual_length;
+			if (urb->status != 0 ||
+			    len != cmd->sgv[cmd->current_sg].length) {
+				cmd->act_len += len;
+				ub_cmdtr_act_len(sc, cmd);
+
+				cmd->error = -EIO;
+				ub_state_stat(sc, cmd);
+				return;
+			}
+
+		} else {
+			/*
+			 * If an error occurs on read, we record it, and
+			 * continue to fetch data in order to avoid bubble.
+			 *
+			 * As a small shortcut, we stop if we detect that
+			 * a CSW mixed into data.
+			 */
+			if (urb->status != 0)
+				cmd->error = -EIO;
+
+			len = urb->actual_length;
+			if (urb->status != 0 ||
+			    len != cmd->sgv[cmd->current_sg].length) {
+				if ((len & 0x1FF) == US_BULK_CS_WRAP_LEN)
+					goto Bad_End;
+			}
+		}
 
 		cmd->act_len += urb->actual_length;
 		ub_cmdtr_act_len(sc, cmd);
@@ -1249,11 +1324,8 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
 				printk(KERN_NOTICE "%s: "
 				    "unable to submit clear (%d)\n",
 				    sc->name, rc);
-				/*
-				 * This is typically ENOMEM or some other such shit.
-				 * Retrying is pointless. Just do Bad End on it...
-				 */
-				goto Bad_End;
+				ub_state_done(sc, cmd, rc);
+				return;
 			}
 
 			/*
@@ -1266,14 +1338,8 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
 			ub_cmdtr_state(sc, cmd);
 			return;
 		}
-		if (urb->status == -EOVERFLOW) {
-			/*
-			 * XXX We are screwed here. Retrying is pointless,
-			 * because the pipelined data will not get in until
-			 * we read with a big enough buffer. We must reset XXX.
-			 */
-			goto Bad_End;
-		}
+
+		/* Catch everything, including -EOVERFLOW and other nasties. */
 		if (urb->status != 0)
 			goto Bad_End;
 
@@ -1319,15 +1385,15 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
 			return;
 		}
 
-		rc = le32_to_cpu(bcs->Residue);
-		if (rc != cmd->len - cmd->act_len) {
+		len = le32_to_cpu(bcs->Residue);
+		if (len != cmd->len - cmd->act_len) {
 			/*
 			 * It is all right to transfer less, the caller has
 			 * to check. But it's not all right if the device
 			 * counts disagree with our counts.
 			 */
 			/* P3 */ printk("%s: resid %d len %d act %d\n",
-			    sc->name, rc, cmd->len, cmd->act_len);
+			    sc->name, len, cmd->len, cmd->act_len);
 			goto Bad_End;
 		}
 
@@ -1338,13 +1404,13 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
 			ub_state_sense(sc, cmd);
 			return;
 		case US_BULK_STAT_PHASE:
-			/* XXX We must reset the transport here */
 			/* P3 */ printk("%s: status PHASE\n", sc->name);
 			goto Bad_End;
 		default:
 			printk(KERN_INFO "%s: unknown CSW status 0x%x\n",
 			    sc->name, bcs->Status);
-			goto Bad_End;
+			ub_state_done(sc, cmd, -EINVAL);
+			return;
 		}
 
 		/* Not zeroing error to preserve a babble indicator */
@@ -1364,7 +1430,8 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
 		printk(KERN_WARNING "%s: "
 		    "wrong command state %d\n",
 		    sc->name, cmd->state);
-		goto Bad_End;
+		ub_state_done(sc, cmd, -EINVAL);
+		return;
 	}
 	return;
 
@@ -1612,6 +1679,93 @@ static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd)
 }
 
 /*
+ * Reset management
+ */
+
+static void ub_reset_enter(struct ub_dev *sc)
+{
+
+	if (sc->reset) {
+		/* This happens often on multi-LUN devices. */
+		return;
+	}
+	sc->reset = 1;
+
+#if 0 /* Not needed because the disconnect waits for us. */
+	unsigned long flags;
+	spin_lock_irqsave(&ub_lock, flags);
+	sc->openc++;
+	spin_unlock_irqrestore(&ub_lock, flags);
+#endif
+
+#if 0 /* We let them stop themselves. */
+	struct list_head *p;
+	struct ub_lun *lun;
+	list_for_each(p, &sc->luns) {
+		lun = list_entry(p, struct ub_lun, link);
+		blk_stop_queue(lun->disk->queue);
+	}
+#endif
+
+	schedule_work(&sc->reset_work);
+}
+
+static void ub_reset_task(void *arg)
+{
+	struct ub_dev *sc = arg;
+	unsigned long flags;
+	struct list_head *p;
+	struct ub_lun *lun;
+	int lkr, rc;
+
+	if (!sc->reset) {
+		printk(KERN_WARNING "%s: Running reset unrequested\n",
+		    sc->name);
+		return;
+	}
+
+	if (atomic_read(&sc->poison)) {
+		printk(KERN_NOTICE "%s: Not resetting disconnected device\n",
+		    sc->name); /* P3 This floods. Remove soon. XXX */
+	} else if (sc->dev->actconfig->desc.bNumInterfaces != 1) {
+		printk(KERN_NOTICE "%s: Not resetting multi-interface device\n",
+		    sc->name); /* P3 This floods. Remove soon. XXX */
+	} else {
+		if ((lkr = usb_lock_device_for_reset(sc->dev, sc->intf)) < 0) {
+			printk(KERN_NOTICE
+			    "%s: usb_lock_device_for_reset failed (%d)\n",
+			    sc->name, lkr);
+		} else {
+			rc = usb_reset_device(sc->dev);
+			if (rc < 0) {
+				printk(KERN_NOTICE "%s: "
+				    "usb_lock_device_for_reset failed (%d)\n",
+				    sc->name, rc);
+			}
+
+			if (lkr)
+				usb_unlock_device(sc->dev);
+		}
+	}
+
+	/*
+	 * In theory, no commands can be running while reset is active,
+	 * so nobody can ask for another reset, and so we do not need any
+	 * queues of resets or anything. We do need a spinlock though,
+	 * to interact with block layer.
+	 */
+	spin_lock_irqsave(&sc->lock, flags);
+	sc->reset = 0;
+	tasklet_schedule(&sc->tasklet);
+	list_for_each(p, &sc->luns) {
+		lun = list_entry(p, struct ub_lun, link);
+		blk_start_queue(lun->disk->queue);
+	}
+	wake_up(&sc->reset_wait);
+	spin_unlock_irqrestore(&sc->lock, flags);
+}
+
+/*
  * This is called from a process context.
  */
 static void ub_revalidate(struct ub_dev *sc, struct ub_lun *lun)
@@ -2146,7 +2300,7 @@ static int ub_get_pipes(struct ub_dev *sc, struct usb_device *dev,
 	if (ep_in == NULL || ep_out == NULL) {
 		printk(KERN_NOTICE "%s: failed endpoint check\n",
 		    sc->name);
-		return -EIO;
+		return -ENODEV;
 	}
 
 	/* Calculate and store the pipe values */
@@ -2172,6 +2326,9 @@ static int ub_probe(struct usb_interface *intf,
 	int rc;
 	int i;
 
+	if (usb_usual_check_type(dev_id, USB_US_TYPE_UB))
+		return -ENXIO;
+
 	rc = -ENOMEM;
 	if ((sc = kmalloc(sizeof(struct ub_dev), GFP_KERNEL)) == NULL)
 		goto err_core;
@@ -2181,6 +2338,8 @@ static int ub_probe(struct usb_interface *intf,
 	usb_init_urb(&sc->work_urb);
 	tasklet_init(&sc->tasklet, ub_scsi_action, (unsigned long)sc);
 	atomic_set(&sc->poison, 0);
+	INIT_WORK(&sc->reset_work, ub_reset_task, sc);
+	init_waitqueue_head(&sc->reset_wait);
 
 	init_timer(&sc->work_timer);
 	sc->work_timer.data = (unsigned long) sc;
@@ -2201,7 +2360,8 @@ static int ub_probe(struct usb_interface *intf,
 
 	/* XXX Verify that we can handle the device (from descriptors) */
 
-	ub_get_pipes(sc, sc->dev, intf);
+	if (ub_get_pipes(sc, sc->dev, intf) != 0)
+		goto err_dev_desc;
 
 	if (device_create_file(&sc->intf->dev, &dev_attr_diag) != 0)
 		goto err_diag;
@@ -2272,6 +2432,7 @@ static int ub_probe(struct usb_interface *intf,
 
 	/* device_remove_file(&sc->intf->dev, &dev_attr_diag); */
 err_diag:
+err_dev_desc:
 	usb_set_intfdata(intf, NULL);
 	// usb_put_intf(sc->intf);
 	usb_put_dev(sc->dev);
@@ -2309,14 +2470,14 @@ static int ub_probe_lun(struct ub_dev *sc, int lnum)
 	ub_revalidate(sc, lun);
 
 	rc = -ENOMEM;
-	if ((disk = alloc_disk(UB_MINORS_PER_MAJOR)) == NULL)
+	if ((disk = alloc_disk(UB_PARTS_PER_LUN)) == NULL)
 		goto err_diskalloc;
 
 	lun->disk = disk;
 	sprintf(disk->disk_name, DRV_NAME "%c", lun->id + 'a');
 	sprintf(disk->devfs_name, DEVFS_NAME "/%c", lun->id + 'a');
 	disk->major = UB_MAJOR;
-	disk->first_minor = lun->id * UB_MINORS_PER_MAJOR;
+	disk->first_minor = lun->id * UB_PARTS_PER_LUN;
 	disk->fops = &ub_bd_fops;
 	disk->private_data = lun;
 	disk->driverfs_dev = &sc->intf->dev;
@@ -2380,6 +2541,11 @@ static void ub_disconnect(struct usb_interface *intf)
 	atomic_set(&sc->poison, 1);
 
 	/*
+	 * Wait for reset to end, if any.
+	 */
+	wait_event(sc->reset_wait, !sc->reset);
+
+	/*
 	 * Blow away queued commands.
 	 *
 	 * Actually, this never works, because before we get here
@@ -2392,7 +2558,7 @@ static void ub_disconnect(struct usb_interface *intf)
 	{
 		struct ub_scsi_cmd *cmd;
 		int cnt = 0;
-		while ((cmd = ub_cmdq_pop(sc)) != NULL) {
+		while ((cmd = ub_cmdq_peek(sc)) != NULL) {
 			cmd->error = -ENOTCONN;
 			cmd->state = UB_CMDST_DONE;
 			ub_cmdtr_state(sc, cmd);
@@ -2461,7 +2627,6 @@ static void ub_disconnect(struct usb_interface *intf)
 }
 
 static struct usb_driver ub_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"ub",
 	.probe =	ub_probe,
 	.disconnect =	ub_disconnect,
@@ -2479,6 +2644,7 @@ static int __init ub_init(void)
 	if ((rc = usb_register(&ub_driver)) != 0)
 		goto err_register;
 
+	usb_usual_set_present(USB_US_TYPE_UB);
 	return 0;
 
 err_register:
@@ -2494,6 +2660,7 @@ static void __exit ub_exit(void)
 
 	devfs_remove(DEVFS_NAME);
 	unregister_blkdev(UB_MAJOR, DRV_NAME);
+	usb_usual_clear_present(USB_US_TYPE_UB);
 }
 
 module_init(ub_init);
diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c
index 2d518aa2720a..063f0304a163 100644
--- a/drivers/block/viodasd.c
+++ b/drivers/block/viodasd.c
@@ -305,7 +305,7 @@ static void viodasd_end_request(struct request *req, int uptodate,
 	if (end_that_request_first(req, uptodate, num_sectors))
 		return;
 	add_disk_randomness(req->rq_disk);
-	end_that_request_last(req);
+	end_that_request_last(req, uptodate);
 }
 
 /*
diff --git a/drivers/bluetooth/bcm203x.c b/drivers/bluetooth/bcm203x.c
index 8e7fb3551775..3e7a067cc087 100644
--- a/drivers/bluetooth/bcm203x.c
+++ b/drivers/bluetooth/bcm203x.c
@@ -275,7 +275,6 @@ static void bcm203x_disconnect(struct usb_interface *intf)
 }
 
 static struct usb_driver bcm203x_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "bcm203x",
 	.probe		= bcm203x_probe,
 	.disconnect	= bcm203x_disconnect,
diff --git a/drivers/bluetooth/bfusb.c b/drivers/bluetooth/bfusb.c
index 067e27893e4a..8947c8837dac 100644
--- a/drivers/bluetooth/bfusb.c
+++ b/drivers/bluetooth/bfusb.c
@@ -768,7 +768,6 @@ static void bfusb_disconnect(struct usb_interface *intf)
 }
 
 static struct usb_driver bfusb_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "bfusb",
 	.probe		= bfusb_probe,
 	.disconnect	= bfusb_disconnect,
diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c
index f36c563d72c4..9888bc151755 100644
--- a/drivers/bluetooth/bluecard_cs.c
+++ b/drivers/bluetooth/bluecard_cs.c
@@ -87,14 +87,8 @@ typedef struct bluecard_info_t {
 
 static void bluecard_config(dev_link_t *link);
 static void bluecard_release(dev_link_t *link);
-static int bluecard_event(event_t event, int priority, event_callback_args_t *args);
 
-static dev_info_t dev_info = "bluecard_cs";
-
-static dev_link_t *bluecard_attach(void);
-static void bluecard_detach(dev_link_t *);
-
-static dev_link_t *dev_list = NULL;
+static void bluecard_detach(struct pcmcia_device *p_dev);
 
 
 /* Default baud rate: 57600, 115200, 230400 or 460800 */
@@ -862,17 +856,15 @@ static int bluecard_close(bluecard_info_t *info)
 	return 0;
 }
 
-static dev_link_t *bluecard_attach(void)
+static int bluecard_attach(struct pcmcia_device *p_dev)
 {
 	bluecard_info_t *info;
-	client_reg_t client_reg;
 	dev_link_t *link;
-	int ret;
 
 	/* Create new info device */
 	info = kzalloc(sizeof(*info), GFP_KERNEL);
 	if (!info)
-		return NULL;
+		return -ENOMEM;
 
 	link = &info->link;
 	link->priv = info;
@@ -889,50 +881,24 @@ static dev_link_t *bluecard_attach(void)
 	link->conf.Vcc = 50;
 	link->conf.IntType = INT_MEMORY_AND_IO;
 
-	/* Register with Card Services */
-	link->next = dev_list;
-	dev_list = link;
-	client_reg.dev_info = &dev_info;
-	client_reg.Version = 0x0210;
-	client_reg.event_callback_args.client_data = link;
-
-	ret = pcmcia_register_client(&link->handle, &client_reg);
-	if (ret != CS_SUCCESS) {
-		cs_error(link->handle, RegisterClient, ret);
-		bluecard_detach(link);
-		return NULL;
-	}
+	link->handle = p_dev;
+	p_dev->instance = link;
 
-	return link;
+	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+	bluecard_config(link);
+
+	return 0;
 }
 
 
-static void bluecard_detach(dev_link_t *link)
+static void bluecard_detach(struct pcmcia_device *p_dev)
 {
+	dev_link_t *link = dev_to_instance(p_dev);
 	bluecard_info_t *info = link->priv;
-	dev_link_t **linkp;
-	int ret;
-
-	/* Locate device structure */
-	for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
-		if (*linkp == link)
-			break;
-
-	if (*linkp == NULL)
-		return;
 
 	if (link->state & DEV_CONFIG)
 		bluecard_release(link);
 
-	if (link->handle) {
-		ret = pcmcia_deregister_client(link->handle);
-		if (ret != CS_SUCCESS)
-			cs_error(link->handle, DeregisterClient, ret);
-	}
-
-	/* Unlink device structure, free bits */
-	*linkp = link->next;
-
 	kfree(info);
 }
 
@@ -1045,39 +1011,24 @@ static void bluecard_release(dev_link_t *link)
 	link->state &= ~DEV_CONFIG;
 }
 
+static int bluecard_suspend(struct pcmcia_device *dev)
+{
+	dev_link_t *link = dev_to_instance(dev);
+
+	link->state |= DEV_SUSPEND;
+	if (link->state & DEV_CONFIG)
+		pcmcia_release_configuration(link->handle);
 
-static int bluecard_event(event_t event, int priority, event_callback_args_t *args)
+	return 0;
+}
+
+static int bluecard_resume(struct pcmcia_device *dev)
 {
-	dev_link_t *link = args->client_data;
-	bluecard_info_t *info = link->priv;
+	dev_link_t *link = dev_to_instance(dev);
 
-	switch (event) {
-	case CS_EVENT_CARD_REMOVAL:
-		link->state &= ~DEV_PRESENT;
-		if (link->state & DEV_CONFIG) {
-			bluecard_close(info);
-			bluecard_release(link);
-		}
-		break;
-	case CS_EVENT_CARD_INSERTION:
-		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-		bluecard_config(link);
-		break;
-	case CS_EVENT_PM_SUSPEND:
-		link->state |= DEV_SUSPEND;
-		/* Fall through... */
-	case CS_EVENT_RESET_PHYSICAL:
-		if (link->state & DEV_CONFIG)
-			pcmcia_release_configuration(link->handle);
-		break;
-	case CS_EVENT_PM_RESUME:
-		link->state &= ~DEV_SUSPEND;
-		/* Fall through... */
-	case CS_EVENT_CARD_RESET:
-		if (DEV_OK(link))
-			pcmcia_request_configuration(link->handle, &link->conf);
-		break;
-	}
+	link->state &= ~DEV_SUSPEND;
+	if (DEV_OK(link))
+		pcmcia_request_configuration(link->handle, &link->conf);
 
 	return 0;
 }
@@ -1095,10 +1046,11 @@ static struct pcmcia_driver bluecard_driver = {
 	.drv		= {
 		.name	= "bluecard_cs",
 	},
-	.attach		= bluecard_attach,
-	.event		= bluecard_event,
-	.detach		= bluecard_detach,
+	.probe		= bluecard_attach,
+	.remove		= bluecard_detach,
 	.id_table	= bluecard_ids,
+	.suspend	= bluecard_suspend,
+	.resume		= bluecard_resume,
 };
 
 static int __init init_bluecard_cs(void)
@@ -1110,7 +1062,6 @@ static int __init init_bluecard_cs(void)
 static void __exit exit_bluecard_cs(void)
 {
 	pcmcia_unregister_driver(&bluecard_driver);
-	BUG_ON(dev_list != NULL);
 }
 
 module_init(init_bluecard_cs);
diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c
index 394796315adc..9446960ac742 100644
--- a/drivers/bluetooth/bpa10x.c
+++ b/drivers/bluetooth/bpa10x.c
@@ -619,7 +619,6 @@ static void bpa10x_disconnect(struct usb_interface *intf)
 }
 
 static struct usb_driver bpa10x_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "bpa10x",
 	.probe		= bpa10x_probe,
 	.disconnect	= bpa10x_disconnect,
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c
index d2a0add19cc8..e522d19ad886 100644
--- a/drivers/bluetooth/bt3c_cs.c
+++ b/drivers/bluetooth/bt3c_cs.c
@@ -90,14 +90,8 @@ typedef struct bt3c_info_t {
 
 static void bt3c_config(dev_link_t *link);
 static void bt3c_release(dev_link_t *link);
-static int bt3c_event(event_t event, int priority, event_callback_args_t *args);
 
-static dev_info_t dev_info = "bt3c_cs";
-
-static dev_link_t *bt3c_attach(void);
-static void bt3c_detach(dev_link_t *);
-
-static dev_link_t *dev_list = NULL;
+static void bt3c_detach(struct pcmcia_device *p_dev);
 
 
 /* Transmit states  */
@@ -663,17 +657,15 @@ static int bt3c_close(bt3c_info_t *info)
 	return 0;
 }
 
-static dev_link_t *bt3c_attach(void)
+static int bt3c_attach(struct pcmcia_device *p_dev)
 {
 	bt3c_info_t *info;
-	client_reg_t client_reg;
 	dev_link_t *link;
-	int ret;
 
 	/* Create new info device */
 	info = kzalloc(sizeof(*info), GFP_KERNEL);
 	if (!info)
-		return NULL;
+		return -ENOMEM;
 
 	link = &info->link;
 	link->priv = info;
@@ -690,50 +682,24 @@ static dev_link_t *bt3c_attach(void)
 	link->conf.Vcc = 50;
 	link->conf.IntType = INT_MEMORY_AND_IO;
 
-	/* Register with Card Services */
-	link->next = dev_list;
-	dev_list = link;
-	client_reg.dev_info = &dev_info;
-	client_reg.Version = 0x0210;
-	client_reg.event_callback_args.client_data = link;
-
-	ret = pcmcia_register_client(&link->handle, &client_reg);
-	if (ret != CS_SUCCESS) {
-		cs_error(link->handle, RegisterClient, ret);
-		bt3c_detach(link);
-		return NULL;
-	}
+	link->handle = p_dev;
+	p_dev->instance = link;
 
-	return link;
+	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+	bt3c_config(link);
+
+	return 0;
 }
 
 
-static void bt3c_detach(dev_link_t *link)
+static void bt3c_detach(struct pcmcia_device *p_dev)
 {
+	dev_link_t *link = dev_to_instance(p_dev);
 	bt3c_info_t *info = link->priv;
-	dev_link_t **linkp;
-	int ret;
-
-	/* Locate device structure */
-	for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
-		if (*linkp == link)
-			break;
-
-	if (*linkp == NULL)
-		return;
 
 	if (link->state & DEV_CONFIG)
 		bt3c_release(link);
 
-	if (link->handle) {
-		ret = pcmcia_deregister_client(link->handle);
-		if (ret != CS_SUCCESS)
-			cs_error(link->handle, DeregisterClient, ret);
-	}
-
-	/* Unlink device structure, free bits */
-	*linkp = link->next;
-
 	kfree(info);
 }
 
@@ -891,43 +857,29 @@ static void bt3c_release(dev_link_t *link)
 	link->state &= ~DEV_CONFIG;
 }
 
+static int bt3c_suspend(struct pcmcia_device *dev)
+{
+	dev_link_t *link = dev_to_instance(dev);
 
-static int bt3c_event(event_t event, int priority, event_callback_args_t *args)
+	link->state |= DEV_SUSPEND;
+	if (link->state & DEV_CONFIG)
+		pcmcia_release_configuration(link->handle);
+
+	return 0;
+}
+
+static int bt3c_resume(struct pcmcia_device *dev)
 {
-	dev_link_t *link = args->client_data;
-	bt3c_info_t *info = link->priv;
+	dev_link_t *link = dev_to_instance(dev);
 
-	switch (event) {
-	case CS_EVENT_CARD_REMOVAL:
-		link->state &= ~DEV_PRESENT;
-		if (link->state & DEV_CONFIG) {
-			bt3c_close(info);
-			bt3c_release(link);
-		}
-		break;
-	case CS_EVENT_CARD_INSERTION:
-		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-		bt3c_config(link);
-		break;
-	case CS_EVENT_PM_SUSPEND:
-		link->state |= DEV_SUSPEND;
-		/* Fall through... */
-	case CS_EVENT_RESET_PHYSICAL:
-		if (link->state & DEV_CONFIG)
-			pcmcia_release_configuration(link->handle);
-		break;
-	case CS_EVENT_PM_RESUME:
-		link->state &= ~DEV_SUSPEND;
-		/* Fall through... */
-	case CS_EVENT_CARD_RESET:
-		if (DEV_OK(link))
-			pcmcia_request_configuration(link->handle, &link->conf);
-		break;
-	}
+	link->state &= ~DEV_SUSPEND;
+	if (DEV_OK(link))
+		pcmcia_request_configuration(link->handle, &link->conf);
 
 	return 0;
 }
 
+
 static struct pcmcia_device_id bt3c_ids[] = {
 	PCMCIA_DEVICE_PROD_ID13("3COM", "Bluetooth PC Card", 0xefce0a31, 0xd4ce9b02),
 	PCMCIA_DEVICE_NULL
@@ -939,10 +891,11 @@ static struct pcmcia_driver bt3c_driver = {
 	.drv		= {
 		.name	= "bt3c_cs",
 	},
-	.attach		= bt3c_attach,
-	.event		= bt3c_event,
-	.detach		= bt3c_detach,
+	.probe		= bt3c_attach,
+	.remove		= bt3c_detach,
 	.id_table	= bt3c_ids,
+	.suspend	= bt3c_suspend,
+	.resume		= bt3c_resume,
 };
 
 static int __init init_bt3c_cs(void)
@@ -954,7 +907,6 @@ static int __init init_bt3c_cs(void)
 static void __exit exit_bt3c_cs(void)
 {
 	pcmcia_unregister_driver(&bt3c_driver);
-	BUG_ON(dev_list != NULL);
 }
 
 module_init(init_bt3c_cs);
diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c
index 529a28a3209d..7b4bff4cfa2d 100644
--- a/drivers/bluetooth/btuart_cs.c
+++ b/drivers/bluetooth/btuart_cs.c
@@ -86,14 +86,8 @@ typedef struct btuart_info_t {
 
 static void btuart_config(dev_link_t *link);
 static void btuart_release(dev_link_t *link);
-static int btuart_event(event_t event, int priority, event_callback_args_t *args);
 
-static dev_info_t dev_info = "btuart_cs";
-
-static dev_link_t *btuart_attach(void);
-static void btuart_detach(dev_link_t *);
-
-static dev_link_t *dev_list = NULL;
+static void btuart_detach(struct pcmcia_device *p_dev);
 
 
 /* Maximum baud rate */
@@ -582,17 +576,15 @@ static int btuart_close(btuart_info_t *info)
 	return 0;
 }
 
-static dev_link_t *btuart_attach(void)
+static int btuart_attach(struct pcmcia_device *p_dev)
 {
 	btuart_info_t *info;
-	client_reg_t client_reg;
 	dev_link_t *link;
-	int ret;
 
 	/* Create new info device */
 	info = kzalloc(sizeof(*info), GFP_KERNEL);
 	if (!info)
-		return NULL;
+		return -ENOMEM;
 
 	link = &info->link;
 	link->priv = info;
@@ -609,50 +601,24 @@ static dev_link_t *btuart_attach(void)
 	link->conf.Vcc = 50;
 	link->conf.IntType = INT_MEMORY_AND_IO;
 
-	/* Register with Card Services */
-	link->next = dev_list;
-	dev_list = link;
-	client_reg.dev_info = &dev_info;
-	client_reg.Version = 0x0210;
-	client_reg.event_callback_args.client_data = link;
-
-	ret = pcmcia_register_client(&link->handle, &client_reg);
-	if (ret != CS_SUCCESS) {
-		cs_error(link->handle, RegisterClient, ret);
-		btuart_detach(link);
-		return NULL;
-	}
+	link->handle = p_dev;
+	p_dev->instance = link;
 
-	return link;
+	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+	btuart_config(link);
+
+	return 0;
 }
 
 
-static void btuart_detach(dev_link_t *link)
+static void btuart_detach(struct pcmcia_device *p_dev)
 {
+	dev_link_t *link = dev_to_instance(p_dev);
 	btuart_info_t *info = link->priv;
-	dev_link_t **linkp;
-	int ret;
-
-	/* Locate device structure */
-	for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
-		if (*linkp == link)
-			break;
-
-	if (*linkp == NULL)
-		return;
 
 	if (link->state & DEV_CONFIG)
 		btuart_release(link);
 
-	if (link->handle) {
-		ret = pcmcia_deregister_client(link->handle);
-		if (ret != CS_SUCCESS)
-			cs_error(link->handle, DeregisterClient, ret);
-	}
-
-	/* Unlink device structure, free bits */
-	*linkp = link->next;
-
 	kfree(info);
 }
 
@@ -811,43 +777,29 @@ static void btuart_release(dev_link_t *link)
 	link->state &= ~DEV_CONFIG;
 }
 
+static int btuart_suspend(struct pcmcia_device *dev)
+{
+	dev_link_t *link = dev_to_instance(dev);
 
-static int btuart_event(event_t event, int priority, event_callback_args_t *args)
+	link->state |= DEV_SUSPEND;
+	if (link->state & DEV_CONFIG)
+		pcmcia_release_configuration(link->handle);
+
+	return 0;
+}
+
+static int btuart_resume(struct pcmcia_device *dev)
 {
-	dev_link_t *link = args->client_data;
-	btuart_info_t *info = link->priv;
+	dev_link_t *link = dev_to_instance(dev);
 
-	switch (event) {
-	case CS_EVENT_CARD_REMOVAL:
-		link->state &= ~DEV_PRESENT;
-		if (link->state & DEV_CONFIG) {
-			btuart_close(info);
-			btuart_release(link);
-		}
-		break;
-	case CS_EVENT_CARD_INSERTION:
-		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-		btuart_config(link);
-		break;
-	case CS_EVENT_PM_SUSPEND:
-		link->state |= DEV_SUSPEND;
-		/* Fall through... */
-	case CS_EVENT_RESET_PHYSICAL:
-		if (link->state & DEV_CONFIG)
-			pcmcia_release_configuration(link->handle);
-		break;
-	case CS_EVENT_PM_RESUME:
-		link->state &= ~DEV_SUSPEND;
-		/* Fall through... */
-	case CS_EVENT_CARD_RESET:
-		if (DEV_OK(link))
-			pcmcia_request_configuration(link->handle, &link->conf);
-		break;
-	}
+	link->state &= ~DEV_SUSPEND;
+	if (DEV_OK(link))
+		pcmcia_request_configuration(link->handle, &link->conf);
 
 	return 0;
 }
 
+
 static struct pcmcia_device_id btuart_ids[] = {
 	/* don't use this driver. Use serial_cs + hci_uart instead */
 	PCMCIA_DEVICE_NULL
@@ -859,10 +811,11 @@ static struct pcmcia_driver btuart_driver = {
 	.drv		= {
 		.name	= "btuart_cs",
 	},
-	.attach		= btuart_attach,
-	.event		= btuart_event,
-	.detach		= btuart_detach,
+	.probe		= btuart_attach,
+	.remove		= btuart_detach,
 	.id_table	= btuart_ids,
+	.suspend	= btuart_suspend,
+	.resume		= btuart_resume,
 };
 
 static int __init init_btuart_cs(void)
@@ -874,7 +827,6 @@ static int __init init_btuart_cs(void)
 static void __exit exit_btuart_cs(void)
 {
 	pcmcia_unregister_driver(&btuart_driver);
-	BUG_ON(dev_list != NULL);
 }
 
 module_init(init_btuart_cs);
diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c
index dec5980a1cd6..0449bc45ae5e 100644
--- a/drivers/bluetooth/dtl1_cs.c
+++ b/drivers/bluetooth/dtl1_cs.c
@@ -89,14 +89,8 @@ typedef struct dtl1_info_t {
 
 static void dtl1_config(dev_link_t *link);
 static void dtl1_release(dev_link_t *link);
-static int dtl1_event(event_t event, int priority, event_callback_args_t *args);
 
-static dev_info_t dev_info = "dtl1_cs";
-
-static dev_link_t *dtl1_attach(void);
-static void dtl1_detach(dev_link_t *);
-
-static dev_link_t *dev_list = NULL;
+static void dtl1_detach(struct pcmcia_device *p_dev);
 
 
 /* Transmit states  */
@@ -561,17 +555,15 @@ static int dtl1_close(dtl1_info_t *info)
 	return 0;
 }
 
-static dev_link_t *dtl1_attach(void)
+static int dtl1_attach(struct pcmcia_device *p_dev)
 {
 	dtl1_info_t *info;
-	client_reg_t client_reg;
 	dev_link_t *link;
-	int ret;
 
 	/* Create new info device */
 	info = kzalloc(sizeof(*info), GFP_KERNEL);
 	if (!info)
-		return NULL;
+		return -ENOMEM;
 
 	link = &info->link;
 	link->priv = info;
@@ -588,50 +580,24 @@ static dev_link_t *dtl1_attach(void)
 	link->conf.Vcc = 50;
 	link->conf.IntType = INT_MEMORY_AND_IO;
 
-	/* Register with Card Services */
-	link->next = dev_list;
-	dev_list = link;
-	client_reg.dev_info = &dev_info;
-	client_reg.Version = 0x0210;
-	client_reg.event_callback_args.client_data = link;
-
-	ret = pcmcia_register_client(&link->handle, &client_reg);
-	if (ret != CS_SUCCESS) {
-		cs_error(link->handle, RegisterClient, ret);
-		dtl1_detach(link);
-		return NULL;
-	}
+	link->handle = p_dev;
+	p_dev->instance = link;
 
-	return link;
+	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+	dtl1_config(link);
+
+	return 0;
 }
 
 
-static void dtl1_detach(dev_link_t *link)
+static void dtl1_detach(struct pcmcia_device *p_dev)
 {
+	dev_link_t *link = dev_to_instance(p_dev);
 	dtl1_info_t *info = link->priv;
-	dev_link_t **linkp;
-	int ret;
-
-	/* Locate device structure */
-	for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
-		if (*linkp == link)
-			break;
-
-	if (*linkp == NULL)
-		return;
 
 	if (link->state & DEV_CONFIG)
 		dtl1_release(link);
 
-	if (link->handle) {
-		ret = pcmcia_deregister_client(link->handle);
-		if (ret != CS_SUCCESS)
-			cs_error(link->handle, DeregisterClient, ret);
-	}
-
-	/* Unlink device structure, free bits */
-	*linkp = link->next;
-
 	kfree(info);
 }
 
@@ -763,46 +729,33 @@ static void dtl1_release(dev_link_t *link)
 	link->state &= ~DEV_CONFIG;
 }
 
+static int dtl1_suspend(struct pcmcia_device *dev)
+{
+	dev_link_t *link = dev_to_instance(dev);
 
-static int dtl1_event(event_t event, int priority, event_callback_args_t *args)
+	link->state |= DEV_SUSPEND;
+	if (link->state & DEV_CONFIG)
+		pcmcia_release_configuration(link->handle);
+
+	return 0;
+}
+
+static int dtl1_resume(struct pcmcia_device *dev)
 {
-	dev_link_t *link = args->client_data;
-	dtl1_info_t *info = link->priv;
+	dev_link_t *link = dev_to_instance(dev);
 
-	switch (event) {
-	case CS_EVENT_CARD_REMOVAL:
-		link->state &= ~DEV_PRESENT;
-		if (link->state & DEV_CONFIG) {
-			dtl1_close(info);
-			dtl1_release(link);
-		}
-		break;
-	case CS_EVENT_CARD_INSERTION:
-		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-		dtl1_config(link);
-		break;
-	case CS_EVENT_PM_SUSPEND:
-		link->state |= DEV_SUSPEND;
-		/* Fall through... */
-	case CS_EVENT_RESET_PHYSICAL:
-		if (link->state & DEV_CONFIG)
-			pcmcia_release_configuration(link->handle);
-		break;
-	case CS_EVENT_PM_RESUME:
-		link->state &= ~DEV_SUSPEND;
-		/* Fall through... */
-	case CS_EVENT_CARD_RESET:
-		if (DEV_OK(link))
-			pcmcia_request_configuration(link->handle, &link->conf);
-		break;
-	}
+	link->state &= ~DEV_SUSPEND;
+	if (DEV_OK(link))
+		pcmcia_request_configuration(link->handle, &link->conf);
 
 	return 0;
 }
 
+
 static struct pcmcia_device_id dtl1_ids[] = {
 	PCMCIA_DEVICE_PROD_ID12("Nokia Mobile Phones", "DTL-1", 0xe1bfdd64, 0xe168480d),
 	PCMCIA_DEVICE_PROD_ID12("Socket", "CF", 0xb38bcc2e, 0x44ebf863),
+	PCMCIA_DEVICE_PROD_ID12("Socket", "CF+ Personal Network Card", 0xb38bcc2e, 0xe732bae3),
 	PCMCIA_DEVICE_NULL
 };
 MODULE_DEVICE_TABLE(pcmcia, dtl1_ids);
@@ -812,10 +765,11 @@ static struct pcmcia_driver dtl1_driver = {
 	.drv		= {
 		.name	= "dtl1_cs",
 	},
-	.attach		= dtl1_attach,
-	.event		= dtl1_event,
-	.detach		= dtl1_detach,
+	.probe		= dtl1_attach,
+	.remove		= dtl1_detach,
 	.id_table	= dtl1_ids,
+	.suspend	= dtl1_suspend,
+	.resume		= dtl1_resume,
 };
 
 static int __init init_dtl1_cs(void)
@@ -827,7 +781,6 @@ static int __init init_dtl1_cs(void)
 static void __exit exit_dtl1_cs(void)
 {
 	pcmcia_unregister_driver(&dtl1_driver);
-	BUG_ON(dev_list != NULL);
 }
 
 module_init(init_dtl1_cs);
diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c
index 057cb2b6e6d1..92382e823285 100644
--- a/drivers/bluetooth/hci_usb.c
+++ b/drivers/bluetooth/hci_usb.c
@@ -1044,7 +1044,6 @@ static void hci_usb_disconnect(struct usb_interface *intf)
 }
 
 static struct usb_driver hci_usb_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "hci_usb",
 	.probe		= hci_usb_probe,
 	.disconnect	= hci_usb_disconnect,
diff --git a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c
index ac96de15d833..378e88d20757 100644
--- a/drivers/cdrom/cdu31a.c
+++ b/drivers/cdrom/cdu31a.c
@@ -1402,7 +1402,7 @@ static void do_cdu31a_request(request_queue_t * q)
 			if (!end_that_request_first(req, 1, nblock)) {
 				spin_lock_irq(q->queue_lock);
 				blkdev_dequeue_request(req);
-				end_that_request_last(req);
+				end_that_request_last(req, 1);
 				spin_unlock_irq(q->queue_lock);
 			}
 			continue;
diff --git a/drivers/char/.gitignore b/drivers/char/.gitignore
index 2b6b1d772ed7..73dfdcebfbba 100644
--- a/drivers/char/.gitignore
+++ b/drivers/char/.gitignore
@@ -1,3 +1,3 @@
 consolemap_deftbl.c
 defkeymap.c
-
+qtronixmap.c
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 84e68cdd451b..5ebd06b1b4ca 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -985,7 +985,7 @@ config HPET_MMAP
 
 config HANGCHECK_TIMER
 	tristate "Hangcheck timer"
-	depends on X86 || IA64 || PPC64 || ARCH_S390
+	depends on X86 || IA64 || PPC64 || S390
 	help
 	  The hangcheck-timer module detects when the system has gone
 	  out to lunch past a certain margin.  It can reboot the system
diff --git a/drivers/char/hangcheck-timer.c b/drivers/char/hangcheck-timer.c
index 66e53dd450ff..40a67c86420c 100644
--- a/drivers/char/hangcheck-timer.c
+++ b/drivers/char/hangcheck-timer.c
@@ -120,7 +120,7 @@ __setup("hcheck_dump_tasks", hangcheck_parse_dump_tasks);
 #if defined(CONFIG_X86)
 # define HAVE_MONOTONIC
 # define TIMER_FREQ 1000000000ULL
-#elif defined(CONFIG_ARCH_S390)
+#elif defined(CONFIG_S390)
 /* FA240000 is 1 Second in the IBM time universe (Page 4-38 Principles of Op for zSeries */
 # define TIMER_FREQ 0xFA240000ULL
 #elif defined(CONFIG_IA64)
diff --git a/drivers/char/hw_random.c b/drivers/char/hw_random.c
index 6f673d2de0b1..49769f59ea1b 100644
--- a/drivers/char/hw_random.c
+++ b/drivers/char/hw_random.c
@@ -1,4 +1,9 @@
 /*
+        Added support for the AMD Geode LX RNG
+	(c) Copyright 2004-2005 Advanced Micro Devices, Inc.
+
+	derived from
+
  	Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG)
 	(c) Copyright 2003 Red Hat Inc <jgarzik@redhat.com>
  
@@ -95,6 +100,11 @@ static unsigned int via_data_present (void);
 static u32 via_data_read (void);
 #endif
 
+static int __init geode_init(struct pci_dev *dev);
+static void geode_cleanup(void);
+static unsigned int geode_data_present (void);
+static u32 geode_data_read (void);
+
 struct rng_operations {
 	int (*init) (struct pci_dev *dev);
 	void (*cleanup) (void);
@@ -122,6 +132,7 @@ enum {
 	rng_hw_intel,
 	rng_hw_amd,
 	rng_hw_via,
+	rng_hw_geode,
 };
 
 static struct rng_operations rng_vendor_ops[] = {
@@ -139,6 +150,9 @@ static struct rng_operations rng_vendor_ops[] = {
 	/* rng_hw_via */
 	{ via_init, via_cleanup, via_data_present, via_data_read, 1 },
 #endif
+
+	/* rng_hw_geode */
+	{ geode_init, geode_cleanup, geode_data_present, geode_data_read, 4 }
 };
 
 /*
@@ -159,6 +173,9 @@ static struct pci_device_id rng_pci_tbl[] = {
 	{ 0x8086, 0x244e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel },
 	{ 0x8086, 0x245e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel },
 
+	{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LX_AES,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_geode },
+
 	{ 0, },	/* terminate list */
 };
 MODULE_DEVICE_TABLE (pci, rng_pci_tbl);
@@ -460,6 +477,57 @@ static void via_cleanup(void)
 }
 #endif
 
+/***********************************************************************
+ *
+ * AMD Geode RNG operations
+ *
+ */
+
+static void __iomem *geode_rng_base = NULL;
+
+#define GEODE_RNG_DATA_REG   0x50
+#define GEODE_RNG_STATUS_REG 0x54
+
+static u32 geode_data_read(void)
+{
+	u32 val;
+
+	assert(geode_rng_base != NULL);
+	val = readl(geode_rng_base + GEODE_RNG_DATA_REG);
+	return val;
+}
+
+static unsigned int geode_data_present(void)
+{
+	u32 val;
+
+	assert(geode_rng_base != NULL);
+	val = readl(geode_rng_base + GEODE_RNG_STATUS_REG);
+	return val;
+}
+
+static void geode_cleanup(void)
+{
+	iounmap(geode_rng_base);
+  	geode_rng_base = NULL;
+}
+
+static int geode_init(struct pci_dev *dev)
+{
+	unsigned long rng_base = pci_resource_start(dev, 0);
+
+	if (rng_base == 0)
+		return 1;
+
+	geode_rng_base = ioremap(rng_base, 0x58);
+
+	if (geode_rng_base == NULL) {
+		printk(KERN_ERR PFX "Cannot ioremap RNG memory\n");
+		return -EBUSY;
+	}
+
+	return 0;
+}
 
 /***********************************************************************
  *
@@ -574,7 +642,7 @@ static int __init rng_init (void)
 
 	DPRINTK ("ENTER\n");
 
-	/* Probe for Intel, AMD RNGs */
+	/* Probe for Intel, AMD, Geode RNGs */
 	for_each_pci_dev(pdev) {
 		ent = pci_match_id(rng_pci_tbl, pdev);
 		if (ent) {
diff --git a/drivers/char/ip2/i2pack.h b/drivers/char/ip2/i2pack.h
index e9b87a78622c..00342a677c90 100644
--- a/drivers/char/ip2/i2pack.h
+++ b/drivers/char/ip2/i2pack.h
@@ -358,7 +358,7 @@ typedef struct _failStat
 #define MB_OUT_STRIPPED    0x40  // Board has read all output from fifo 
 #define MB_FATAL_ERROR     0x20  // Board has encountered a fatal error
 
-#pragma pack(4)                  // Reset padding to command-line default
+#pragma pack()                  // Reset padding to command-line default
 
 #endif      // I2PACK_H
 
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index 1f56b4cf0f58..561430ed94af 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -787,7 +787,6 @@ int ipmi_destroy_user(ipmi_user_t user)
 	int              i;
 	unsigned long    flags;
 	struct cmd_rcvr  *rcvr;
-	struct list_head *entry1, *entry2;
 	struct cmd_rcvr  *rcvrs = NULL;
 
 	user->valid = 1;
@@ -812,8 +811,7 @@ int ipmi_destroy_user(ipmi_user_t user)
 	 * synchronize_rcu()) then free everything in that list.
 	 */
 	down(&intf->cmd_rcvrs_lock);
-	list_for_each_safe_rcu(entry1, entry2, &intf->cmd_rcvrs) {
-		rcvr = list_entry(entry1, struct cmd_rcvr, link);
+	list_for_each_entry_rcu(rcvr, &intf->cmd_rcvrs, link) {
 		if (rcvr->user == user) {
 			list_del_rcu(&rcvr->link);
 			rcvr->next = rcvrs;
diff --git a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c
index 78c89a3e7825..c92378121b4c 100644
--- a/drivers/char/mmtimer.c
+++ b/drivers/char/mmtimer.c
@@ -1,11 +1,11 @@
 /*
- * Intel Multimedia Timer device implementation for SGI SN platforms.
+ * Timer device implementation for SGI SN platforms.
  *
  * 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) 2001-2004 Silicon Graphics, Inc.  All rights reserved.
+ * Copyright (c) 2001-2006 Silicon Graphics, Inc.  All rights reserved.
  *
  * This driver exports an API that should be supportable by any HPET or IA-PC
  * multimedia timer.  The code below is currently specific to the SGI Altix
@@ -45,7 +45,7 @@ MODULE_LICENSE("GPL");
 /* name of the device, usually in /dev */
 #define MMTIMER_NAME "mmtimer"
 #define MMTIMER_DESC "SGI Altix RTC Timer"
-#define MMTIMER_VERSION "2.0"
+#define MMTIMER_VERSION "2.1"
 
 #define RTC_BITS 55 /* 55 bits for this implementation */
 
@@ -227,10 +227,7 @@ typedef struct mmtimer {
 	struct tasklet_struct tasklet;
 } mmtimer_t;
 
-/*
- * Total number of comparators is comparators/node * MAX nodes/running kernel
- */
-static mmtimer_t timers[NUM_COMPARATORS*MAX_COMPACT_NODES];
+static mmtimer_t ** timers;
 
 /**
  * mmtimer_ioctl - ioctl interface for /dev/mmtimer
@@ -441,29 +438,29 @@ static irqreturn_t
 mmtimer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	int i;
-	mmtimer_t *base = timers + cpu_to_node(smp_processor_id()) *
-						NUM_COMPARATORS;
 	unsigned long expires = 0;
 	int result = IRQ_NONE;
+	unsigned indx = cpu_to_node(smp_processor_id());
 
 	/*
 	 * Do this once for each comparison register
 	 */
 	for (i = 0; i < NUM_COMPARATORS; i++) {
+		mmtimer_t *base = timers[indx] + i;
 		/* Make sure this doesn't get reused before tasklet_sched */
-		spin_lock(&base[i].lock);
-		if (base[i].cpu == smp_processor_id()) {
-			if (base[i].timer)
-				expires = base[i].timer->it.mmtimer.expires;
+		spin_lock(&base->lock);
+		if (base->cpu == smp_processor_id()) {
+			if (base->timer)
+				expires = base->timer->it.mmtimer.expires;
 			/* expires test won't work with shared irqs */
 			if ((mmtimer_int_pending(i) > 0) ||
 				(expires && (expires < rtc_time()))) {
 				mmtimer_clr_int_pending(i);
-				tasklet_schedule(&base[i].tasklet);
+				tasklet_schedule(&base->tasklet);
 				result = IRQ_HANDLED;
 			}
 		}
-		spin_unlock(&base[i].lock);
+		spin_unlock(&base->lock);
 		expires = 0;
 	}
 	return result;
@@ -523,7 +520,7 @@ static int sgi_timer_del(struct k_itimer *timr)
 {
 	int i = timr->it.mmtimer.clock;
 	cnodeid_t nodeid = timr->it.mmtimer.node;
-	mmtimer_t *t = timers + nodeid * NUM_COMPARATORS +i;
+	mmtimer_t *t = timers[nodeid] + i;
 	unsigned long irqflags;
 
 	if (i != TIMER_OFF) {
@@ -609,11 +606,11 @@ static int sgi_timer_set(struct k_itimer *timr, int flags,
 	preempt_disable();
 
 	nodeid =  cpu_to_node(smp_processor_id());
-	base = timers + nodeid * NUM_COMPARATORS;
 retry:
 	/* Don't use an allocated timer, or a deleted one that's pending */
 	for(i = 0; i< NUM_COMPARATORS; i++) {
-		if (!base[i].timer && !base[i].tasklet.state) {
+		base = timers[nodeid] + i;
+		if (!base->timer && !base->tasklet.state) {
 			break;
 		}
 	}
@@ -623,14 +620,14 @@ retry:
 		return -EBUSY;
 	}
 
-	spin_lock_irqsave(&base[i].lock, irqflags);
+	spin_lock_irqsave(&base->lock, irqflags);
 
-	if (base[i].timer || base[i].tasklet.state != 0) {
-		spin_unlock_irqrestore(&base[i].lock, irqflags);
+	if (base->timer || base->tasklet.state != 0) {
+		spin_unlock_irqrestore(&base->lock, irqflags);
 		goto retry;
 	}
-	base[i].timer = timr;
-	base[i].cpu = smp_processor_id();
+	base->timer = timr;
+	base->cpu = smp_processor_id();
 
 	timr->it.mmtimer.clock = i;
 	timr->it.mmtimer.node = nodeid;
@@ -645,11 +642,11 @@ retry:
 		}
 	} else {
 		timr->it.mmtimer.expires -= period;
-		if (reschedule_periodic_timer(base+i))
+		if (reschedule_periodic_timer(base))
 			err = -EINVAL;
 	}
 
-	spin_unlock_irqrestore(&base[i].lock, irqflags);
+	spin_unlock_irqrestore(&base->lock, irqflags);
 
 	preempt_enable();
 
@@ -675,6 +672,7 @@ static struct k_clock sgi_clock = {
 static int __init mmtimer_init(void)
 {
 	unsigned i;
+	cnodeid_t node, maxn = -1;
 
 	if (!ia64_platform_is("sn2"))
 		return -1;
@@ -691,14 +689,6 @@ static int __init mmtimer_init(void)
 	mmtimer_femtoperiod = ((unsigned long)1E15 + sn_rtc_cycles_per_second /
 			       2) / sn_rtc_cycles_per_second;
 
-	for (i=0; i< NUM_COMPARATORS*MAX_COMPACT_NODES; i++) {
-		spin_lock_init(&timers[i].lock);
-		timers[i].timer = NULL;
-		timers[i].cpu = 0;
-		timers[i].i = i % NUM_COMPARATORS;
-		tasklet_init(&timers[i].tasklet, mmtimer_tasklet, (unsigned long) (timers+i));
-	}
-
 	if (request_irq(SGI_MMTIMER_VECTOR, mmtimer_interrupt, SA_PERCPU_IRQ, MMTIMER_NAME, NULL)) {
 		printk(KERN_WARNING "%s: unable to allocate interrupt.",
 			MMTIMER_NAME);
@@ -712,6 +702,40 @@ static int __init mmtimer_init(void)
 		return -1;
 	}
 
+	/* Get max numbered node, calculate slots needed */
+	for_each_online_node(node) {
+		maxn = node;
+	}
+	maxn++;
+
+	/* Allocate list of node ptrs to mmtimer_t's */
+	timers = kmalloc(sizeof(mmtimer_t *)*maxn, GFP_KERNEL);
+	if (timers == NULL) {
+		printk(KERN_ERR "%s: failed to allocate memory for device\n",
+				MMTIMER_NAME);
+		return -1;
+	}
+
+	/* Allocate mmtimer_t's for each online node */
+	for_each_online_node(node) {
+		timers[node] = kmalloc_node(sizeof(mmtimer_t)*NUM_COMPARATORS, GFP_KERNEL, node);
+		if (timers[node] == NULL) {
+			printk(KERN_ERR "%s: failed to allocate memory for device\n",
+				MMTIMER_NAME);
+			return -1;
+		}
+		for (i=0; i< NUM_COMPARATORS; i++) {
+			mmtimer_t * base = timers[node] + i;
+
+			spin_lock_init(&base->lock);
+			base->timer = NULL;
+			base->cpu = 0;
+			base->i = i;
+			tasklet_init(&base->tasklet, mmtimer_tasklet,
+				(unsigned long) (base));
+		}
+	}
+
 	sgi_clock_period = sgi_clock.res = NSEC_PER_SEC / sn_rtc_cycles_per_second;
 	register_posix_clock(CLOCK_SGI_CYCLE, &sgi_clock);
 
diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c
index c3660d8781a4..a133a62f3d55 100644
--- a/drivers/char/n_hdlc.c
+++ b/drivers/char/n_hdlc.c
@@ -562,7 +562,7 @@ static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *data,
 }	/* end of n_hdlc_tty_receive() */
 
 /**
- * n_hdlc_tty_read - Called to retreive one frame of data (if available)
+ * n_hdlc_tty_read - Called to retrieve one frame of data (if available)
  * @tty - pointer to tty instance data
  * @file - pointer to open file object
  * @buf - pointer to returned data buffer
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c
index 61681c9f3f72..649677b5dc36 100644
--- a/drivers/char/pcmcia/cm4000_cs.c
+++ b/drivers/char/pcmcia/cm4000_cs.c
@@ -66,7 +66,6 @@ static char *version = "cm4000_cs.c v2.4.0gm5 - All bugs added by Harald Welte";
 #define	T_100MSEC	msecs_to_jiffies(100)
 #define	T_500MSEC	msecs_to_jiffies(500)
 
-static void cm4000_detach(dev_link_t *link);
 static void cm4000_release(dev_link_t *link);
 
 static int major;		/* major number we get from the kernel */
@@ -156,7 +155,6 @@ struct cm4000_dev {
 		/*sbuf*/ 512*sizeof(char) - 			\
 		/*queue*/ 4*sizeof(wait_queue_head_t))
 
-static dev_info_t dev_info = MODULE_NAME;
 static dev_link_t *dev_table[CM4000_MAX_DEV];
 
 /* This table doesn't use spaces after the comma between fields and thus
@@ -1864,68 +1862,36 @@ cs_release:
 	link->state &= ~DEV_CONFIG_PENDING;
 }
 
-static int cm4000_event(event_t event, int priority,
-			event_callback_args_t *args)
+static int cm4000_suspend(struct pcmcia_device *p_dev)
 {
-	dev_link_t *link;
+	dev_link_t *link = dev_to_instance(p_dev);
 	struct cm4000_dev *dev;
-	int devno;
 
-	link = args->client_data;
 	dev = link->priv;
 
-	DEBUGP(3, dev, "-> cm4000_event\n");
-	for (devno = 0; devno < CM4000_MAX_DEV; devno++)
-		if (dev_table[devno] == link)
-			break;
+	link->state |= DEV_SUSPEND;
+	if (link->state & DEV_CONFIG)
+		pcmcia_release_configuration(link->handle);
+	stop_monitor(dev);
 
-	if (devno == CM4000_MAX_DEV)
-		return CS_BAD_ADAPTER;
+	return 0;
+}
 
-	switch (event) {
-	case CS_EVENT_CARD_INSERTION:
-		DEBUGP(5, dev, "CS_EVENT_CARD_INSERTION\n");
-		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-		cm4000_config(link, devno);
-		break;
-	case CS_EVENT_CARD_REMOVAL:
-		DEBUGP(5, dev, "CS_EVENT_CARD_REMOVAL\n");
-		link->state &= ~DEV_PRESENT;
-		stop_monitor(dev);
-		break;
-	case CS_EVENT_PM_SUSPEND:
-		DEBUGP(5, dev, "CS_EVENT_PM_SUSPEND "
-		      "(fall-through to CS_EVENT_RESET_PHYSICAL)\n");
-		link->state |= DEV_SUSPEND;
-		/* fall-through */
-	case CS_EVENT_RESET_PHYSICAL:
-		DEBUGP(5, dev, "CS_EVENT_RESET_PHYSICAL\n");
-		if (link->state & DEV_CONFIG) {
-			DEBUGP(5, dev, "ReleaseConfiguration\n");
-			pcmcia_release_configuration(link->handle);
-		}
-		stop_monitor(dev);
-		break;
-	case CS_EVENT_PM_RESUME:
-		DEBUGP(5, dev, "CS_EVENT_PM_RESUME "
-		      "(fall-through to CS_EVENT_CARD_RESET)\n");
-		link->state &= ~DEV_SUSPEND;
-		/* fall-through */
-	case CS_EVENT_CARD_RESET:
-		DEBUGP(5, dev, "CS_EVENT_CARD_RESET\n");
-		if ((link->state & DEV_CONFIG)) {
-			DEBUGP(5, dev, "RequestConfiguration\n");
-			pcmcia_request_configuration(link->handle, &link->conf);
-		}
-		if (link->open)
-			start_monitor(dev);
-		break;
-	default:
-		DEBUGP(5, dev, "unknown event %.2x\n", event);
-		break;
-	}
-	DEBUGP(3, dev, "<- cm4000_event\n");
-	return CS_SUCCESS;
+static int cm4000_resume(struct pcmcia_device *p_dev)
+{
+	dev_link_t *link = dev_to_instance(p_dev);
+	struct cm4000_dev *dev;
+
+	dev = link->priv;
+
+	link->state &= ~DEV_SUSPEND;
+	if (link->state & DEV_CONFIG)
+		pcmcia_request_configuration(link->handle, &link->conf);
+
+	if (link->open)
+		start_monitor(dev);
+
+	return 0;
 }
 
 static void cm4000_release(dev_link_t *link)
@@ -1935,11 +1901,10 @@ static void cm4000_release(dev_link_t *link)
 	pcmcia_release_io(link->handle, &link->io);
 }
 
-static dev_link_t *cm4000_attach(void)
+static int cm4000_attach(struct pcmcia_device *p_dev)
 {
 	struct cm4000_dev *dev;
 	dev_link_t *link;
-	client_reg_t client_reg;
 	int i;
 
 	for (i = 0; i < CM4000_MAX_DEV; i++)
@@ -1948,76 +1913,55 @@ static dev_link_t *cm4000_attach(void)
 
 	if (i == CM4000_MAX_DEV) {
 		printk(KERN_NOTICE MODULE_NAME ": all devices in use\n");
-		return NULL;
+		return -ENODEV;
 	}
 
 	/* create a new cm4000_cs device */
 	dev = kzalloc(sizeof(struct cm4000_dev), GFP_KERNEL);
 	if (dev == NULL)
-		return NULL;
+		return -ENOMEM;
 
 	link = &dev->link;
 	link->priv = dev;
 	link->conf.IntType = INT_MEMORY_AND_IO;
 	dev_table[i] = link;
 
-	/* register with card services */
-	client_reg.dev_info = &dev_info;
-	client_reg.EventMask =
-	    CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
-	    CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
-	    CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
-	client_reg.Version = 0x0210;
-	client_reg.event_callback_args.client_data = link;
-
-	i = pcmcia_register_client(&link->handle, &client_reg);
-	if (i) {
-		cs_error(link->handle, RegisterClient, i);
-		cm4000_detach(link);
-		return NULL;
-	}
-
 	init_waitqueue_head(&dev->devq);
 	init_waitqueue_head(&dev->ioq);
 	init_waitqueue_head(&dev->atrq);
 	init_waitqueue_head(&dev->readq);
 
-	return link;
-}
-
-static void cm4000_detach_by_devno(int devno, dev_link_t * link)
-{
-	struct cm4000_dev *dev = link->priv;
-
-	DEBUGP(3, dev, "-> detach_by_devno(devno=%d)\n", devno);
-
-	if (link->state & DEV_CONFIG) {
-		DEBUGP(5, dev, "device still configured (try to release it)\n");
-		cm4000_release(link);
-	}
+	link->handle = p_dev;
+	p_dev->instance = link;
 
-	if (link->handle) {
-		pcmcia_deregister_client(link->handle);
-	}
+	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+	cm4000_config(link, i);
 
-	dev_table[devno] = NULL;
-	kfree(dev);
-	return;
+	return 0;
 }
 
-static void cm4000_detach(dev_link_t * link)
+static void cm4000_detach(struct pcmcia_device *p_dev)
 {
-	int i;
+	dev_link_t *link = dev_to_instance(p_dev);
+	struct cm4000_dev *dev = link->priv;
+	int devno;
 
 	/* find device */
-	for (i = 0; i < CM4000_MAX_DEV; i++)
-		if (dev_table[i] == link)
+	for (devno = 0; devno < CM4000_MAX_DEV; devno++)
+		if (dev_table[devno] == link)
 			break;
-
-	if (i == CM4000_MAX_DEV)
+	if (devno == CM4000_MAX_DEV)
 		return;
 
-	cm4000_detach_by_devno(i, link);
+	link->state &= ~DEV_PRESENT;
+	stop_monitor(dev);
+
+	if (link->state & DEV_CONFIG)
+ 		cm4000_release(link);
+
+	dev_table[devno] = NULL;
+ 	kfree(dev);
+
 	return;
 }
 
@@ -2042,9 +1986,10 @@ static struct pcmcia_driver cm4000_driver = {
 	.drv	  = {
 		.name = "cm4000_cs",
 		},
-	.attach   = cm4000_attach,
-	.detach   = cm4000_detach,
-	.event	  = cm4000_event,
+	.probe    = cm4000_attach,
+	.remove   = cm4000_detach,
+	.suspend  = cm4000_suspend,
+	.resume   = cm4000_resume,
 	.id_table = cm4000_ids,
 };
 
@@ -2064,13 +2009,8 @@ static int __init cmm_init(void)
 
 static void __exit cmm_exit(void)
 {
-	int i;
-
 	printk(KERN_INFO MODULE_NAME ": unloading\n");
 	pcmcia_unregister_driver(&cm4000_driver);
-	for (i = 0; i < CM4000_MAX_DEV; i++)
-		if (dev_table[i])
-			cm4000_detach_by_devno(i, dev_table[i]);
 	unregister_chrdev(major, DEVICE_NAME);
 };
 
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c
index 4c698d908ffa..46eb371bf17e 100644
--- a/drivers/char/pcmcia/cm4040_cs.c
+++ b/drivers/char/pcmcia/cm4040_cs.c
@@ -65,7 +65,6 @@ static char *version =
 #define POLL_PERIOD 				msecs_to_jiffies(10)
 
 static void reader_release(dev_link_t *link);
-static void reader_detach(dev_link_t *link);
 
 static int major;
 
@@ -86,7 +85,6 @@ struct reader_dev {
 	struct timer_list 	poll_timer;
 };
 
-static dev_info_t dev_info = MODULE_NAME;
 static dev_link_t *dev_table[CM_MAX_DEV];
 
 #ifndef PCMCIA_DEBUG
@@ -629,65 +627,26 @@ cs_release:
 	link->state &= ~DEV_CONFIG_PENDING;
 }
 
-static int reader_event(event_t event, int priority,
-			event_callback_args_t *args)
+static int reader_suspend(struct pcmcia_device *p_dev)
 {
-	dev_link_t *link;
-	struct reader_dev *dev;
-	int devno;
+	dev_link_t *link = dev_to_instance(p_dev);
 
-	link = args->client_data;
-	dev = link->priv;
-	DEBUGP(3, dev, "-> reader_event\n");
-	for (devno = 0; devno < CM_MAX_DEV; devno++) {
-		if (dev_table[devno] == link)
-			break;
-	}
-	if (devno == CM_MAX_DEV)
-		return CS_BAD_ADAPTER;
+	link->state |= DEV_SUSPEND;
+	if (link->state & DEV_CONFIG)
+		pcmcia_release_configuration(link->handle);
 
-	switch (event) {
-		case CS_EVENT_CARD_INSERTION:
-			DEBUGP(5, dev, "CS_EVENT_CARD_INSERTION\n");
-			link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-			reader_config(link, devno);
-			break;
-		case CS_EVENT_CARD_REMOVAL:
-			DEBUGP(5, dev, "CS_EVENT_CARD_REMOVAL\n");
-			link->state &= ~DEV_PRESENT;
-			break;
-		case CS_EVENT_PM_SUSPEND:
-			DEBUGP(5, dev, "CS_EVENT_PM_SUSPEND "
-			      "(fall-through to CS_EVENT_RESET_PHYSICAL)\n");
-			link->state |= DEV_SUSPEND;
-
-		case CS_EVENT_RESET_PHYSICAL:
-			DEBUGP(5, dev, "CS_EVENT_RESET_PHYSICAL\n");
-			if (link->state & DEV_CONFIG) {
-		  		DEBUGP(5, dev, "ReleaseConfiguration\n");
-		  		pcmcia_release_configuration(link->handle);
-			}
-			break;
-		case CS_EVENT_PM_RESUME:
-			DEBUGP(5, dev, "CS_EVENT_PM_RESUME "
-			      "(fall-through to CS_EVENT_CARD_RESET)\n");
-			link->state &= ~DEV_SUSPEND;
-
-		case CS_EVENT_CARD_RESET:
-			DEBUGP(5, dev, "CS_EVENT_CARD_RESET\n");
-			if ((link->state & DEV_CONFIG)) {
-				DEBUGP(5, dev, "RequestConfiguration\n");
-		  		pcmcia_request_configuration(link->handle,
-							     &link->conf);
-			}
-			break;
-		default:
-			DEBUGP(5, dev, "reader_event: unknown event %.2x\n",
-			       event);
-			break;
-	}
-	DEBUGP(3, dev, "<- reader_event\n");
-	return CS_SUCCESS;
+	return 0;
+}
+
+static int reader_resume(struct pcmcia_device *p_dev)
+{
+	dev_link_t *link = dev_to_instance(p_dev);
+
+	link->state &= ~DEV_SUSPEND;
+	if (link->state & DEV_CONFIG)
+		pcmcia_request_configuration(link->handle, &link->conf);
+
+	return 0;
 }
 
 static void reader_release(dev_link_t *link)
@@ -697,11 +656,10 @@ static void reader_release(dev_link_t *link)
 	pcmcia_release_io(link->handle, &link->io);
 }
 
-static dev_link_t *reader_attach(void)
+static int reader_attach(struct pcmcia_device *p_dev)
 {
 	struct reader_dev *dev;
 	dev_link_t *link;
-	client_reg_t client_reg;
 	int i;
 
 	for (i = 0; i < CM_MAX_DEV; i++) {
@@ -710,11 +668,11 @@ static dev_link_t *reader_attach(void)
 	}
 
 	if (i == CM_MAX_DEV)
-		return NULL;
+		return -ENODEV;
 
 	dev = kzalloc(sizeof(struct reader_dev), GFP_KERNEL);
 	if (dev == NULL)
-		return NULL;
+		return -ENOMEM;
 
 	dev->timeout = CCID_DRIVER_MINIMUM_TIMEOUT;
 	dev->buffer_status = 0;
@@ -725,20 +683,6 @@ static dev_link_t *reader_attach(void)
 	link->conf.IntType = INT_MEMORY_AND_IO;
 	dev_table[i] = link;
 
-	client_reg.dev_info = &dev_info;
-	client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
-	client_reg.EventMask=
-		CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
-		CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
-		CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
-	client_reg.Version = 0x0210;
-	client_reg.event_callback_args.client_data = link;
-	i = pcmcia_register_client(&link->handle, &client_reg);
-	if (i) {
-		cs_error(link->handle, RegisterClient, i);
-		reader_detach(link);
-		return NULL;
-	}
 	init_waitqueue_head(&dev->devq);
 	init_waitqueue_head(&dev->poll_wait);
 	init_waitqueue_head(&dev->read_wait);
@@ -746,39 +690,37 @@ static dev_link_t *reader_attach(void)
 	init_timer(&dev->poll_timer);
 	dev->poll_timer.function = &cm4040_do_poll;
 
-	return link;
-}
-
-static void reader_detach_by_devno(int devno, dev_link_t *link)
-{
-	struct reader_dev *dev = link->priv;
+	link->handle = p_dev;
+	p_dev->instance = link;
 
-	if (link->state & DEV_CONFIG) {
-		DEBUGP(5, dev, "device still configured (try to release it)\n");
-		reader_release(link);
-	}
+	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+	reader_config(link, i);
 
-	pcmcia_deregister_client(link->handle);
-	dev_table[devno] = NULL;
-	DEBUGP(5, dev, "freeing dev=%p\n", dev);
-	cm4040_stop_poll(dev);
-	kfree(dev);
-	return;
+	return 0;
 }
 
-static void reader_detach(dev_link_t *link)
+static void reader_detach(struct pcmcia_device *p_dev)
 {
-	int i;
+	dev_link_t *link = dev_to_instance(p_dev);
+	struct reader_dev *dev = link->priv;
+	int devno;
 
 	/* find device */
-	for (i = 0; i < CM_MAX_DEV; i++) {
-		if (dev_table[i] == link)
+	for (devno = 0; devno < CM_MAX_DEV; devno++) {
+		if (dev_table[devno] == link)
 			break;
 	}
-	if (i == CM_MAX_DEV)
+	if (devno == CM_MAX_DEV)
 		return;
 
-	reader_detach_by_devno(i, link);
+	link->state &= ~DEV_PRESENT;
+
+	if (link->state & DEV_CONFIG)
+		reader_release(link);
+
+	dev_table[devno] = NULL;
+	kfree(dev);
+
 	return;
 }
 
@@ -804,9 +746,10 @@ static struct pcmcia_driver reader_driver = {
   	.drv		= {
 		.name	= "cm4040_cs",
 	},
-	.attach		= reader_attach,
-	.detach		= reader_detach,
-	.event		= reader_event,
+	.probe		= reader_attach,
+	.remove		= reader_detach,
+	.suspend	= reader_suspend,
+	.resume		= reader_resume,
 	.id_table	= cm4040_ids,
 };
 
@@ -825,14 +768,8 @@ static int __init cm4040_init(void)
 
 static void __exit cm4040_exit(void)
 {
-	int i;
-
 	printk(KERN_INFO MODULE_NAME ": unloading\n");
 	pcmcia_unregister_driver(&reader_driver);
-	for (i = 0; i < CM_MAX_DEV; i++) {
-		if (dev_table[i])
-			reader_detach_by_devno(i, dev_table[i]);
-	}
 	unregister_chrdev(major, DEVICE_NAME);
 }
 
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index 2c326ea53421..cf45b100eff1 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -486,13 +486,7 @@ static void mgslpc_wait_until_sent(struct tty_struct *tty, int timeout);
 
 static void mgslpc_config(dev_link_t *link);
 static void mgslpc_release(u_long arg);
-static int  mgslpc_event(event_t event, int priority,
-			 event_callback_args_t *args);
-static dev_link_t *mgslpc_attach(void);
-static void mgslpc_detach(dev_link_t *);
-
-static dev_info_t dev_info = "synclink_cs";
-static dev_link_t *dev_list = NULL;
+static void mgslpc_detach(struct pcmcia_device *p_dev);
 
 /*
  * 1st function defined in .text section. Calling this function in
@@ -539,12 +533,10 @@ static void ldisc_receive_buf(struct tty_struct *tty,
 	}
 }
 
-static dev_link_t *mgslpc_attach(void)
+static int mgslpc_attach(struct pcmcia_device *p_dev)
 {
     MGSLPC_INFO *info;
     dev_link_t *link;
-    client_reg_t client_reg;
-    int ret;
     
     if (debug_level >= DEBUG_LEVEL_INFO)
 	    printk("mgslpc_attach\n");
@@ -552,7 +544,7 @@ static dev_link_t *mgslpc_attach(void)
     info = (MGSLPC_INFO *)kmalloc(sizeof(MGSLPC_INFO), GFP_KERNEL);
     if (!info) {
 	    printk("Error can't allocate device instance data\n");
-	    return NULL;
+	    return -ENOMEM;
     }
 
     memset(info, 0, sizeof(MGSLPC_INFO));
@@ -587,24 +579,15 @@ static dev_link_t *mgslpc_attach(void)
     link->conf.Vcc = 50;
     link->conf.IntType = INT_MEMORY_AND_IO;
 
-    /* Register with Card Services */
-    link->next = dev_list;
-    dev_list = link;
-
-    client_reg.dev_info = &dev_info;
-    client_reg.Version = 0x0210;
-    client_reg.event_callback_args.client_data = link;
+    link->handle = p_dev;
+    p_dev->instance = link;
 
-    ret = pcmcia_register_client(&link->handle, &client_reg);
-    if (ret != CS_SUCCESS) {
-	    cs_error(link->handle, RegisterClient, ret);
-	    mgslpc_detach(link);
-	    return NULL;
-    }
+    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+    mgslpc_config(link);
 
     mgslpc_add_device(info);
 
-    return link;
+    return 0;
 }
 
 /* Card has been inserted.
@@ -736,85 +719,50 @@ static void mgslpc_release(u_long arg)
 	    pcmcia_release_io(link->handle, &link->io);
     if (link->irq.AssignedIRQ)
 	    pcmcia_release_irq(link->handle, &link->irq);
-    if (link->state & DEV_STALE_LINK)
-	    mgslpc_detach(link);
 }
 
-static void mgslpc_detach(dev_link_t *link)
+static void mgslpc_detach(struct pcmcia_device *p_dev)
 {
-    dev_link_t **linkp;
+    dev_link_t *link = dev_to_instance(p_dev);
 
     if (debug_level >= DEBUG_LEVEL_INFO)
 	    printk("mgslpc_detach(0x%p)\n", link);
-    
-    /* find device */
-    for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
-	    if (*linkp == link) break;
-    if (*linkp == NULL)
-	    return;
 
     if (link->state & DEV_CONFIG) {
-	    /* device is configured/active, mark it so when
-	     * release() is called a proper detach() occurs.
-	     */
-	    if (debug_level >= DEBUG_LEVEL_INFO)
-		    printk(KERN_DEBUG "synclinkpc: detach postponed, '%s' "
-			   "still locked\n", link->dev->dev_name);
-	    link->state |= DEV_STALE_LINK;
-	    return;
+	    ((MGSLPC_INFO *)link->priv)->stop = 1;
+	    mgslpc_release((u_long)link);
     }
 
-    /* Break the link with Card Services */
-    if (link->handle)
-	    pcmcia_deregister_client(link->handle);
-    
-    /* Unlink device structure, and free it */
-    *linkp = link->next;
     mgslpc_remove_device((MGSLPC_INFO *)link->priv);
 }
 
-static int mgslpc_event(event_t event, int priority,
-			event_callback_args_t *args)
+static int mgslpc_suspend(struct pcmcia_device *dev)
 {
-    dev_link_t *link = args->client_data;
-    MGSLPC_INFO *info = link->priv;
-    
-    if (debug_level >= DEBUG_LEVEL_INFO)
-	    printk("mgslpc_event(0x%06x)\n", event);
-    
-    switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-	    link->state &= ~DEV_PRESENT;
-	    if (link->state & DEV_CONFIG) {
-		    ((MGSLPC_INFO *)link->priv)->stop = 1;
-		    mgslpc_release((u_long)link);
-	    }
-	    break;
-    case CS_EVENT_CARD_INSERTION:
-	    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-	    mgslpc_config(link);
-	    break;
-    case CS_EVENT_PM_SUSPEND:
-	    link->state |= DEV_SUSPEND;
-	    /* Fall through... */
-    case CS_EVENT_RESET_PHYSICAL:
-	    /* Mark the device as stopped, to block IO until later */
-	    info->stop = 1;
-	    if (link->state & DEV_CONFIG)
-		    pcmcia_release_configuration(link->handle);
-	    break;
-    case CS_EVENT_PM_RESUME:
-	    link->state &= ~DEV_SUSPEND;
-	    /* Fall through... */
-    case CS_EVENT_CARD_RESET:
-	    if (link->state & DEV_CONFIG)
-		    pcmcia_request_configuration(link->handle, &link->conf);
-	    info->stop = 0;
-	    break;
-    }
-    return 0;
+	dev_link_t *link = dev_to_instance(dev);
+	MGSLPC_INFO *info = link->priv;
+
+	link->state |= DEV_SUSPEND;
+	info->stop = 1;
+	if (link->state & DEV_CONFIG)
+		pcmcia_release_configuration(link->handle);
+
+	return 0;
 }
 
+static int mgslpc_resume(struct pcmcia_device *dev)
+{
+	dev_link_t *link = dev_to_instance(dev);
+	MGSLPC_INFO *info = link->priv;
+
+	link->state &= ~DEV_SUSPEND;
+	if (link->state & DEV_CONFIG)
+		pcmcia_request_configuration(link->handle, &link->conf);
+	info->stop = 0;
+
+	return 0;
+}
+
+
 static inline int mgslpc_paranoia_check(MGSLPC_INFO *info,
 					char *name, const char *routine)
 {
@@ -3091,10 +3039,11 @@ static struct pcmcia_driver mgslpc_driver = {
 	.drv		= {
 		.name	= "synclink_cs",
 	},
-	.attach		= mgslpc_attach,
-	.event		= mgslpc_event,
-	.detach		= mgslpc_detach,
+	.probe		= mgslpc_attach,
+	.remove		= mgslpc_detach,
 	.id_table	= mgslpc_ids,
+	.suspend	= mgslpc_suspend,
+	.resume		= mgslpc_resume,
 };
 
 static struct tty_operations mgslpc_ops = {
@@ -3138,7 +3087,6 @@ static void synclink_cs_cleanup(void)
 	}
 
 	pcmcia_unregister_driver(&mgslpc_driver);
-	BUG_ON(dev_list != NULL);
 }
 
 static int __init synclink_cs_init(void)
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 7999da25fe40..bdfdfd28594d 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1554,10 +1554,8 @@ __u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr,
 
 EXPORT_SYMBOL(secure_tcp_sequence_number);
 
-
-
-/* Generate secure starting point for ephemeral TCP port search */
-u32 secure_tcp_port_ephemeral(__u32 saddr, __u32 daddr, __u16 dport)
+/* Generate secure starting point for ephemeral IPV4 transport port search */
+u32 secure_ipv4_port_ephemeral(__u32 saddr, __u32 daddr, __u16 dport)
 {
 	struct keydata *keyptr = get_keyptr();
 	u32 hash[4];
@@ -1575,7 +1573,7 @@ u32 secure_tcp_port_ephemeral(__u32 saddr, __u32 daddr, __u16 dport)
 }
 
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-u32 secure_tcpv6_port_ephemeral(const __u32 *saddr, const __u32 *daddr, __u16 dport)
+u32 secure_ipv6_port_ephemeral(const __u32 *saddr, const __u32 *daddr, __u16 dport)
 {
 	struct keydata *keyptr = get_keyptr();
 	u32 hash[12];
@@ -1586,7 +1584,7 @@ u32 secure_tcpv6_port_ephemeral(const __u32 *saddr, const __u32 *daddr, __u16 dp
 
 	return twothirdsMD4Transform(daddr, hash);
 }
-EXPORT_SYMBOL(secure_tcpv6_port_ephemeral);
+EXPORT_SYMBOL(secure_ipv6_port_ephemeral);
 #endif
 
 #if defined(CONFIG_IP_DCCP) || defined(CONFIG_IP_DCCP_MODULE)
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
index 344001b45af9..a6544790af60 100644
--- a/drivers/char/watchdog/Kconfig
+++ b/drivers/char/watchdog/Kconfig
@@ -438,7 +438,7 @@ config INDYDOG
 
 config ZVM_WATCHDOG
 	tristate "z/VM Watchdog Timer"
-	depends on WATCHDOG && ARCH_S390
+	depends on WATCHDOG && S390
 	help
 	  IBM s/390 and zSeries machines running under z/VM 5.1 or later
 	  provide a virtual watchdog timer to their guest that cause a
diff --git a/drivers/char/watchdog/ixp4xx_wdt.c b/drivers/char/watchdog/ixp4xx_wdt.c
index b5be8b11104a..3800835ca8f3 100644
--- a/drivers/char/watchdog/ixp4xx_wdt.c
+++ b/drivers/char/watchdog/ixp4xx_wdt.c
@@ -186,8 +186,8 @@ static int __init ixp4xx_wdt_init(void)
 	unsigned long processor_id;
 
 	asm("mrc p15, 0, %0, cr0, cr0, 0;" : "=r"(processor_id) :);
-	if (!(processor_id & 0xf)) {
-		printk("IXP4XXX Watchdog: Rev. A0 CPU detected - "
+	if (!(processor_id & 0xf) && !cpu_is_ixp46x()) {
+		printk("IXP4XXX Watchdog: Rev. A0 IXP42x CPU detected - "
 			"watchdog disabled\n");
 
 		return -ENODEV;
diff --git a/drivers/char/watchdog/pcwd_usb.c b/drivers/char/watchdog/pcwd_usb.c
index 092e9b133750..1533f56baa42 100644
--- a/drivers/char/watchdog/pcwd_usb.c
+++ b/drivers/char/watchdog/pcwd_usb.c
@@ -151,7 +151,6 @@ static void usb_pcwd_disconnect	(struct usb_interface *interface);
 
 /* usb specific object needed to register this driver with the usb subsystem */
 static struct usb_driver usb_pcwd_driver = {
-	.owner =	THIS_MODULE,
 	.name =		DRIVER_NAME,
 	.probe =	usb_pcwd_probe,
 	.disconnect =	usb_pcwd_disconnect,
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 815902c2c856..a9163d02983a 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -823,6 +823,30 @@ static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq, unsigne
 
 
 /** 
+ * cpufreq_quick_get - get the CPU frequency (in kHz) frpm policy->cur
+ * @cpu: CPU number
+ *
+ * This is the last known freq, without actually getting it from the driver.
+ * Return value will be same as what is shown in scaling_cur_freq in sysfs.
+ */
+unsigned int cpufreq_quick_get(unsigned int cpu)
+{
+	struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
+	unsigned int ret = 0;
+
+	if (policy) {
+		down(&policy->lock);
+		ret = policy->cur;
+		up(&policy->lock);
+		cpufreq_cpu_put(policy);
+	}
+
+	return (ret);
+}
+EXPORT_SYMBOL(cpufreq_quick_get);
+
+
+/** 
  * cpufreq_get - get the current CPU frequency (in kHz)
  * @cpu: CPU number
  *
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index 2ed5c4363b53..39543a2bed0f 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -93,7 +93,7 @@ static inline unsigned int get_cpu_idle_time(unsigned int cpu)
 {
 	return	kstat_cpu(cpu).cpustat.idle +
 		kstat_cpu(cpu).cpustat.iowait +
-		( !dbs_tuners_ins.ignore_nice ? 
+		( dbs_tuners_ins.ignore_nice ?
 		  kstat_cpu(cpu).cpustat.nice :
 		  0);
 }
@@ -127,7 +127,7 @@ show_one(sampling_rate, sampling_rate);
 show_one(sampling_down_factor, sampling_down_factor);
 show_one(up_threshold, up_threshold);
 show_one(down_threshold, down_threshold);
-show_one(ignore_nice, ignore_nice);
+show_one(ignore_nice_load, ignore_nice);
 show_one(freq_step, freq_step);
 
 static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused, 
@@ -207,7 +207,7 @@ static ssize_t store_down_threshold(struct cpufreq_policy *unused,
 	return count;
 }
 
-static ssize_t store_ignore_nice(struct cpufreq_policy *policy,
+static ssize_t store_ignore_nice_load(struct cpufreq_policy *policy,
 		const char *buf, size_t count)
 {
 	unsigned int input;
@@ -272,7 +272,7 @@ define_one_rw(sampling_rate);
 define_one_rw(sampling_down_factor);
 define_one_rw(up_threshold);
 define_one_rw(down_threshold);
-define_one_rw(ignore_nice);
+define_one_rw(ignore_nice_load);
 define_one_rw(freq_step);
 
 static struct attribute * dbs_attributes[] = {
@@ -282,7 +282,7 @@ static struct attribute * dbs_attributes[] = {
 	&sampling_down_factor.attr,
 	&up_threshold.attr,
 	&down_threshold.attr,
-	&ignore_nice.attr,
+	&ignore_nice_load.attr,
 	&freq_step.attr,
 	NULL
 };
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 17741111246b..e69fd8dd1f1c 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -89,7 +89,7 @@ static inline unsigned int get_cpu_idle_time(unsigned int cpu)
 {
 	return	kstat_cpu(cpu).cpustat.idle +
 		kstat_cpu(cpu).cpustat.iowait +
-		( !dbs_tuners_ins.ignore_nice ? 
+		( dbs_tuners_ins.ignore_nice ?
 		  kstat_cpu(cpu).cpustat.nice :
 		  0);
 }
@@ -122,7 +122,7 @@ static ssize_t show_##file_name						\
 show_one(sampling_rate, sampling_rate);
 show_one(sampling_down_factor, sampling_down_factor);
 show_one(up_threshold, up_threshold);
-show_one(ignore_nice, ignore_nice);
+show_one(ignore_nice_load, ignore_nice);
 
 static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused, 
 		const char *buf, size_t count)
@@ -182,7 +182,7 @@ static ssize_t store_up_threshold(struct cpufreq_policy *unused,
 	return count;
 }
 
-static ssize_t store_ignore_nice(struct cpufreq_policy *policy,
+static ssize_t store_ignore_nice_load(struct cpufreq_policy *policy,
 		const char *buf, size_t count)
 {
 	unsigned int input;
@@ -223,7 +223,7 @@ __ATTR(_name, 0644, show_##_name, store_##_name)
 define_one_rw(sampling_rate);
 define_one_rw(sampling_down_factor);
 define_one_rw(up_threshold);
-define_one_rw(ignore_nice);
+define_one_rw(ignore_nice_load);
 
 static struct attribute * dbs_attributes[] = {
 	&sampling_rate_max.attr,
@@ -231,7 +231,7 @@ static struct attribute * dbs_attributes[] = {
 	&sampling_rate.attr,
 	&sampling_down_factor.attr,
 	&up_threshold.attr,
-	&ignore_nice.attr,
+	&ignore_nice_load.attr,
 	NULL
 };
 
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index db358cfa7cbf..c58295914365 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -350,6 +350,18 @@ config SENSORS_VIA686A
 	  This driver can also be built as a module.  If so, the module
 	  will be called via686a.
 
+config SENSORS_VT8231
+	tristate "VT8231"
+	depends on HWMON && I2C && PCI && EXPERIMENTAL
+	select HWMON_VID
+	select I2C_ISA
+	help
+	  If you say yes here then you get support for the integrated sensors
+	  in the VIA VT8231 device.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called vt8231.
+
 config SENSORS_W83781D
 	tristate "Winbond W83781D, W83782D, W83783S, W83627HF, Asus AS99127F"
 	depends on HWMON && I2C
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index f7d6a2f61ee7..06d4a1d14105 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -40,6 +40,7 @@ obj-$(CONFIG_SENSORS_SIS5595)	+= sis5595.o
 obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o
 obj-$(CONFIG_SENSORS_SMSC47M1)	+= smsc47m1.o
 obj-$(CONFIG_SENSORS_VIA686A)	+= via686a.o
+obj-$(CONFIG_SENSORS_VT8231)	+= vt8231.o
 obj-$(CONFIG_SENSORS_W83627EHF)	+= w83627ehf.o
 obj-$(CONFIG_SENSORS_W83L785TS)	+= w83l785ts.o
 
diff --git a/drivers/hwmon/adm1021.c b/drivers/hwmon/adm1021.c
index 8102876c7c3f..665612729cb9 100644
--- a/drivers/hwmon/adm1021.c
+++ b/drivers/hwmon/adm1021.c
@@ -126,10 +126,10 @@ static int read_only;
 
 /* This is the driver that will be inserted */
 static struct i2c_driver adm1021_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "adm1021",
+	.driver = {
+		.name	= "adm1021",
+	},
 	.id		= I2C_DRIVERID_ADM1021,
-	.flags		= I2C_DF_NOTIFY,
 	.attach_adapter	= adm1021_attach_adapter,
 	.detach_client	= adm1021_detach_client,
 };
diff --git a/drivers/hwmon/adm1025.c b/drivers/hwmon/adm1025.c
index 3ec12421694f..9331c56d2ba6 100644
--- a/drivers/hwmon/adm1025.c
+++ b/drivers/hwmon/adm1025.c
@@ -118,10 +118,10 @@ static struct adm1025_data *adm1025_update_device(struct device *dev);
  */
 
 static struct i2c_driver adm1025_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "adm1025",
+	.driver = {
+		.name	= "adm1025",
+	},
 	.id		= I2C_DRIVERID_ADM1025,
-	.flags		= I2C_DF_NOTIFY,
 	.attach_adapter	= adm1025_attach_adapter,
 	.detach_client	= adm1025_detach_client,
 };
@@ -287,8 +287,6 @@ static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char
 	struct adm1025_data *data = adm1025_update_device(dev);
 	return sprintf(buf, "%u\n", vid_from_reg(data->vid, data->vrm));
 }
-/* in1_ref is deprecated in favour of cpu0_vid, remove after 2005-11-11 */
-static DEVICE_ATTR(in1_ref, S_IRUGO, show_vid, NULL);
 static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
 
 static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char *buf)
@@ -444,8 +442,6 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind)
 	device_create_file(&new_client->dev, &dev_attr_temp1_max);
 	device_create_file(&new_client->dev, &dev_attr_temp2_max);
 	device_create_file(&new_client->dev, &dev_attr_alarms);
-	/* in1_ref is deprecated, remove after 2005-11-11 */
-	device_create_file(&new_client->dev, &dev_attr_in1_ref);
 	device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
 	device_create_file(&new_client->dev, &dev_attr_vrm);
 
diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c
index e0f56549d1d8..fefe6e74fd02 100644
--- a/drivers/hwmon/adm1026.c
+++ b/drivers/hwmon/adm1026.c
@@ -308,9 +308,9 @@ static void adm1026_init_client(struct i2c_client *client);
 
 
 static struct i2c_driver adm1026_driver = {
-	.owner          = THIS_MODULE,
-	.name           = "adm1026",
-	.flags          = I2C_DF_NOTIFY,
+	.driver = {
+		.name	= "adm1026",
+	},
 	.attach_adapter = adm1026_attach_adapter,
 	.detach_client  = adm1026_detach_client,
 };
@@ -1227,8 +1227,6 @@ static ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr, c
 	struct adm1026_data *data = adm1026_update_device(dev);
 	return sprintf(buf,"%d\n", vid_from_reg(data->vid & 0x3f, data->vrm));
 }
-/* vid deprecated in favour of cpu0_vid, remove after 2005-11-11 */
-static DEVICE_ATTR(vid, S_IRUGO, show_vid_reg, NULL);
 static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
 
 static ssize_t show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf)
@@ -1673,8 +1671,6 @@ static int adm1026_detect(struct i2c_adapter *adapter, int address,
 	device_create_file(&new_client->dev, &dev_attr_temp1_crit_enable);
 	device_create_file(&new_client->dev, &dev_attr_temp2_crit_enable);
 	device_create_file(&new_client->dev, &dev_attr_temp3_crit_enable);
-	/* vid deprecated in favour of cpu0_vid, remove after 2005-11-11 */
-	device_create_file(&new_client->dev, &dev_attr_vid);
 	device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
 	device_create_file(&new_client->dev, &dev_attr_vrm);
 	device_create_file(&new_client->dev, &dev_attr_alarms);
diff --git a/drivers/hwmon/adm1031.c b/drivers/hwmon/adm1031.c
index 7c545d5eee45..d06397966081 100644
--- a/drivers/hwmon/adm1031.c
+++ b/drivers/hwmon/adm1031.c
@@ -105,9 +105,9 @@ static struct adm1031_data *adm1031_update_device(struct device *dev);
 
 /* This is the driver that will be inserted */
 static struct i2c_driver adm1031_driver = {
-	.owner = THIS_MODULE,
-	.name = "adm1031",
-	.flags = I2C_DF_NOTIFY,
+	.driver = {
+		.name = "adm1031",
+	},
 	.attach_adapter = adm1031_attach_adapter,
 	.detach_client = adm1031_detach_client,
 };
diff --git a/drivers/hwmon/adm9240.c b/drivers/hwmon/adm9240.c
index 11dc95f8a17e..5ddc22fea4a3 100644
--- a/drivers/hwmon/adm9240.c
+++ b/drivers/hwmon/adm9240.c
@@ -137,10 +137,10 @@ static struct adm9240_data *adm9240_update_device(struct device *dev);
 
 /* driver data */
 static struct i2c_driver adm9240_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "adm9240",
+	.driver = {
+		.name	= "adm9240",
+	},
 	.id		= I2C_DRIVERID_ADM9240,
-	.flags		= I2C_DF_NOTIFY,
 	.attach_adapter	= adm9240_attach_adapter,
 	.detach_client	= adm9240_detach_client,
 };
diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c
index 52c469722a65..ae9de63cf2e0 100644
--- a/drivers/hwmon/asb100.c
+++ b/drivers/hwmon/asb100.c
@@ -217,10 +217,10 @@ static struct asb100_data *asb100_update_device(struct device *dev);
 static void asb100_init_client(struct i2c_client *client);
 
 static struct i2c_driver asb100_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "asb100",
+	.driver = {
+		.name	= "asb100",
+	},
 	.id		= I2C_DRIVERID_ASB100,
-	.flags		= I2C_DF_NOTIFY,
 	.attach_adapter	= asb100_attach_adapter,
 	.detach_client	= asb100_detach_client,
 };
diff --git a/drivers/hwmon/atxp1.c b/drivers/hwmon/atxp1.c
index 53324f56404e..b0c490073c8e 100644
--- a/drivers/hwmon/atxp1.c
+++ b/drivers/hwmon/atxp1.c
@@ -50,9 +50,9 @@ static struct atxp1_data * atxp1_update_device(struct device *dev);
 static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind);
 
 static struct i2c_driver atxp1_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "atxp1",
-	.flags		= I2C_DF_NOTIFY,
+	.driver = {
+		.name	= "atxp1",
+	},
 	.attach_adapter = atxp1_attach_adapter,
 	.detach_client	= atxp1_detach_client,
 };
diff --git a/drivers/hwmon/ds1621.c b/drivers/hwmon/ds1621.c
index 34f71b7c7f37..203f9c7abb20 100644
--- a/drivers/hwmon/ds1621.c
+++ b/drivers/hwmon/ds1621.c
@@ -89,10 +89,10 @@ static struct ds1621_data *ds1621_update_client(struct device *dev);
 
 /* This is the driver that will be inserted */
 static struct i2c_driver ds1621_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "ds1621",
+	.driver = {
+		.name	= "ds1621",
+	},
 	.id		= I2C_DRIVERID_DS1621,
-	.flags		= I2C_DF_NOTIFY,
 	.attach_adapter	= ds1621_attach_adapter,
 	.detach_client	= ds1621_detach_client,
 };
diff --git a/drivers/hwmon/fscher.c b/drivers/hwmon/fscher.c
index a02e1c34c757..25409181d1eb 100644
--- a/drivers/hwmon/fscher.c
+++ b/drivers/hwmon/fscher.c
@@ -118,10 +118,10 @@ static int fscher_write_value(struct i2c_client *client, u8 reg, u8 value);
  */
  
 static struct i2c_driver fscher_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "fscher",
+	.driver = {
+		.name	= "fscher",
+	},
 	.id		= I2C_DRIVERID_FSCHER,
-	.flags		= I2C_DF_NOTIFY,
 	.attach_adapter	= fscher_attach_adapter,
 	.detach_client	= fscher_detach_client,
 };
diff --git a/drivers/hwmon/fscpos.c b/drivers/hwmon/fscpos.c
index 64e4edc64f8d..6d0146b57020 100644
--- a/drivers/hwmon/fscpos.c
+++ b/drivers/hwmon/fscpos.c
@@ -100,10 +100,10 @@ static void reset_fan_alarm(struct i2c_client *client, int nr);
  * Driver data (common to all clients)
  */
 static struct i2c_driver fscpos_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "fscpos",
+	.driver = {
+		.name	= "fscpos",
+	},
 	.id		= I2C_DRIVERID_FSCPOS,
-	.flags		= I2C_DF_NOTIFY,
 	.attach_adapter	= fscpos_attach_adapter,
 	.detach_client	= fscpos_detach_client,
 };
diff --git a/drivers/hwmon/gl518sm.c b/drivers/hwmon/gl518sm.c
index 2f178dbe3d87..9e685e3a3bc9 100644
--- a/drivers/hwmon/gl518sm.c
+++ b/drivers/hwmon/gl518sm.c
@@ -151,10 +151,10 @@ static struct gl518_data *gl518_update_device(struct device *dev);
 
 /* This is the driver that will be inserted */
 static struct i2c_driver gl518_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "gl518sm",
+	.driver = {
+		.name	= "gl518sm",
+	},
 	.id		= I2C_DRIVERID_GL518,
-	.flags		= I2C_DF_NOTIFY,
 	.attach_adapter	= gl518_attach_adapter,
 	.detach_client	= gl518_detach_client,
 };
diff --git a/drivers/hwmon/gl520sm.c b/drivers/hwmon/gl520sm.c
index c39ba1239426..baee60e44b52 100644
--- a/drivers/hwmon/gl520sm.c
+++ b/drivers/hwmon/gl520sm.c
@@ -109,10 +109,10 @@ static struct gl520_data *gl520_update_device(struct device *dev);
 
 /* Driver data */
 static struct i2c_driver gl520_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "gl520sm",
+	.driver = {
+		.name	= "gl520sm",
+	},
 	.id		= I2C_DRIVERID_GL520,
-	.flags		= I2C_DF_NOTIFY,
 	.attach_adapter	= gl520_attach_adapter,
 	.detach_client	= gl520_detach_client,
 };
diff --git a/drivers/hwmon/hwmon-vid.c b/drivers/hwmon/hwmon-vid.c
index 312769ad4dab..e497274916ce 100644
--- a/drivers/hwmon/hwmon-vid.c
+++ b/drivers/hwmon/hwmon-vid.c
@@ -49,20 +49,22 @@
         . . . .
        11110  =  0.800 V
        11111  =  0.000 V (off)
+
+    The 17 specification is in fact Intel Mobile Voltage Positioning -
+    (IMVP-II). You can find more information in the datasheet of Max1718
+    http://www.maxim-ic.com/quick_view2.cfm/qv_pk/2452
+
 */
 
 /* vrm is the VRM/VRD document version multiplied by 10.
    val is the 4-, 5- or 6-bit VID code.
    Returned value is in mV to avoid floating point in the kernel. */
-int vid_from_reg(int val, int vrm)
+int vid_from_reg(int val, u8 vrm)
 {
 	int vid;
 
 	switch(vrm) {
 
-	case  0:
-		return 0;
-
 	case 100:               /* VRD 10.0 */
 		if((val & 0x1f) == 0x1f)
 			return 0;
@@ -91,10 +93,16 @@ int vid_from_reg(int val, int vrm)
 	case 84:		/* VRM 8.4 */
 		val &= 0x0f;
 				/* fall through */
-	default:		/* VRM 8.2 */
+	case 82:		/* VRM 8.2 */
 		return(val == 0x1f ? 0 :
 		       val & 0x10  ? 5100 - (val) * 100 :
 		                     2050 - (val) * 50);
+	case 17:		/* Intel IMVP-II */
+		return(val & 0x10 ? 975 - (val & 0xF) * 25 :
+				    1750 - val * 50);
+	default:		/* report 0 for unknown */
+		printk(KERN_INFO "hwmon-vid: requested unknown VRM version\n");
+		return 0;
 	}
 }
 
@@ -108,30 +116,36 @@ struct vrm_model {
 	u8 vendor;
 	u8 eff_family;
 	u8 eff_model;
-	int vrm_type;
+	u8 eff_stepping;
+	u8 vrm_type;
 };
 
 #define ANY 0xFF
 
 #ifdef CONFIG_X86
 
+/* the stepping parameter is highest acceptable stepping for current line */
+
 static struct vrm_model vrm_models[] = {
-	{X86_VENDOR_AMD, 0x6, ANY, 90},		/* Athlon Duron etc */
-	{X86_VENDOR_AMD, 0xF, ANY, 24},		/* Athlon 64, Opteron */
-	{X86_VENDOR_INTEL, 0x6, 0x9, 85},	/* 0.13um too */
-	{X86_VENDOR_INTEL, 0x6, 0xB, 85},	/* Tualatin */
-	{X86_VENDOR_INTEL, 0x6, ANY, 82},	/* any P6 */
-	{X86_VENDOR_INTEL, 0x7, ANY, 0},	/* Itanium */
-	{X86_VENDOR_INTEL, 0xF, 0x0, 90},	/* P4 */
-	{X86_VENDOR_INTEL, 0xF, 0x1, 90},	/* P4 Willamette */
-	{X86_VENDOR_INTEL, 0xF, 0x2, 90},	/* P4 Northwood */
-	{X86_VENDOR_INTEL, 0xF, 0x3, 100},	/* P4 Prescott */
-	{X86_VENDOR_INTEL, 0xF, 0x4, 100},	/* P4 Prescott */
-	{X86_VENDOR_INTEL, 0x10,ANY, 0},	/* Itanium 2 */
-	{X86_VENDOR_UNKNOWN, ANY, ANY, 0}	/* stop here */
+	{X86_VENDOR_AMD, 0x6, ANY, ANY, 90},		/* Athlon Duron etc */
+	{X86_VENDOR_AMD, 0xF, ANY, ANY, 24},		/* Athlon 64, Opteron and above VRM 24 */
+	{X86_VENDOR_INTEL, 0x6, 0x9, ANY, 85},		/* 0.13um too */
+	{X86_VENDOR_INTEL, 0x6, 0xB, ANY, 85},		/* Tualatin */
+	{X86_VENDOR_INTEL, 0x6, ANY, ANY, 82},		/* any P6 */
+	{X86_VENDOR_INTEL, 0x7, ANY, ANY, 0},		/* Itanium */
+	{X86_VENDOR_INTEL, 0xF, 0x0, ANY, 90},		/* P4 */
+	{X86_VENDOR_INTEL, 0xF, 0x1, ANY, 90},		/* P4 Willamette */
+	{X86_VENDOR_INTEL, 0xF, 0x2, ANY, 90},		/* P4 Northwood */
+	{X86_VENDOR_INTEL, 0xF, ANY, ANY, 100},		/* Prescott and above assume VRD 10 */
+	{X86_VENDOR_INTEL, 0x10, ANY, ANY, 0},		/* Itanium 2 */
+	{X86_VENDOR_CENTAUR, 0x6, 0x7, ANY, 85},	/* Eden ESP/Ezra */
+	{X86_VENDOR_CENTAUR, 0x6, 0x8, 0x7, 85},	/* Ezra T */
+	{X86_VENDOR_CENTAUR, 0x6, 0x9, 0x7, 85},	/* Nemiah */
+	{X86_VENDOR_CENTAUR, 0x6, 0x9, ANY, 17},	/* C3-M */
+	{X86_VENDOR_UNKNOWN, ANY, ANY, ANY, 0}		/* stop here */
 };
 
-static int find_vrm(u8 eff_family, u8 eff_model, u8 vendor)
+static u8 find_vrm(u8 eff_family, u8 eff_model, u8 eff_stepping, u8 vendor)
 {
 	int i = 0;
 
@@ -139,7 +153,8 @@ static int find_vrm(u8 eff_family, u8 eff_model, u8 vendor)
 		if (vrm_models[i].vendor==vendor)
 			if ((vrm_models[i].eff_family==eff_family)
 			 && ((vrm_models[i].eff_model==eff_model) ||
-			     (vrm_models[i].eff_model==ANY)))
+			     (vrm_models[i].eff_model==ANY)) &&
+			     (eff_stepping <= vrm_models[i].eff_stepping))
 				return vrm_models[i].vrm_type;
 		i++;
 	}
@@ -147,12 +162,11 @@ static int find_vrm(u8 eff_family, u8 eff_model, u8 vendor)
 	return 0;
 }
 
-int vid_which_vrm(void)
+u8 vid_which_vrm(void)
 {
 	struct cpuinfo_x86 *c = cpu_data;
 	u32 eax;
-	u8 eff_family, eff_model;
-	int vrm_ret;
+	u8 eff_family, eff_model, eff_stepping, vrm_ret;
 
 	if (c->x86 < 6)		/* Any CPU with family lower than 6 */
 		return 0;	/* doesn't have VID and/or CPUID */
@@ -160,20 +174,21 @@ int vid_which_vrm(void)
 	eax = cpuid_eax(1);
 	eff_family = ((eax & 0x00000F00)>>8);
 	eff_model  = ((eax & 0x000000F0)>>4);
+	eff_stepping = eax & 0xF;
 	if (eff_family == 0xF) {	/* use extended model & family */
 		eff_family += ((eax & 0x00F00000)>>20);
 		eff_model += ((eax & 0x000F0000)>>16)<<4;
 	}
-	vrm_ret = find_vrm(eff_family,eff_model,c->x86_vendor);
+	vrm_ret = find_vrm(eff_family, eff_model, eff_stepping, c->x86_vendor);
 	if (vrm_ret == 0)
 		printk(KERN_INFO "hwmon-vid: Unknown VRM version of your "
 		       "x86 CPU\n");
 	return vrm_ret;
 }
 
-/* and now something completely different for the non-x86 world */
+/* and now for something completely different for the non-x86 world */
 #else
-int vid_which_vrm(void)
+u8 vid_which_vrm(void)
 {
 	printk(KERN_INFO "hwmon-vid: Unknown VRM version of your CPU\n");
 	return 0;
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index a61f5d00f10a..0da7c9c508c3 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -213,7 +213,7 @@ struct it87_data {
 	u8 sensor;		/* Register value */
 	u8 fan_div[3];		/* Register encoding, shifted right */
 	u8 vid;			/* Register encoding, combined */
-	int vrm;
+	u8 vrm;
 	u32 alarms;		/* Register encoding, combined */
 	u8 fan_main_ctrl;	/* Register value */
 	u8 manual_pwm_ctl[3];   /* manual PWM value set by user */
@@ -234,17 +234,18 @@ static void it87_init_client(struct i2c_client *client, struct it87_data *data);
 
 
 static struct i2c_driver it87_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "it87",
+	.driver = {
+		.name	= "it87",
+	},
 	.id		= I2C_DRIVERID_IT87,
-	.flags		= I2C_DF_NOTIFY,
 	.attach_adapter	= it87_attach_adapter,
 	.detach_client	= it87_detach_client,
 };
 
 static struct i2c_driver it87_isa_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "it87-isa",
+	.driver = {
+		.name	= "it87-isa",
+	},
 	.attach_adapter	= it87_isa_attach_adapter,
 	.detach_client	= it87_detach_client,
 };
@@ -668,7 +669,7 @@ static ssize_t
 show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct it87_data *data = it87_update_device(dev);
-	return sprintf(buf, "%ld\n", (long) data->vrm);
+	return sprintf(buf, "%u\n", data->vrm);
 }
 static ssize_t
 store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
@@ -761,7 +762,8 @@ static int it87_detect(struct i2c_adapter *adapter, int address, int kind)
 
 	/* Reserve the ISA region */
 	if (is_isa)
-		if (!request_region(address, IT87_EXTENT, it87_isa_driver.name))
+		if (!request_region(address, IT87_EXTENT,
+				    it87_isa_driver.driver.name))
 			goto ERROR0;
 
 	/* For now, we presume we have a valid client. We create the
diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c
index 954ec2497249..6b1aa7ef552e 100644
--- a/drivers/hwmon/lm63.c
+++ b/drivers/hwmon/lm63.c
@@ -139,9 +139,9 @@ static void lm63_init_client(struct i2c_client *client);
  */
 
 static struct i2c_driver lm63_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "lm63",
-	.flags		= I2C_DF_NOTIFY,
+	.driver = {
+		.name	= "lm63",
+	},
 	.attach_adapter	= lm63_attach_adapter,
 	.detach_client	= lm63_detach_client,
 };
diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
index d70f4c8fc1e6..74ca2c8c61c3 100644
--- a/drivers/hwmon/lm75.c
+++ b/drivers/hwmon/lm75.c
@@ -66,10 +66,10 @@ static struct lm75_data *lm75_update_device(struct device *dev);
 
 /* This is the driver that will be inserted */
 static struct i2c_driver lm75_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "lm75",
+	.driver = {
+		.name	= "lm75",
+	},
 	.id		= I2C_DRIVERID_LM75,
-	.flags		= I2C_DF_NOTIFY,
 	.attach_adapter	= lm75_attach_adapter,
 	.detach_client	= lm75_detach_client,
 };
diff --git a/drivers/hwmon/lm77.c b/drivers/hwmon/lm77.c
index 9380fda7dcd1..a2f420d01fb7 100644
--- a/drivers/hwmon/lm77.c
+++ b/drivers/hwmon/lm77.c
@@ -74,9 +74,9 @@ static struct lm77_data *lm77_update_device(struct device *dev);
 
 /* This is the driver that will be inserted */
 static struct i2c_driver lm77_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "lm77",
-	.flags		= I2C_DF_NOTIFY,
+	.driver = {
+		.name	= "lm77",
+	},
 	.attach_adapter = lm77_attach_adapter,
 	.detach_client	= lm77_detach_client,
 };
diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c
index 78cdd506439f..e404001e20da 100644
--- a/drivers/hwmon/lm78.c
+++ b/drivers/hwmon/lm78.c
@@ -164,17 +164,18 @@ static void lm78_init_client(struct i2c_client *client);
 
 
 static struct i2c_driver lm78_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "lm78",
+	.driver = {
+		.name	= "lm78",
+	},
 	.id		= I2C_DRIVERID_LM78,
-	.flags		= I2C_DF_NOTIFY,
 	.attach_adapter	= lm78_attach_adapter,
 	.detach_client	= lm78_detach_client,
 };
 
 static struct i2c_driver lm78_isa_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "lm78-isa",
+	.driver = {
+		.name	= "lm78-isa",
+	},
 	.attach_adapter	= lm78_isa_attach_adapter,
 	.detach_client	= lm78_detach_client,
 };
@@ -497,7 +498,7 @@ static int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
 	/* Reserve the ISA region */
 	if (is_isa)
 		if (!request_region(address, LM78_EXTENT,
-				    lm78_isa_driver.name)) {
+				    lm78_isa_driver.driver.name)) {
 			err = -EBUSY;
 			goto ERROR0;
 		}
diff --git a/drivers/hwmon/lm80.c b/drivers/hwmon/lm80.c
index c359fdea211e..c9a7cdea7bd7 100644
--- a/drivers/hwmon/lm80.c
+++ b/drivers/hwmon/lm80.c
@@ -143,10 +143,10 @@ static int lm80_write_value(struct i2c_client *client, u8 reg, u8 value);
  */
 
 static struct i2c_driver lm80_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "lm80",
+	.driver = {
+		.name	= "lm80",
+	},
 	.id		= I2C_DRIVERID_LM80,
-	.flags		= I2C_DF_NOTIFY,
 	.attach_adapter	= lm80_attach_adapter,
 	.detach_client	= lm80_detach_client,
 };
diff --git a/drivers/hwmon/lm83.c b/drivers/hwmon/lm83.c
index 9a70611a9f69..26dfa9e216c2 100644
--- a/drivers/hwmon/lm83.c
+++ b/drivers/hwmon/lm83.c
@@ -124,10 +124,10 @@ static struct lm83_data *lm83_update_device(struct device *dev);
  */
  
 static struct i2c_driver lm83_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "lm83",
+	.driver = {
+		.name	= "lm83",
+	},
 	.id		= I2C_DRIVERID_LM83,
-	.flags		= I2C_DF_NOTIFY,
 	.attach_adapter	= lm83_attach_adapter,
 	.detach_client	= lm83_detach_client,
 };
diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c
index d1070ed2bee6..7389a0127547 100644
--- a/drivers/hwmon/lm85.c
+++ b/drivers/hwmon/lm85.c
@@ -380,10 +380,10 @@ static void lm85_init_client(struct i2c_client *client);
 
 
 static struct i2c_driver lm85_driver = {
-	.owner          = THIS_MODULE,
-	.name           = "lm85",
+	.driver = {
+		.name   = "lm85",
+	},
 	.id             = I2C_DRIVERID_LM85,
-	.flags          = I2C_DF_NOTIFY,
 	.attach_adapter = lm85_attach_adapter,
 	.detach_client  = lm85_detach_client,
 };
@@ -443,7 +443,17 @@ show_fan_offset(4);
 static ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct lm85_data *data = lm85_update_device(dev);
-	return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
+	int vid;
+
+	if (data->type == adt7463 && (data->vid & 0x80)) {
+		/* 6-pin VID (VRM 10) */
+		vid = vid_from_reg(data->vid & 0x3f, data->vrm);
+	} else {
+		/* 5-pin VID (VRM 9) */
+		vid = vid_from_reg(data->vid & 0x1f, data->vrm);
+	}
+
+	return sprintf(buf, "%d\n", vid);
 }
 
 static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
@@ -1176,17 +1186,14 @@ static int lm85_detect(struct i2c_adapter *adapter, int address,
 	device_create_file(&new_client->dev, &dev_attr_in1_input);
 	device_create_file(&new_client->dev, &dev_attr_in2_input);
 	device_create_file(&new_client->dev, &dev_attr_in3_input);
-	device_create_file(&new_client->dev, &dev_attr_in4_input);
 	device_create_file(&new_client->dev, &dev_attr_in0_min);
 	device_create_file(&new_client->dev, &dev_attr_in1_min);
 	device_create_file(&new_client->dev, &dev_attr_in2_min);
 	device_create_file(&new_client->dev, &dev_attr_in3_min);
-	device_create_file(&new_client->dev, &dev_attr_in4_min);
 	device_create_file(&new_client->dev, &dev_attr_in0_max);
 	device_create_file(&new_client->dev, &dev_attr_in1_max);
 	device_create_file(&new_client->dev, &dev_attr_in2_max);
 	device_create_file(&new_client->dev, &dev_attr_in3_max);
-	device_create_file(&new_client->dev, &dev_attr_in4_max);
 	device_create_file(&new_client->dev, &dev_attr_temp1_input);
 	device_create_file(&new_client->dev, &dev_attr_temp2_input);
 	device_create_file(&new_client->dev, &dev_attr_temp3_input);
@@ -1224,6 +1231,15 @@ static int lm85_detect(struct i2c_adapter *adapter, int address,
 	device_create_file(&new_client->dev, &dev_attr_temp2_auto_temp_crit);
 	device_create_file(&new_client->dev, &dev_attr_temp3_auto_temp_crit);
 
+	/* The ADT7463 has an optional VRM 10 mode where pin 21 is used
+	   as a sixth digital VID input rather than an analog input. */
+	data->vid = lm85_read_value(new_client, LM85_REG_VID);
+	if (!(kind == adt7463 && (data->vid & 0x80))) {
+		device_create_file(&new_client->dev, &dev_attr_in4_input);
+		device_create_file(&new_client->dev, &dev_attr_in4_min);
+		device_create_file(&new_client->dev, &dev_attr_in4_max);
+	}
+
 	return 0;
 
 	/* Error out and cleanup code */
@@ -1382,11 +1398,18 @@ static struct lm85_data *lm85_update_device(struct device *dev)
 		   irrelevant. So it is left in 4*/
 		data->adc_scale = (data->type == emc6d102 ) ? 16 : 4;
 
-		for (i = 0; i <= 4; ++i) {
+		data->vid = lm85_read_value(client, LM85_REG_VID);
+
+		for (i = 0; i <= 3; ++i) {
 			data->in[i] =
 			    lm85_read_value(client, LM85_REG_IN(i));
 		}
 
+		if (!(data->type == adt7463 && (data->vid & 0x80))) {
+			data->in[4] = lm85_read_value(client,
+				      LM85_REG_IN(4));
+		}
+
 		for (i = 0; i <= 3; ++i) {
 			data->fan[i] =
 			    lm85_read_value(client, LM85_REG_FAN(i));
@@ -1450,13 +1473,20 @@ static struct lm85_data *lm85_update_device(struct device *dev)
 		/* Things that don't change often */
 		dev_dbg(&client->dev, "Reading config values\n");
 
-		for (i = 0; i <= 4; ++i) {
+		for (i = 0; i <= 3; ++i) {
 			data->in_min[i] =
 			    lm85_read_value(client, LM85_REG_IN_MIN(i));
 			data->in_max[i] =
 			    lm85_read_value(client, LM85_REG_IN_MAX(i));
 		}
 
+		if (!(data->type == adt7463 && (data->vid & 0x80))) {
+			data->in_min[4] = lm85_read_value(client,
+					  LM85_REG_IN_MIN(4));
+			data->in_max[4] = lm85_read_value(client,
+					  LM85_REG_IN_MAX(4));
+		}
+
 		if ( data->type == emc6d100 ) {
 			for (i = 5; i <= 7; ++i) {
 				data->in_min[i] =
@@ -1478,8 +1508,6 @@ static struct lm85_data *lm85_update_device(struct device *dev)
 			    lm85_read_value(client, LM85_REG_TEMP_MAX(i));
 		}
 
-		data->vid = lm85_read_value(client, LM85_REG_VID);
-
 		for (i = 0; i <= 2; ++i) {
 			int val ;
 			data->autofan[i].config =
diff --git a/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c
index eeec18177861..6ba34c302d8d 100644
--- a/drivers/hwmon/lm87.c
+++ b/drivers/hwmon/lm87.c
@@ -161,10 +161,10 @@ static struct lm87_data *lm87_update_device(struct device *dev);
  */
 
 static struct i2c_driver lm87_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "lm87",
+	.driver = {
+		.name	= "lm87",
+	},
 	.id		= I2C_DRIVERID_LM87,
-	.flags		= I2C_DF_NOTIFY,
 	.attach_adapter	= lm87_attach_adapter,
 	.detach_client	= lm87_detach_client,
 };
diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c
index 83cf2e1b09f5..5679464447cc 100644
--- a/drivers/hwmon/lm90.c
+++ b/drivers/hwmon/lm90.c
@@ -186,10 +186,10 @@ static struct lm90_data *lm90_update_device(struct device *dev);
  */
 
 static struct i2c_driver lm90_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "lm90",
+	.driver = {
+		.name	= "lm90",
+	},
 	.id		= I2C_DRIVERID_LM90,
-	.flags		= I2C_DF_NOTIFY,
 	.attach_adapter	= lm90_attach_adapter,
 	.detach_client	= lm90_detach_client,
 };
diff --git a/drivers/hwmon/lm92.c b/drivers/hwmon/lm92.c
index 7a4b3701ed1a..b0c4cb730a7e 100644
--- a/drivers/hwmon/lm92.c
+++ b/drivers/hwmon/lm92.c
@@ -410,10 +410,10 @@ static int lm92_detach_client(struct i2c_client *client)
  */
 
 static struct i2c_driver lm92_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "lm92",
+	.driver = {
+		.name	= "lm92",
+	},
 	.id		= I2C_DRIVERID_LM92,
-	.flags		= I2C_DF_NOTIFY,
 	.attach_adapter	= lm92_attach_adapter,
 	.detach_client	= lm92_detach_client,
 };
diff --git a/drivers/hwmon/max1619.c b/drivers/hwmon/max1619.c
index 69e7e125683b..3abe330b22ce 100644
--- a/drivers/hwmon/max1619.c
+++ b/drivers/hwmon/max1619.c
@@ -90,9 +90,9 @@ static struct max1619_data *max1619_update_device(struct device *dev);
  */
 
 static struct i2c_driver max1619_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "max1619",
-	.flags		= I2C_DF_NOTIFY,
+	.driver = {
+		.name	= "max1619",
+	},
 	.attach_adapter	= max1619_attach_adapter,
 	.detach_client	= max1619_detach_client,
 };
diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c
index 17f745a23d04..f161e88e3bb6 100644
--- a/drivers/hwmon/pc87360.c
+++ b/drivers/hwmon/pc87360.c
@@ -236,8 +236,9 @@ static struct pc87360_data *pc87360_update_device(struct device *dev);
  */
 
 static struct i2c_driver pc87360_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "pc87360",
+	.driver = {
+		.name	= "pc87360",
+	},
 	.attach_adapter	= pc87360_detect,
 	.detach_client	= pc87360_detach_client,
 };
@@ -798,7 +799,7 @@ static int pc87360_detect(struct i2c_adapter *adapter)
 	for (i = 0; i < 3; i++) {
 		if (((data->address[i] = extra_isa[i]))
 		 && !request_region(extra_isa[i], PC87360_EXTENT,
-		 		    pc87360_driver.name)) {
+		 		    pc87360_driver.driver.name)) {
 			dev_err(&new_client->dev, "Region 0x%x-0x%x already "
 				"in use!\n", extra_isa[i],
 				extra_isa[i]+PC87360_EXTENT-1);
diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c
index 9c6cadec1087..8be5189d9bd9 100644
--- a/drivers/hwmon/sis5595.c
+++ b/drivers/hwmon/sis5595.c
@@ -198,8 +198,9 @@ static struct sis5595_data *sis5595_update_device(struct device *dev);
 static void sis5595_init_client(struct i2c_client *client);
 
 static struct i2c_driver sis5595_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "sis5595",
+	.driver = {
+		.name	= "sis5595",
+	},
 	.attach_adapter	= sis5595_detect,
 	.detach_client	= sis5595_detach_client,
 };
@@ -484,7 +485,8 @@ static int sis5595_detect(struct i2c_adapter *adapter)
 	if (force_addr)
 		address = force_addr & ~(SIS5595_EXTENT - 1);
 	/* Reserve the ISA region */
-	if (!request_region(address, SIS5595_EXTENT, sis5595_driver.name)) {
+	if (!request_region(address, SIS5595_EXTENT,
+			    sis5595_driver.driver.name)) {
 		err = -EBUSY;
 		goto exit;
 	}
diff --git a/drivers/hwmon/smsc47b397.c b/drivers/hwmon/smsc47b397.c
index 2a3e21b5b6b4..8663bbbe97f5 100644
--- a/drivers/hwmon/smsc47b397.c
+++ b/drivers/hwmon/smsc47b397.c
@@ -226,8 +226,9 @@ static int smsc47b397_detach_client(struct i2c_client *client)
 static int smsc47b397_detect(struct i2c_adapter *adapter);
 
 static struct i2c_driver smsc47b397_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "smsc47b397",
+	.driver = {
+		.name	= "smsc47b397",
+	},
 	.attach_adapter	= smsc47b397_detect,
 	.detach_client	= smsc47b397_detach_client,
 };
@@ -238,7 +239,8 @@ static int smsc47b397_detect(struct i2c_adapter *adapter)
 	struct smsc47b397_data *data;
 	int err = 0;
 
-	if (!request_region(address, SMSC_EXTENT, smsc47b397_driver.name)) {
+	if (!request_region(address, SMSC_EXTENT,
+			    smsc47b397_driver.driver.name)) {
 		dev_err(&adapter->dev, "Region 0x%x already in use!\n",
 			address);
 		return -EBUSY;
diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c
index 5905c1af88f2..d1e3ec0fe4df 100644
--- a/drivers/hwmon/smsc47m1.c
+++ b/drivers/hwmon/smsc47m1.c
@@ -126,8 +126,9 @@ static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
 
 
 static struct i2c_driver smsc47m1_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "smsc47m1",
+	.driver = {
+		.name	= "smsc47m1",
+	},
 	.attach_adapter	= smsc47m1_detect,
 	.detach_client	= smsc47m1_detach_client,
 };
@@ -394,7 +395,7 @@ static int smsc47m1_detect(struct i2c_adapter *adapter)
 	int err = 0;
 	int fan1, fan2, pwm1, pwm2;
 
-	if (!request_region(address, SMSC_EXTENT, smsc47m1_driver.name)) {
+	if (!request_region(address, SMSC_EXTENT, smsc47m1_driver.driver.name)) {
 		dev_err(&adapter->dev, "Region 0x%x already in use!\n", address);
 		return -EBUSY;
 	}
diff --git a/drivers/hwmon/via686a.c b/drivers/hwmon/via686a.c
index 6f696f897176..cb01848729b5 100644
--- a/drivers/hwmon/via686a.c
+++ b/drivers/hwmon/via686a.c
@@ -572,8 +572,9 @@ static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 /* The driver. I choose to use type i2c_driver, as at is identical to both
    smbus_driver and isa_driver, and clients could be of either kind */
 static struct i2c_driver via686a_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "via686a",
+	.driver = {
+		.name	= "via686a",
+	},
 	.attach_adapter	= via686a_detect,
 	.detach_client	= via686a_detach_client,
 };
@@ -615,7 +616,8 @@ static int via686a_detect(struct i2c_adapter *adapter)
 	}
 
 	/* Reserve the ISA region */
-	if (!request_region(address, VIA686A_EXTENT, via686a_driver.name)) {
+	if (!request_region(address, VIA686A_EXTENT,
+			    via686a_driver.driver.name)) {
 		dev_err(&adapter->dev, "region 0x%x already in use!\n",
 			address);
 		return -ENODEV;
diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c
new file mode 100644
index 000000000000..d00a726d0239
--- /dev/null
+++ b/drivers/hwmon/vt8231.c
@@ -0,0 +1,862 @@
+/*
+	vt8231.c - Part of lm_sensors, Linux kernel modules
+				for hardware monitoring
+
+	Copyright (c) 2005 Roger Lucas <roger@planbit.co.uk>
+	Copyright (c) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
+			   Aaron M. Marsh <amarsh@sdf.lonestar.org>
+
+	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.
+*/
+
+/* Supports VIA VT8231 South Bridge embedded sensors
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/jiffies.h>
+#include <linux/i2c.h>
+#include <linux/i2c-isa.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
+#include <asm/io.h>
+
+static int force_addr;
+module_param(force_addr, int, 0);
+MODULE_PARM_DESC(force_addr, "Initialize the base address of the sensors");
+
+/* Device address
+   Note that we can't determine the ISA address until we have initialized
+   our module */
+static unsigned short isa_address;
+
+#define VT8231_EXTENT 0x80
+#define VT8231_BASE_REG 0x70
+#define VT8231_ENABLE_REG 0x74
+
+/* The VT8231 registers
+
+   The reset value for the input channel configuration is used (Reg 0x4A=0x07)
+   which sets the selected inputs marked with '*' below if multiple options are
+   possible:
+
+	            Voltage Mode	  Temperature Mode
+	Sensor	      Linux Id	      Linux Id        VIA Id
+	--------      --------	      --------        ------
+	CPU Diode	N/A		temp1		0
+	UIC1		in0		temp2 *		1
+	UIC2		in1 *		temp3   	2
+	UIC3		in2 *		temp4		3
+	UIC4		in3 *		temp5		4
+	UIC5		in4 *		temp6		5
+	3.3V		in5		N/A
+
+   Note that the BIOS may set the configuration register to a different value
+   to match the motherboard configuration.
+*/
+
+/* fans numbered 0-1 */
+#define VT8231_REG_FAN_MIN(nr)	(0x3b + (nr))
+#define VT8231_REG_FAN(nr)	(0x29 + (nr))
+
+/* Voltage inputs numbered 0-5 */
+
+static const u8 regvolt[]    = { 0x21, 0x22, 0x23, 0x24, 0x25, 0x26 };
+static const u8 regvoltmax[] = { 0x3d, 0x2b, 0x2d, 0x2f, 0x31, 0x33 };
+static const u8 regvoltmin[] = { 0x3e, 0x2c, 0x2e, 0x30, 0x32, 0x34 };
+
+/* Temperatures are numbered 1-6 according to the Linux kernel specification.
+**
+** In the VIA datasheet, however, the temperatures are numbered from zero.
+** Since it is important that this driver can easily be compared to the VIA
+** datasheet, we will use the VIA numbering within this driver and map the
+** kernel sysfs device name to the VIA number in the sysfs callback.
+*/
+
+#define VT8231_REG_TEMP_LOW01	0x49
+#define VT8231_REG_TEMP_LOW25	0x4d
+
+static const u8 regtemp[]    = { 0x1f, 0x21, 0x22, 0x23, 0x24, 0x25 };
+static const u8 regtempmax[] = { 0x39, 0x3d, 0x2b, 0x2d, 0x2f, 0x31 };
+static const u8 regtempmin[] = { 0x3a, 0x3e, 0x2c, 0x2e, 0x30, 0x32 };
+
+#define TEMP_FROM_REG(reg)		(((253 * 4 - (reg)) * 550 + 105) / 210)
+#define TEMP_MAXMIN_FROM_REG(reg)	(((253 - (reg)) * 2200 + 105) / 210)
+#define TEMP_MAXMIN_TO_REG(val)		(253 - ((val) * 210 + 1100) / 2200)
+
+#define VT8231_REG_CONFIG 0x40
+#define VT8231_REG_ALARM1 0x41
+#define VT8231_REG_ALARM2 0x42
+#define VT8231_REG_FANDIV 0x47
+#define VT8231_REG_UCH_CONFIG 0x4a
+#define VT8231_REG_TEMP1_CONFIG 0x4b
+#define VT8231_REG_TEMP2_CONFIG 0x4c
+
+/* temps 0-5 as numbered in VIA datasheet - see later for mapping to Linux
+** numbering
+*/
+#define ISTEMP(i, ch_config) ((i) == 0 ? 1 : \
+			      ((ch_config) >> ((i)+1)) & 0x01)
+/* voltages 0-5 */
+#define ISVOLT(i, ch_config) ((i) == 5 ? 1 : \
+			      !(((ch_config) >> ((i)+2)) & 0x01))
+
+#define DIV_FROM_REG(val) (1 << (val))
+
+/* NB  The values returned here are NOT temperatures.  The calibration curves
+**     for the thermistor curves are board-specific and must go in the
+**     sensors.conf file.  Temperature sensors are actually ten bits, but the
+**     VIA datasheet only considers the 8 MSBs obtained from the regtemp[]
+**     register.  The temperature value returned should have a magnitude of 3,
+**     so we use the VIA scaling as the "true" scaling and use the remaining 2
+**     LSBs as fractional precision.
+**
+**     All the on-chip hardware temperature comparisons for the alarms are only
+**     8-bits wide, and compare against the 8 MSBs of the temperature.  The bits
+**     in the registers VT8231_REG_TEMP_LOW01 and VT8231_REG_TEMP_LOW25 are
+**     ignored.
+*/
+
+/******** FAN RPM CONVERSIONS ********
+** This chip saturates back at 0, not at 255 like many the other chips.
+** So, 0 means 0 RPM
+*/
+static inline u8 FAN_TO_REG(long rpm, int div)
+{
+	if (rpm == 0)
+		return 0;
+	return SENSORS_LIMIT(1310720 / (rpm * div), 1, 255);
+}
+
+#define FAN_FROM_REG(val, div) ((val) == 0 ? 0 : 1310720 / ((val) * (div)))
+
+struct vt8231_data {
+	struct i2c_client client;
+	struct semaphore update_lock;
+	struct class_device *class_dev;
+	char valid;		/* !=0 if following fields are valid */
+	unsigned long last_updated;	/* In jiffies */
+
+	u8 in[6];		/* Register value */
+	u8 in_max[6];		/* Register value */
+	u8 in_min[6];		/* Register value */
+	u16 temp[6];		/* Register value 10 bit, right aligned */
+	u8 temp_max[6];		/* Register value */
+	u8 temp_min[6];		/* Register value */
+	u8 fan[2];		/* Register value */
+	u8 fan_min[2];		/* Register value */
+	u8 fan_div[2];		/* Register encoding, shifted right */
+	u16 alarms;		/* Register encoding */
+	u8 uch_config;
+};
+
+static struct pci_dev *s_bridge;
+static int vt8231_detect(struct i2c_adapter *adapter);
+static int vt8231_detach_client(struct i2c_client *client);
+static struct vt8231_data *vt8231_update_device(struct device *dev);
+static void vt8231_init_client(struct i2c_client *client);
+
+static inline int vt8231_read_value(struct i2c_client *client, u8 reg)
+{
+	return inb_p(client->addr + reg);
+}
+
+static inline void vt8231_write_value(struct i2c_client *client, u8 reg,
+					u8 value)
+{
+	outb_p(value, client->addr + reg);
+}
+
+/* following are the sysfs callback functions */
+static ssize_t show_in(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	struct vt8231_data *data = vt8231_update_device(dev);
+
+	return sprintf(buf, "%d\n", ((data->in[nr] - 3) * 10000) / 958);
+}
+
+static ssize_t show_in_min(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	struct vt8231_data *data = vt8231_update_device(dev);
+
+	return sprintf(buf, "%d\n", ((data->in_min[nr] - 3) * 10000) / 958);
+}
+
+static ssize_t show_in_max(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	struct vt8231_data *data = vt8231_update_device(dev);
+
+	return sprintf(buf, "%d\n", (((data->in_max[nr] - 3) * 10000) / 958));
+}
+
+static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct vt8231_data *data = i2c_get_clientdata(client);
+	unsigned long val = simple_strtoul(buf, NULL, 10);
+
+	down(&data->update_lock);
+	data->in_min[nr] = SENSORS_LIMIT(((val * 958) / 10000) + 3, 0, 255);
+	vt8231_write_value(client, regvoltmin[nr], data->in_min[nr]);
+	up(&data->update_lock);
+	return count;
+}
+
+static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct vt8231_data *data = i2c_get_clientdata(client);
+	unsigned long val = simple_strtoul(buf, NULL, 10);
+
+	down(&data->update_lock);
+	data->in_max[nr] = SENSORS_LIMIT(((val * 958) / 10000) + 3, 0, 255);
+	vt8231_write_value(client, regvoltmax[nr], data->in_max[nr]);
+	up(&data->update_lock);
+	return count;
+}
+
+/* Special case for input 5 as this has 3.3V scaling built into the chip */
+static ssize_t show_in5(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct vt8231_data *data = vt8231_update_device(dev);
+
+	return sprintf(buf, "%d\n",
+		(((data->in[5] - 3) * 10000 * 54) / (958 * 34)));
+}
+
+static ssize_t show_in5_min(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct vt8231_data *data = vt8231_update_device(dev);
+
+	return sprintf(buf, "%d\n",
+		(((data->in_min[5] - 3) * 10000 * 54) / (958 * 34)));
+}
+
+static ssize_t show_in5_max(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct vt8231_data *data = vt8231_update_device(dev);
+
+	return sprintf(buf, "%d\n",
+		(((data->in_max[5] - 3) * 10000 * 54) / (958 * 34)));
+}
+
+static ssize_t set_in5_min(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct vt8231_data *data = i2c_get_clientdata(client);
+	unsigned long val = simple_strtoul(buf, NULL, 10);
+
+	down(&data->update_lock);
+	data->in_min[5] = SENSORS_LIMIT(((val * 958 * 34) / (10000 * 54)) + 3,
+					0, 255);
+	vt8231_write_value(client, regvoltmin[5], data->in_min[5]);
+	up(&data->update_lock);
+	return count;
+}
+
+static ssize_t set_in5_max(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct vt8231_data *data = i2c_get_clientdata(client);
+	unsigned long val = simple_strtoul(buf, NULL, 10);
+
+	down(&data->update_lock);
+	data->in_max[5] = SENSORS_LIMIT(((val * 958 * 34) / (10000 * 54)) + 3,
+					0, 255);
+	vt8231_write_value(client, regvoltmax[5], data->in_max[5]);
+	up(&data->update_lock);
+	return count;
+}
+
+#define define_voltage_sysfs(offset)				\
+static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO,		\
+		show_in, NULL, offset);				\
+static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR,	\
+		show_in_min, set_in_min, offset);		\
+static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR,	\
+		show_in_max, set_in_max, offset)
+
+define_voltage_sysfs(0);
+define_voltage_sysfs(1);
+define_voltage_sysfs(2);
+define_voltage_sysfs(3);
+define_voltage_sysfs(4);
+
+static DEVICE_ATTR(in5_input, S_IRUGO, show_in5, NULL);
+static DEVICE_ATTR(in5_min, S_IRUGO | S_IWUSR, show_in5_min, set_in5_min);
+static DEVICE_ATTR(in5_max, S_IRUGO | S_IWUSR, show_in5_max, set_in5_max);
+
+/* Temperatures */
+static ssize_t show_temp0(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct vt8231_data *data = vt8231_update_device(dev);
+	return sprintf(buf, "%d\n", data->temp[0] * 250);
+}
+
+static ssize_t show_temp0_max(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct vt8231_data *data = vt8231_update_device(dev);
+	return sprintf(buf, "%d\n", data->temp_max[0] * 1000);
+}
+
+static ssize_t show_temp0_min(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct vt8231_data *data = vt8231_update_device(dev);
+	return sprintf(buf, "%d\n", data->temp_min[0] * 1000);
+}
+
+static ssize_t set_temp0_max(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct vt8231_data *data = i2c_get_clientdata(client);
+	int val = simple_strtol(buf, NULL, 10);
+
+	down(&data->update_lock);
+	data->temp_max[0] = SENSORS_LIMIT((val + 500) / 1000, 0, 255);
+	vt8231_write_value(client, regtempmax[0], data->temp_max[0]);
+	up(&data->update_lock);
+	return count;
+}
+static ssize_t set_temp0_min(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct vt8231_data *data = i2c_get_clientdata(client);
+	int val = simple_strtol(buf, NULL, 10);
+
+	down(&data->update_lock);
+	data->temp_min[0] = SENSORS_LIMIT((val + 500) / 1000, 0, 255);
+	vt8231_write_value(client, regtempmin[0], data->temp_min[0]);
+	up(&data->update_lock);
+	return count;
+}
+
+static ssize_t show_temp(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	struct vt8231_data *data = vt8231_update_device(dev);
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr]));
+}
+
+static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	struct vt8231_data *data = vt8231_update_device(dev);
+	return sprintf(buf, "%d\n", TEMP_MAXMIN_FROM_REG(data->temp_max[nr]));
+}
+
+static ssize_t show_temp_min(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	struct vt8231_data *data = vt8231_update_device(dev);
+	return sprintf(buf, "%d\n", TEMP_MAXMIN_FROM_REG(data->temp_min[nr]));
+}
+
+static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct vt8231_data *data = i2c_get_clientdata(client);
+	int val = simple_strtol(buf, NULL, 10);
+
+	down(&data->update_lock);
+	data->temp_max[nr] = SENSORS_LIMIT(TEMP_MAXMIN_TO_REG(val), 0, 255);
+	vt8231_write_value(client, regtempmax[nr], data->temp_max[nr]);
+	up(&data->update_lock);
+	return count;
+}
+static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct vt8231_data *data = i2c_get_clientdata(client);
+	int val = simple_strtol(buf, NULL, 10);
+
+	down(&data->update_lock);
+	data->temp_min[nr] = SENSORS_LIMIT(TEMP_MAXMIN_TO_REG(val), 0, 255);
+	vt8231_write_value(client, regtempmin[nr], data->temp_min[nr]);
+	up(&data->update_lock);
+	return count;
+}
+
+/* Note that these map the Linux temperature sensor numbering (1-6) to the VIA
+** temperature sensor numbering (0-5)
+*/
+#define define_temperature_sysfs(offset)				\
+static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO,		\
+		show_temp, NULL, offset - 1);				\
+static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR,	\
+		show_temp_max, set_temp_max, offset - 1);		\
+static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR,	\
+		show_temp_min, set_temp_min, offset - 1)
+
+static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp0, NULL);
+static DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, show_temp0_max, set_temp0_max);
+static DEVICE_ATTR(temp1_min, S_IRUGO | S_IWUSR, show_temp0_min, set_temp0_min);
+
+define_temperature_sysfs(2);
+define_temperature_sysfs(3);
+define_temperature_sysfs(4);
+define_temperature_sysfs(5);
+define_temperature_sysfs(6);
+
+#define CFG_INFO_TEMP(id)	{ &sensor_dev_attr_temp##id##_input.dev_attr, \
+				&sensor_dev_attr_temp##id##_min.dev_attr, \
+				&sensor_dev_attr_temp##id##_max.dev_attr }
+#define CFG_INFO_VOLT(id)	{ &sensor_dev_attr_in##id##_input.dev_attr, \
+				&sensor_dev_attr_in##id##_min.dev_attr, \
+				&sensor_dev_attr_in##id##_max.dev_attr }
+
+struct str_device_attr_table {
+	struct device_attribute *input;
+	struct device_attribute *min;
+	struct device_attribute *max;
+};
+
+static struct str_device_attr_table cfg_info_temp[] = {
+	{ &dev_attr_temp1_input, &dev_attr_temp1_min, &dev_attr_temp1_max },
+	CFG_INFO_TEMP(2),
+	CFG_INFO_TEMP(3),
+	CFG_INFO_TEMP(4),
+	CFG_INFO_TEMP(5),
+	CFG_INFO_TEMP(6)
+};
+
+static struct str_device_attr_table cfg_info_volt[] = {
+	CFG_INFO_VOLT(0),
+	CFG_INFO_VOLT(1),
+	CFG_INFO_VOLT(2),
+	CFG_INFO_VOLT(3),
+	CFG_INFO_VOLT(4),
+	{ &dev_attr_in5_input, &dev_attr_in5_min, &dev_attr_in5_max }
+};
+
+/* Fans */
+static ssize_t show_fan(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	struct vt8231_data *data = vt8231_update_device(dev);
+	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr],
+				DIV_FROM_REG(data->fan_div[nr])));
+}
+
+static ssize_t show_fan_min(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	struct vt8231_data *data = vt8231_update_device(dev);
+	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr],
+			DIV_FROM_REG(data->fan_div[nr])));
+}
+
+static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	struct vt8231_data *data = vt8231_update_device(dev);
+	return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]));
+}
+
+static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct vt8231_data *data = i2c_get_clientdata(client);
+	int val = simple_strtoul(buf, NULL, 10);
+
+	down(&data->update_lock);
+	data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
+	vt8231_write_value(client, VT8231_REG_FAN_MIN(nr), data->fan_min[nr]);
+	up(&data->update_lock);
+	return count;
+}
+
+static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct vt8231_data *data = i2c_get_clientdata(client);
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	unsigned long val = simple_strtoul(buf, NULL, 10);
+	int nr = sensor_attr->index;
+	int old = vt8231_read_value(client, VT8231_REG_FANDIV);
+	long min = FAN_FROM_REG(data->fan_min[nr],
+				 DIV_FROM_REG(data->fan_div[nr]));
+
+	down(&data->update_lock);
+	switch (val) {
+	case 1: data->fan_div[nr] = 0; break;
+	case 2: data->fan_div[nr] = 1; break;
+	case 4: data->fan_div[nr] = 2; break;
+	case 8: data->fan_div[nr] = 3; break;
+	default:
+		dev_err(&client->dev, "fan_div value %ld not supported."
+		        "Choose one of 1, 2, 4 or 8!\n", val);
+		up(&data->update_lock);
+		return -EINVAL;
+	}
+
+	/* Correct the fan minimum speed */
+	data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
+	vt8231_write_value(client, VT8231_REG_FAN_MIN(nr), data->fan_min[nr]);
+
+	old = (old & 0x0f) | (data->fan_div[1] << 6) | (data->fan_div[0] << 4);
+	vt8231_write_value(client, VT8231_REG_FANDIV, old);
+	up(&data->update_lock);
+	return count;
+}
+
+
+#define define_fan_sysfs(offset)					\
+static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO,			\
+		show_fan, NULL, offset - 1);				\
+static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR,		\
+		show_fan_div, set_fan_div, offset - 1);			\
+static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR,		\
+		show_fan_min, set_fan_min, offset - 1)
+
+define_fan_sysfs(1);
+define_fan_sysfs(2);
+
+/* Alarms */
+static ssize_t show_alarms(struct device *dev, struct device_attribute *attr,
+			   char *buf)
+{
+	struct vt8231_data *data = vt8231_update_device(dev);
+	return sprintf(buf, "%d\n", data->alarms);
+}
+
+static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
+
+static struct i2c_driver vt8231_driver = {
+	.driver = {
+		.name	= "vt8231",
+	},
+	.attach_adapter	= vt8231_detect,
+	.detach_client	= vt8231_detach_client,
+};
+
+static struct pci_device_id vt8231_pci_ids[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231_4) },
+	{ 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, vt8231_pci_ids);
+
+static int __devinit vt8231_pci_probe(struct pci_dev *dev,
+			 	      const struct pci_device_id *id);
+
+static struct pci_driver vt8231_pci_driver = {
+	.name		= "vt8231",
+	.id_table	= vt8231_pci_ids,
+	.probe		= vt8231_pci_probe,
+};
+
+int vt8231_detect(struct i2c_adapter *adapter)
+{
+	struct i2c_client *client;
+	struct vt8231_data *data;
+	int err = 0, i;
+	u16 val;
+
+	/* 8231 requires multiple of 256 */
+	if (force_addr)	{
+		isa_address = force_addr & 0xFF00;
+		dev_warn(&adapter->dev, "forcing ISA address 0x%04X\n",
+				 isa_address);
+		if (PCIBIOS_SUCCESSFUL != pci_write_config_word(s_bridge,
+						VT8231_BASE_REG, isa_address))
+			return -ENODEV;
+	}
+
+	if (PCIBIOS_SUCCESSFUL !=
+		pci_read_config_word(s_bridge, VT8231_ENABLE_REG, &val))
+		return -ENODEV;
+
+	if (!(val & 0x0001)) {
+		dev_warn(&adapter->dev, "enabling sensors\n");
+		if (PCIBIOS_SUCCESSFUL !=
+			pci_write_config_word(s_bridge, VT8231_ENABLE_REG,
+							  val | 0x0001))
+			return -ENODEV;
+	}
+
+	/* Reserve the ISA region */
+	if (!request_region(isa_address, VT8231_EXTENT,
+			    vt8231_pci_driver.name)) {
+		dev_err(&adapter->dev, "region 0x%x already in use!\n",
+			   isa_address);
+		return -ENODEV;
+	}
+
+	if (!(data = kzalloc(sizeof(struct vt8231_data), GFP_KERNEL))) {
+		err = -ENOMEM;
+		goto exit_release;
+	}
+
+	client = &data->client;
+	i2c_set_clientdata(client, data);
+	client->addr = isa_address;
+	client->adapter = adapter;
+	client->driver = &vt8231_driver;
+	client->dev.parent = &adapter->dev;
+
+	/* Fill in the remaining client fields and put into the global list */
+	strlcpy(client->name, "vt8231", I2C_NAME_SIZE);
+
+	init_MUTEX(&data->update_lock);
+
+	/* Tell the I2C layer a new client has arrived */
+	if ((err = i2c_attach_client(client)))
+		goto exit_free;
+
+	vt8231_init_client(client);
+
+	/* Register sysfs hooks */
+	data->class_dev = hwmon_device_register(&client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto exit_detach;
+	}
+
+	/* Must update device information to find out the config field */
+	data->uch_config = vt8231_read_value(client, VT8231_REG_UCH_CONFIG);
+
+	for (i = 0; i < ARRAY_SIZE(cfg_info_temp); i++) {
+		if (ISTEMP(i, data->uch_config)) {
+			device_create_file(&client->dev,
+					   cfg_info_temp[i].input);
+			device_create_file(&client->dev, cfg_info_temp[i].max);
+			device_create_file(&client->dev, cfg_info_temp[i].min);
+		}
+	}
+
+	for (i = 0; i < ARRAY_SIZE(cfg_info_volt); i++) {
+		if (ISVOLT(i, data->uch_config)) {
+			device_create_file(&client->dev,
+					   cfg_info_volt[i].input);
+			device_create_file(&client->dev, cfg_info_volt[i].max);
+			device_create_file(&client->dev, cfg_info_volt[i].min);
+		}
+	}
+
+	device_create_file(&client->dev, &sensor_dev_attr_fan1_input.dev_attr);
+	device_create_file(&client->dev, &sensor_dev_attr_fan2_input.dev_attr);
+	device_create_file(&client->dev, &sensor_dev_attr_fan1_min.dev_attr);
+	device_create_file(&client->dev, &sensor_dev_attr_fan2_min.dev_attr);
+	device_create_file(&client->dev, &sensor_dev_attr_fan1_div.dev_attr);
+	device_create_file(&client->dev, &sensor_dev_attr_fan2_div.dev_attr);
+
+	device_create_file(&client->dev, &dev_attr_alarms);
+	return 0;
+
+exit_detach:
+	i2c_detach_client(client);
+exit_free:
+	kfree(data);
+exit_release:
+	release_region(isa_address, VT8231_EXTENT);
+	return err;
+}
+
+static int vt8231_detach_client(struct i2c_client *client)
+{
+	struct vt8231_data *data = i2c_get_clientdata(client);
+	int err;
+
+	hwmon_device_unregister(data->class_dev);
+
+	if ((err = i2c_detach_client(client))) {
+		return err;
+	}
+
+	release_region(client->addr, VT8231_EXTENT);
+	kfree(data);
+
+	return 0;
+}
+
+static void vt8231_init_client(struct i2c_client *client)
+{
+	vt8231_write_value(client, VT8231_REG_TEMP1_CONFIG, 0);
+	vt8231_write_value(client, VT8231_REG_TEMP2_CONFIG, 0);
+}
+
+static struct vt8231_data *vt8231_update_device(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct vt8231_data *data = i2c_get_clientdata(client);
+	int i;
+	u16 low;
+
+	down(&data->update_lock);
+
+	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+	    || !data->valid) {
+		for (i = 0; i < 6; i++) {
+			if (ISVOLT(i, data->uch_config)) {
+				data->in[i] = vt8231_read_value(client,
+						regvolt[i]);
+				data->in_min[i] = vt8231_read_value(client,
+						regvoltmin[i]);
+				data->in_max[i] = vt8231_read_value(client,
+						regvoltmax[i]);
+			}
+		}
+		for (i = 0; i < 2; i++) {
+			data->fan[i] = vt8231_read_value(client,
+						VT8231_REG_FAN(i));
+			data->fan_min[i] = vt8231_read_value(client,
+						VT8231_REG_FAN_MIN(i));
+		}
+
+		low = vt8231_read_value(client, VT8231_REG_TEMP_LOW01);
+		low = (low >> 6) | ((low & 0x30) >> 2)
+		    | (vt8231_read_value(client, VT8231_REG_TEMP_LOW25) << 4);
+		for (i = 0; i < 6; i++) {
+			if (ISTEMP(i, data->uch_config)) {
+				data->temp[i] = (vt8231_read_value(client,
+						       regtemp[i]) << 2)
+						| ((low >> (2 * i)) & 0x03);
+				data->temp_max[i] = vt8231_read_value(client,
+						      regtempmax[i]);
+				data->temp_min[i] = vt8231_read_value(client,
+						      regtempmin[i]);
+			}
+		}
+
+		i = vt8231_read_value(client, VT8231_REG_FANDIV);
+		data->fan_div[0] = (i >> 4) & 0x03;
+		data->fan_div[1] = i >> 6;
+		data->alarms = vt8231_read_value(client, VT8231_REG_ALARM1) |
+			(vt8231_read_value(client, VT8231_REG_ALARM2) << 8);
+
+		/* Set alarm flags correctly */
+		if (!data->fan[0] && data->fan_min[0]) {
+			data->alarms |= 0x40;
+		} else if (data->fan[0] && !data->fan_min[0]) {
+			data->alarms &= ~0x40;
+		}
+
+		if (!data->fan[1] && data->fan_min[1]) {
+			data->alarms |= 0x80;
+		} else if (data->fan[1] && !data->fan_min[1]) {
+			data->alarms &= ~0x80;
+		}
+
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+
+	up(&data->update_lock);
+
+	return data;
+}
+
+static int __devinit vt8231_pci_probe(struct pci_dev *dev,
+				const struct pci_device_id *id)
+{
+	u16 val;
+
+	if (PCIBIOS_SUCCESSFUL != pci_read_config_word(dev, VT8231_BASE_REG,
+							&val))
+		return -ENODEV;
+
+	isa_address = val & ~(VT8231_EXTENT - 1);
+	if (isa_address == 0 && force_addr == 0) {
+		dev_err(&dev->dev, "base address not set -\
+				 upgrade BIOS or use force_addr=0xaddr\n");
+		return -ENODEV;
+	}
+
+	s_bridge = pci_dev_get(dev);
+
+	if (i2c_isa_add_driver(&vt8231_driver)) {
+		pci_dev_put(s_bridge);
+		s_bridge = NULL;
+	}
+
+	/* Always return failure here.  This is to allow other drivers to bind
+	 * to this pci device.  We don't really want to have control over the
+	 * pci device, we only wanted to read as few register values from it.
+	 */
+	return -ENODEV;
+}
+
+static int __init sm_vt8231_init(void)
+{
+	return pci_module_init(&vt8231_pci_driver);
+}
+
+static void __exit sm_vt8231_exit(void)
+{
+	pci_unregister_driver(&vt8231_pci_driver);
+	if (s_bridge != NULL) {
+		i2c_isa_del_driver(&vt8231_driver);
+		pci_dev_put(s_bridge);
+		s_bridge = NULL;
+	}
+}
+
+MODULE_AUTHOR("Roger Lucas <roger@planbit.co.uk>");
+MODULE_DESCRIPTION("VT8231 sensors");
+MODULE_LICENSE("GPL");
+
+module_init(sm_vt8231_init);
+module_exit(sm_vt8231_exit);
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
index eee22a57e929..12d79f5e4900 100644
--- a/drivers/hwmon/w83627ehf.c
+++ b/drivers/hwmon/w83627ehf.c
@@ -676,7 +676,7 @@ static int w83627ehf_detect(struct i2c_adapter *adapter)
 	int i, err = 0;
 
 	if (!request_region(address + REGION_OFFSET, REGION_LENGTH,
-	                    w83627ehf_driver.name)) {
+	                    w83627ehf_driver.driver.name)) {
 		err = -EBUSY;
 		goto exit;
 	}
@@ -785,8 +785,9 @@ static int w83627ehf_detach_client(struct i2c_client *client)
 }
 
 static struct i2c_driver w83627ehf_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "w83627ehf",
+	.driver = {
+		.name	= "w83627ehf",
+	},
 	.attach_adapter	= w83627ehf_detect,
 	.detach_client	= w83627ehf_detach_client,
 };
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c
index bbb3dcde146b..7ea441d4da63 100644
--- a/drivers/hwmon/w83627hf.c
+++ b/drivers/hwmon/w83627hf.c
@@ -332,8 +332,9 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev);
 static void w83627hf_init_client(struct i2c_client *client);
 
 static struct i2c_driver w83627hf_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "w83627hf",
+	.driver = {
+		.name	= "w83627hf",
+	},
 	.attach_adapter	= w83627hf_detect,
 	.detach_client	= w83627hf_detach_client,
 };
@@ -1009,7 +1010,7 @@ static int w83627hf_detect(struct i2c_adapter *adapter)
 		address = force_addr & WINB_ALIGNMENT;
 
 	if (!request_region(address + WINB_REGION_OFFSET, WINB_REGION_SIZE,
-	                    w83627hf_driver.name)) {
+	                    w83627hf_driver.driver.name)) {
 		err = -EBUSY;
 		goto ERROR0;
 	}
@@ -1122,11 +1123,10 @@ static int w83627hf_detect(struct i2c_adapter *adapter)
 	if (kind != w83697hf)
 		device_create_file_temp(new_client, 3);
 
-	if (kind != w83697hf)
+	if (kind != w83697hf && data->vid != 0xff) {
 		device_create_file_vid(new_client);
-
-	if (kind != w83697hf)
 		device_create_file_vrm(new_client);
+	}
 
 	device_create_file_fan_div(new_client, 1);
 	device_create_file_fan_div(new_client, 2);
@@ -1232,7 +1232,7 @@ static int w83627thf_read_gpio5(struct i2c_client *client)
 
 	/* Make sure the pins are configured for input
 	   There must be at least five (VRM 9), and possibly 6 (VRM 10) */
-	sel = superio_inb(W83627THF_GPIO5_IOSR);
+	sel = superio_inb(W83627THF_GPIO5_IOSR) & 0x3f;
 	if ((sel & 0x1f) != 0x1f) {
 		dev_dbg(&client->dev, "GPIO5 not configured for VID "
 			"function\n");
@@ -1323,19 +1323,18 @@ static void w83627hf_init_client(struct i2c_client *client)
 		int hi = w83627hf_read_value(client, W83781D_REG_CHIPID);
 		data->vid = (lo & 0x0f) | ((hi & 0x01) << 4);
 	} else if (w83627thf == data->type) {
-		data->vid = w83627thf_read_gpio5(client) & 0x3f;
+		data->vid = w83627thf_read_gpio5(client);
 	}
 
 	/* Read VRM & OVT Config only once */
 	if (w83627thf == data->type || w83637hf == data->type) {
 		data->vrm_ovt = 
 			w83627hf_read_value(client, W83627THF_REG_VRM_OVT_CFG);
-		data->vrm = (data->vrm_ovt & 0x01) ? 90 : 82;
-	} else {
-		/* Convert VID to voltage based on default VRM */
-		data->vrm = vid_which_vrm();
 	}
 
+	/* Convert VID to voltage based on VRM */
+	data->vrm = vid_which_vrm();
+
 	tmp = w83627hf_read_value(client, W83781D_REG_SCFG1);
 	for (i = 1; i <= 3; i++) {
 		if (!(tmp & BIT_SCFG1[i - 1])) {
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c
index ffdb3a03e2b5..557114872f3c 100644
--- a/drivers/hwmon/w83781d.c
+++ b/drivers/hwmon/w83781d.c
@@ -269,17 +269,18 @@ static struct w83781d_data *w83781d_update_device(struct device *dev);
 static void w83781d_init_client(struct i2c_client *client);
 
 static struct i2c_driver w83781d_driver = {
-	.owner = THIS_MODULE,
-	.name = "w83781d",
+	.driver = {
+		.name = "w83781d",
+	},
 	.id = I2C_DRIVERID_W83781D,
-	.flags = I2C_DF_NOTIFY,
 	.attach_adapter = w83781d_attach_adapter,
 	.detach_client = w83781d_detach_client,
 };
 
 static struct i2c_driver w83781d_isa_driver = {
-	.owner = THIS_MODULE,
-	.name = "w83781d-isa",
+	.driver = {
+		.name = "w83781d-isa",
+	},
 	.attach_adapter = w83781d_isa_attach_adapter,
 	.detach_client = w83781d_detach_client,
 };
@@ -1012,7 +1013,7 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
 	
 	if (is_isa)
 		if (!request_region(address, W83781D_EXTENT,
-				    w83781d_isa_driver.name)) {
+				    w83781d_isa_driver.driver.name)) {
 			dev_dbg(&adapter->dev, "Request of region "
 				"0x%x-0x%x for w83781d failed\n", address,
 				address + W83781D_EXTENT - 1);
diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c
index 1ba072630361..b176bf0c4c7b 100644
--- a/drivers/hwmon/w83792d.c
+++ b/drivers/hwmon/w83792d.c
@@ -269,7 +269,6 @@ DIV_TO_REG(long val)
 struct w83792d_data {
 	struct i2c_client client;
 	struct class_device *class_dev;
-	struct semaphore lock;
 	enum chips type;
 
 	struct semaphore update_lock;
@@ -282,7 +281,7 @@ struct w83792d_data {
 	u8 in[9];		/* Register value */
 	u8 in_max[9];		/* Register value */
 	u8 in_min[9];		/* Register value */
-	u8 low_bits[2];		/* Additional resolution to voltage in0-6 */
+	u16 low_bits;		/* Additional resolution to voltage in6-0 */
 	u8 fan[7];		/* Register value */
 	u8 fan_min[7];		/* Register value */
 	u8 temp1[3];		/* current, over, thyst */
@@ -317,45 +316,17 @@ static void w83792d_print_debug(struct w83792d_data *data, struct device *dev);
 static void w83792d_init_client(struct i2c_client *client);
 
 static struct i2c_driver w83792d_driver = {
-	.owner = THIS_MODULE,
-	.name = "w83792d",
-	.flags = I2C_DF_NOTIFY,
+	.driver = {
+		.name = "w83792d",
+	},
 	.attach_adapter = w83792d_attach_adapter,
 	.detach_client = w83792d_detach_client,
 };
 
-static long in_count_from_reg(int nr, struct w83792d_data *data)
+static inline long in_count_from_reg(int nr, struct w83792d_data *data)
 {
-	u16 vol_count = data->in[nr];
-	u16 low_bits = 0;
-	vol_count = (vol_count << 2);
-	switch (nr)
-	{
-	case 0:  /* vin0 */
-		low_bits = (data->low_bits[0]) & 0x03;
-		break;
-	case 1:  /* vin1 */
-		low_bits = ((data->low_bits[0]) & 0x0c) >> 2;
-		break;
-	case 2:  /* vin2 */
-		low_bits = ((data->low_bits[0]) & 0x30) >> 4;
-		break;
-	case 3:  /* vin3 */
-		low_bits = ((data->low_bits[0]) & 0xc0) >> 6;
-		break;
-	case 4:  /* vin4 */
-		low_bits = (data->low_bits[1]) & 0x03;
-		break;
-	case 5:  /* vin5 */
-		low_bits = ((data->low_bits[1]) & 0x0c) >> 2;
-		break;
-	case 6:  /* vin6 */
-		low_bits = ((data->low_bits[1]) & 0x30) >> 4;
-	default:
-		break;
-	}
-	vol_count = vol_count | low_bits;
-	return vol_count;
+	/* in7 and in8 do not have low bits, but the formula still works */
+	return ((data->in[nr] << 2) | ((data->low_bits >> (2 * nr)) & 0x03));
 }
 
 /* following are the sysfs callback functions */
@@ -1192,7 +1163,6 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind)
 	new_client = &data->client;
 	i2c_set_clientdata(new_client, data);
 	new_client->addr = address;
-	init_MUTEX(&data->lock);
 	new_client->adapter = adapter;
 	new_client->driver = &w83792d_driver;
 	new_client->flags = 0;
@@ -1243,7 +1213,7 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind)
 			goto ERROR1;
 		}
 		val1 = w83792d_read_value(new_client, W83792D_REG_WCHIPID);
-		if (val1 == 0x7a && address >= 0x2c) {
+		if (val1 == 0x7a) {
 			kind = w83792d;
 		} else {
 			if (kind == 0)
@@ -1416,26 +1386,17 @@ w83792d_detach_client(struct i2c_client *client)
 	return 0;
 }
 
-/* The SMBus locks itself, usually, but nothing may access the Winbond between
-   bank switches. ISA access must always be locked explicitly!
-   We ignore the W83792D BUSY flag at this moment - it could lead to deadlocks,
-   would slow down the W83792D access and should not be necessary.
-   There are some ugly typecasts here, but the good news is - they should
-   nowhere else be necessary! */
-static int
-w83792d_read_value(struct i2c_client *client, u8 reg)
+/* The SMBus locks itself. The Winbond W83792D chip has a bank register,
+   but the driver only accesses registers in bank 0, so we don't have
+   to switch banks and lock access between switches. */
+static int w83792d_read_value(struct i2c_client *client, u8 reg)
 {
-	int res=0;
-	res = i2c_smbus_read_byte_data(client, reg);
-
-	return res;
+	return i2c_smbus_read_byte_data(client, reg);
 }
 
-static int
-w83792d_write_value(struct i2c_client *client, u8 reg, u8 value)
+static int w83792d_write_value(struct i2c_client *client, u8 reg, u8 value)
 {
-	i2c_smbus_write_byte_data(client, reg,  value);
-	return 0;
+	return i2c_smbus_write_byte_data(client, reg, value);
 }
 
 static void
@@ -1492,10 +1453,10 @@ static struct w83792d_data *w83792d_update_device(struct device *dev)
 			data->in_min[i] = w83792d_read_value(client,
 						W83792D_REG_IN_MIN[i]);
 		}
-		data->low_bits[0] = w83792d_read_value(client,
-						W83792D_REG_LOW_BITS1);
-		data->low_bits[1] = w83792d_read_value(client,
-						W83792D_REG_LOW_BITS2);
+		data->low_bits = w83792d_read_value(client,
+						W83792D_REG_LOW_BITS1) +
+				 (w83792d_read_value(client,
+						W83792D_REG_LOW_BITS2) << 8);
 		for (i = 0; i < 7; i++) {
 			/* Update the Fan measured value and limits */
 			data->fan[i] = w83792d_read_value(client,
@@ -1506,7 +1467,7 @@ static struct w83792d_data *w83792d_update_device(struct device *dev)
 			pwm_array_tmp[i] = w83792d_read_value(client,
 						W83792D_REG_PWM[i]);
 			data->pwm[i] = pwm_array_tmp[i] & 0x0f;
-			data->pwm_mode[i] = (pwm_array_tmp[i] >> 7) & 0x01;
+			data->pwm_mode[i] = pwm_array_tmp[i] >> 7;
 		}
 
 		reg_tmp = w83792d_read_value(client, W83792D_REG_FAN_CFG);
@@ -1607,8 +1568,8 @@ static void w83792d_print_debug(struct w83792d_data *data, struct device *dev)
 		dev_dbg(dev, "vin[%d] max is: 0x%x\n", i, data->in_max[i]);
 		dev_dbg(dev, "vin[%d] min is: 0x%x\n", i, data->in_min[i]);
 	}
-	dev_dbg(dev, "Low Bit1 is: 0x%x\n", data->low_bits[0]);
-	dev_dbg(dev, "Low Bit2 is: 0x%x\n", data->low_bits[1]);
+	dev_dbg(dev, "Low Bit1 is: 0x%x\n", data->low_bits & 0xff);
+	dev_dbg(dev, "Low Bit2 is: 0x%x\n", data->low_bits >> 8);
 	dev_dbg(dev, "7 set of Fan Counts and Duty Cycles: =====>\n");
 	for (i=0; i<7; i++) {
 		dev_dbg(dev, "fan[%d] is: 0x%x\n", i, data->fan[i]);
diff --git a/drivers/hwmon/w83l785ts.c b/drivers/hwmon/w83l785ts.c
index f495b6378668..f66c0cfdeda7 100644
--- a/drivers/hwmon/w83l785ts.c
+++ b/drivers/hwmon/w83l785ts.c
@@ -92,10 +92,10 @@ static struct w83l785ts_data *w83l785ts_update_device(struct device *dev);
  */
  
 static struct i2c_driver w83l785ts_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "w83l785ts",
+	.driver = {
+		.name	= "w83l785ts",
+	},
 	.id		= I2C_DRIVERID_W83L785TS,
-	.flags		= I2C_DF_NOTIFY,
 	.attach_adapter	= w83l785ts_attach_adapter,
 	.detach_client	= w83l785ts_detach_client,
 };
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index ac3eafa8aac0..1c752ddc10e2 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -468,8 +468,7 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr,
 		return -1;
 	}
 
-	if (hwpec)
-		outb_p(1, SMBAUXCTL);	/* enable hardware PEC */
+	outb_p(hwpec, SMBAUXCTL);	/* enable/disable hardware PEC */
 
 	if(block)
 		ret = i801_block_transaction(data, read_write, size, hwpec);
@@ -478,9 +477,6 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr,
 		ret = i801_transaction();
 	}
 
-	if (hwpec)
-		outb_p(0, SMBAUXCTL);	/* disable hardware PEC */
-
 	if(block)
 		return ret;
 	if(ret)
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
index 1a587253d716..87fae937e666 100644
--- a/drivers/i2c/busses/i2c-ibm_iic.c
+++ b/drivers/i2c/busses/i2c-ibm_iic.c
@@ -725,6 +725,7 @@ static int __devinit iic_probe(struct ocp_device *ocp){
 	strcpy(adap->name, "IBM IIC");
 	i2c_set_adapdata(adap, dev);
 	adap->id = I2C_HW_OCP;
+	adap->class = I2C_CLASS_HWMON;
 	adap->algo = &iic_algo;
 	adap->client_register = NULL;
 	adap->client_unregister = NULL;
diff --git a/drivers/i2c/busses/i2c-isa.c b/drivers/i2c/busses/i2c-isa.c
index 03672c9ca409..9f2ffef4d812 100644
--- a/drivers/i2c/busses/i2c-isa.c
+++ b/drivers/i2c/busses/i2c-isa.c
@@ -92,15 +92,13 @@ int i2c_isa_add_driver(struct i2c_driver *driver)
 	int res;
 
 	/* Add the driver to the list of i2c drivers in the driver core */
-	driver->driver.name = driver->name;
-	driver->driver.owner = driver->owner;
 	driver->driver.bus = &i2c_bus_type;
 	driver->driver.probe = i2c_isa_device_probe;
 	driver->driver.remove = i2c_isa_device_remove;
 	res = driver_register(&driver->driver);
 	if (res)
 		return res;
-	dev_dbg(&isa_adapter.dev, "Driver %s registered\n", driver->name);
+	dev_dbg(&isa_adapter.dev, "Driver %s registered\n", driver->driver.name);
 
 	/* Now look for clients */
 	driver->attach_adapter(&isa_adapter);
@@ -124,14 +122,14 @@ int i2c_isa_del_driver(struct i2c_driver *driver)
 		if ((res = driver->detach_client(client))) {
 			dev_err(&isa_adapter.dev, "Failed, driver "
 				"%s not unregistered!\n",
-				driver->name);
+				driver->driver.name);
 			return res;
 		}
 	}
 
 	/* Get the driver off the core list */
 	driver_unregister(&driver->driver);
-	dev_dbg(&isa_adapter.dev, "Driver %s unregistered\n", driver->name);
+	dev_dbg(&isa_adapter.dev, "Driver %s unregistered\n", driver->driver.name);
 
 	return 0;
 }
@@ -176,7 +174,7 @@ static void __exit i2c_isa_exit(void)
 	list_for_each_safe(item, _n, &isa_adapter.clients) {
 		client = list_entry(item, struct i2c_client, list);
 		dev_err(&isa_adapter.dev, "Driver %s still has an active "
-			"ISA client at 0x%x\n", client->driver->name,
+			"ISA client at 0x%x\n", client->driver->driver.name,
 			client->addr);
 	}
 	if (client != NULL)
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index 81031eb51056..22781d84f79f 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -1,6 +1,4 @@
 /*
- * drivers/i2c/busses/i2c-mv64xxx.c
- * 
  * Driver for the i2c controller on the Marvell line of host bridges for MIPS
  * and PPC (e.g, gt642[46]0, mv643[46]0, mv644[46]0).
  *
@@ -65,7 +63,6 @@ enum {
 	MV64XXX_I2C_STATE_WAITING_FOR_ADDR_2_ACK,
 	MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_ACK,
 	MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_DATA,
-	MV64XXX_I2C_STATE_ABORTING,
 };
 
 /* Driver actions */
@@ -85,6 +82,7 @@ struct mv64xxx_i2c_data {
 	int			irq;
 	u32			state;
 	u32			action;
+	u32			aborting;
 	u32			cntl_bits;
 	void __iomem		*reg_base;
 	u32			reg_base_p;
@@ -122,12 +120,6 @@ mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status)
 		return;
 	}
 
-	if (drv_data->state == MV64XXX_I2C_STATE_ABORTING) {
-		drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP;
-		drv_data->state = MV64XXX_I2C_STATE_IDLE;
-		return;
-	}
-
 	/* The status from the ctlr [mostly] tells us what to do next */
 	switch (status) {
 	/* Start condition interrupt */
@@ -148,14 +140,16 @@ mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status)
 		/* FALLTHRU */
 	case MV64XXX_I2C_STATUS_MAST_WR_ADDR_2_ACK: /* 0xd0 */
 	case MV64XXX_I2C_STATUS_MAST_WR_ACK: /* 0x28 */
-		if (drv_data->bytes_left > 0) {
+		if ((drv_data->bytes_left == 0)
+				|| (drv_data->aborting
+					&& (drv_data->byte_posn != 0))) {
+			drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP;
+			drv_data->state = MV64XXX_I2C_STATE_IDLE;
+		} else {
 			drv_data->action = MV64XXX_I2C_ACTION_SEND_DATA;
 			drv_data->state =
 				MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_ACK;
 			drv_data->bytes_left--;
-		} else {
-			drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP;
-			drv_data->state = MV64XXX_I2C_STATE_IDLE;
 		}
 		break;
 
@@ -184,7 +178,7 @@ mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status)
 		}
 		drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_DATA;
 
-		if (drv_data->bytes_left == 1)
+		if ((drv_data->bytes_left == 1) || drv_data->aborting)
 			drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_ACK;
 		break;
 
@@ -320,6 +314,7 @@ mv64xxx_i2c_prepare_for_io(struct mv64xxx_i2c_data *drv_data,
 	drv_data->msg = msg;
 	drv_data->byte_posn = 0;
 	drv_data->bytes_left = msg->len;
+	drv_data->aborting = 0;
 	drv_data->rc = 0;
 	drv_data->cntl_bits = MV64XXX_I2C_REG_CONTROL_ACK |
 		MV64XXX_I2C_REG_CONTROL_INTEN | MV64XXX_I2C_REG_CONTROL_TWSIEN;
@@ -359,17 +354,19 @@ mv64xxx_i2c_wait_for_completion(struct mv64xxx_i2c_data *drv_data)
 	}
 
 	if (abort && drv_data->block) {
-		drv_data->state = MV64XXX_I2C_STATE_ABORTING;
+		drv_data->aborting = 1;
 		spin_unlock_irqrestore(&drv_data->lock, flags);
 
 		time_left = wait_event_timeout(drv_data->waitq,
 			!drv_data->block,
 			msecs_to_jiffies(drv_data->adapter.timeout));
 
-		if (time_left <= 0) {
+		if ((time_left <= 0) && drv_data->block) {
 			drv_data->state = MV64XXX_I2C_STATE_IDLE;
 			dev_err(&drv_data->adapter.dev,
-				"mv64xxx: I2C bus locked\n");
+				"mv64xxx: I2C bus locked, block: %d, "
+				"time_left: %d\n", drv_data->block,
+				(int)time_left);
 		}
 	} else
 		spin_unlock_irqrestore(&drv_data->lock, flags);
@@ -510,7 +507,7 @@ mv64xxx_i2c_probe(struct platform_device *pd)
 		goto exit_kfree;
 	}
 
-	strncpy(drv_data->adapter.name, MV64XXX_I2C_CTLR_NAME " adapter",
+	strlcpy(drv_data->adapter.name, MV64XXX_I2C_CTLR_NAME " adapter",
 		I2C_NAME_SIZE);
 
 	init_waitqueue_head(&drv_data->waitq);
diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c
index 4d18e6e5f159..2d80eb26f688 100644
--- a/drivers/i2c/busses/i2c-nforce2.c
+++ b/drivers/i2c/busses/i2c-nforce2.c
@@ -30,6 +30,7 @@
     nForce3 Pro150 MCP		00D4
     nForce3 250Gb MCP		00E4
     nForce4 MCP			0052
+    nForce4 MCP-04		0034
 
     This driver supports the 2 SMBuses that are included in the MCP of the
     nForce2/3/4 chipsets.
@@ -257,6 +258,7 @@ static struct pci_device_id nforce2_ids[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SMBUS) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE4_SMBUS) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SMBUS) },
 	{ 0 }
 };
 
diff --git a/drivers/i2c/busses/i2c-parport.h b/drivers/i2c/busses/i2c-parport.h
index f63a53779281..d702e5e0388d 100644
--- a/drivers/i2c/busses/i2c-parport.h
+++ b/drivers/i2c/busses/i2c-parport.h
@@ -80,6 +80,14 @@ static struct adapter_parm adapter_parm[] = {
 		.setscl	= { 0x01, DATA, 1 },
 		.getsda	= { 0x10, STAT, 1 },
 	},
+	/* type 6: Barco LPT->DVI (K5800236) adapter */
+	{
+		.setsda	= { 0x02, DATA, 1 },
+		.setscl	= { 0x01, DATA, 1 },
+		.getsda	= { 0x20, STAT, 0 },
+		.getscl	= { 0x40, STAT, 0 },
+		.init	= { 0xfc, DATA, 0 },
+	},
 };
 
 static int type;
@@ -91,4 +99,6 @@ MODULE_PARM_DESC(type,
 	" 2 = Velleman K8000 adapter\n"
 	" 3 = ELV adapter\n"
 	" 4 = ADM1032 evaluation board\n"
-	" 5 = ADM1025, ADM1030 and ADM1031 evaluation boards\n");
+	" 5 = ADM1025, ADM1030 and ADM1031 evaluation boards\n"
+	" 6 = Barco LPT->DVI (K5800236) adapter\n"
+);
diff --git a/drivers/i2c/chips/ds1337.c b/drivers/i2c/chips/ds1337.c
index 02682fb794c8..93d483b8b770 100644
--- a/drivers/i2c/chips/ds1337.c
+++ b/drivers/i2c/chips/ds1337.c
@@ -52,9 +52,9 @@ static int ds1337_command(struct i2c_client *client, unsigned int cmd,
  * Driver data (common to all clients)
  */
 static struct i2c_driver ds1337_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "ds1337",
-	.flags		= I2C_DF_NOTIFY,
+	.driver = {
+		.name	= "ds1337",
+	},
 	.attach_adapter	= ds1337_attach_adapter,
 	.detach_client	= ds1337_detach_client,
 	.command	= ds1337_command,
@@ -337,13 +337,38 @@ exit:
 
 static void ds1337_init_client(struct i2c_client *client)
 {
-	s32 val;
+	u8 status, control;
 
-	/* Ensure that device is set in 24-hour mode */
-	val = i2c_smbus_read_byte_data(client, DS1337_REG_HOUR);
-	if ((val >= 0) && (val & (1 << 6)))
-		i2c_smbus_write_byte_data(client, DS1337_REG_HOUR,
-					  val & 0x3f);
+	/* On some boards, the RTC isn't configured by boot firmware.
+	 * Handle that case by starting/configuring the RTC now.
+	 */
+	status = i2c_smbus_read_byte_data(client, DS1337_REG_STATUS);
+	control = i2c_smbus_read_byte_data(client, DS1337_REG_CONTROL);
+
+	if ((status & 0x80) || (control & 0x80)) {
+		/* RTC not running */
+		u8 buf[16];
+		struct i2c_msg msg[1];
+
+		dev_dbg(&client->dev, "%s: RTC not running!\n", __FUNCTION__);
+
+		/* Initialize all, including STATUS and CONTROL to zero */
+		memset(buf, 0, sizeof(buf));
+		msg[0].addr = client->addr;
+		msg[0].flags = 0;
+		msg[0].len = sizeof(buf);
+		msg[0].buf = &buf[0];
+
+		i2c_transfer(client->adapter, msg, 1);
+	} else {
+		/* Running: ensure that device is set in 24-hour mode */
+		s32 val;
+
+		val = i2c_smbus_read_byte_data(client, DS1337_REG_HOUR);
+		if ((val >= 0) && (val & (1 << 6)))
+			i2c_smbus_write_byte_data(client, DS1337_REG_HOUR,
+						  val & 0x3f);
+	}
 }
 
 static int ds1337_detach_client(struct i2c_client *client)
diff --git a/drivers/i2c/chips/ds1374.c b/drivers/i2c/chips/ds1374.c
index da488b735abf..0710b9da9d54 100644
--- a/drivers/i2c/chips/ds1374.c
+++ b/drivers/i2c/chips/ds1374.c
@@ -232,10 +232,10 @@ static int ds1374_detach(struct i2c_client *client)
 }
 
 static struct i2c_driver ds1374_driver = {
-	.owner = THIS_MODULE,
-	.name = DS1374_DRV_NAME,
+	.driver = {
+		.name	= DS1374_DRV_NAME,
+	},
 	.id = I2C_DRIVERID_DS1374,
-	.flags = I2C_DF_NOTIFY,
 	.attach_adapter = ds1374_attach,
 	.detach_client = ds1374_detach,
 };
diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c
index 4baf573fa04f..41116b7947f6 100644
--- a/drivers/i2c/chips/eeprom.c
+++ b/drivers/i2c/chips/eeprom.c
@@ -68,10 +68,10 @@ static int eeprom_detach_client(struct i2c_client *client);
 
 /* This is the driver that will be inserted */
 static struct i2c_driver eeprom_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "eeprom",
+	.driver = {
+		.name	= "eeprom",
+	},
 	.id		= I2C_DRIVERID_EEPROM,
-	.flags		= I2C_DF_NOTIFY,
 	.attach_adapter	= eeprom_attach_adapter,
 	.detach_client	= eeprom_detach_client,
 };
diff --git a/drivers/i2c/chips/isp1301_omap.c b/drivers/i2c/chips/isp1301_omap.c
index d2a100d77839..1251c7fc18d5 100644
--- a/drivers/i2c/chips/isp1301_omap.c
+++ b/drivers/i2c/chips/isp1301_omap.c
@@ -1632,11 +1632,11 @@ static int isp1301_scan_bus(struct i2c_adapter *bus)
 }
 
 static struct i2c_driver isp1301_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "isp1301_omap",
+	.driver = {
+		.name	= "isp1301_omap",
+	},
 	.id		= 1301,		/* FIXME "official", i2c-ids.h */
 	.class		= I2C_CLASS_HWMON,
-	.flags		= I2C_DF_NOTIFY,
 	.attach_adapter	= isp1301_scan_bus,
 	.detach_client	= isp1301_detach_client,
 };
diff --git a/drivers/i2c/chips/m41t00.c b/drivers/i2c/chips/m41t00.c
index 3df309ae44a6..2dc3d48375fc 100644
--- a/drivers/i2c/chips/m41t00.c
+++ b/drivers/i2c/chips/m41t00.c
@@ -211,10 +211,10 @@ m41t00_detach(struct i2c_client *client)
 }
 
 static struct i2c_driver m41t00_driver = {
-	.owner		= THIS_MODULE,
-	.name		= M41T00_DRV_NAME,
+	.driver = {
+		.name	= M41T00_DRV_NAME,
+	},
 	.id		= I2C_DRIVERID_STM41T00,
-	.flags		= I2C_DF_NOTIFY,
 	.attach_adapter	= m41t00_attach,
 	.detach_client	= m41t00_detach,
 };
diff --git a/drivers/i2c/chips/max6875.c b/drivers/i2c/chips/max6875.c
index b376a006883c..6d3ff584155e 100644
--- a/drivers/i2c/chips/max6875.c
+++ b/drivers/i2c/chips/max6875.c
@@ -67,9 +67,9 @@ static int max6875_detach_client(struct i2c_client *client);
 
 /* This is the driver that will be inserted */
 static struct i2c_driver max6875_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "max6875",
-	.flags		= I2C_DF_NOTIFY,
+	.driver = {
+		.name	= "max6875",
+	},
 	.attach_adapter	= max6875_attach_adapter,
 	.detach_client	= max6875_detach_client,
 };
diff --git a/drivers/i2c/chips/pca9539.c b/drivers/i2c/chips/pca9539.c
index 59a930346229..54b6e6a4beed 100644
--- a/drivers/i2c/chips/pca9539.c
+++ b/drivers/i2c/chips/pca9539.c
@@ -38,9 +38,9 @@ static int pca9539_detach_client(struct i2c_client *client);
 
 /* This is the driver that will be inserted */
 static struct i2c_driver pca9539_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "pca9539",
-	.flags		= I2C_DF_NOTIFY,
+	.driver = {
+		.name	= "pca9539",
+	},
 	.attach_adapter	= pca9539_attach_adapter,
 	.detach_client	= pca9539_detach_client,
 };
diff --git a/drivers/i2c/chips/pcf8574.c b/drivers/i2c/chips/pcf8574.c
index c323c2de236c..c3e6449c4481 100644
--- a/drivers/i2c/chips/pcf8574.c
+++ b/drivers/i2c/chips/pcf8574.c
@@ -65,10 +65,10 @@ static void pcf8574_init_client(struct i2c_client *client);
 
 /* This is the driver that will be inserted */
 static struct i2c_driver pcf8574_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "pcf8574",
+	.driver = {
+		.name	= "pcf8574",
+	},
 	.id		= I2C_DRIVERID_PCF8574,
-	.flags		= I2C_DF_NOTIFY,
 	.attach_adapter	= pcf8574_attach_adapter,
 	.detach_client	= pcf8574_detach_client,
 };
diff --git a/drivers/i2c/chips/pcf8591.c b/drivers/i2c/chips/pcf8591.c
index ce420a67560b..36cff09c678d 100644
--- a/drivers/i2c/chips/pcf8591.c
+++ b/drivers/i2c/chips/pcf8591.c
@@ -88,10 +88,10 @@ static int pcf8591_read_channel(struct device *dev, int channel);
 
 /* This is the driver that will be inserted */
 static struct i2c_driver pcf8591_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "pcf8591",
+	.driver = {
+		.name	= "pcf8591",
+	},
 	.id		= I2C_DRIVERID_PCF8591,
-	.flags		= I2C_DF_NOTIFY,
 	.attach_adapter	= pcf8591_attach_adapter,
 	.detach_client	= pcf8591_detach_client,
 };
diff --git a/drivers/i2c/chips/rtc8564.c b/drivers/i2c/chips/rtc8564.c
index 916cdc1af23c..ceaa6b0bdfd6 100644
--- a/drivers/i2c/chips/rtc8564.c
+++ b/drivers/i2c/chips/rtc8564.c
@@ -14,6 +14,7 @@
  */
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/bcd.h>
 #include <linux/i2c.h>
 #include <linux/slab.h>
 #include <linux/string.h>
@@ -52,9 +53,6 @@ static inline u8 _rtc8564_ctrl2(struct i2c_client *client)
 #define CTRL1(c) _rtc8564_ctrl1(c)
 #define CTRL2(c) _rtc8564_ctrl2(c)
 
-#define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10)
-#define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10)
-
 static int debug;;
 module_param(debug, int, S_IRUGO | S_IWUSR);
 
@@ -157,7 +155,6 @@ static int rtc8564_attach(struct i2c_adapter *adap, int addr, int kind)
 
 	strlcpy(new_client->name, "RTC8564", I2C_NAME_SIZE);
 	i2c_set_clientdata(new_client, d);
-	new_client->flags = I2C_CLIENT_ALLOW_USE;
 	new_client->addr = addr;
 	new_client->adapter = adap;
 	new_client->driver = &rtc8564_driver;
@@ -224,16 +221,16 @@ static int rtc8564_get_datetime(struct i2c_client *client, struct rtc_tm *dt)
 		return ret;
 
 	/* century stored in minute alarm reg */
-	dt->year = BCD_TO_BIN(buf[RTC8564_REG_YEAR]);
-	dt->year += 100 * BCD_TO_BIN(buf[RTC8564_REG_AL_MIN] & 0x3f);
-	dt->mday = BCD_TO_BIN(buf[RTC8564_REG_DAY] & 0x3f);
-	dt->wday = BCD_TO_BIN(buf[RTC8564_REG_WDAY] & 7);
-	dt->mon = BCD_TO_BIN(buf[RTC8564_REG_MON_CENT] & 0x1f);
+	dt->year = BCD2BIN(buf[RTC8564_REG_YEAR]);
+	dt->year += 100 * BCD2BIN(buf[RTC8564_REG_AL_MIN] & 0x3f);
+	dt->mday = BCD2BIN(buf[RTC8564_REG_DAY] & 0x3f);
+	dt->wday = BCD2BIN(buf[RTC8564_REG_WDAY] & 7);
+	dt->mon = BCD2BIN(buf[RTC8564_REG_MON_CENT] & 0x1f);
 
-	dt->secs = BCD_TO_BIN(buf[RTC8564_REG_SEC] & 0x7f);
+	dt->secs = BCD2BIN(buf[RTC8564_REG_SEC] & 0x7f);
 	dt->vl = (buf[RTC8564_REG_SEC] & 0x80) == 0x80;
-	dt->mins = BCD_TO_BIN(buf[RTC8564_REG_MIN] & 0x7f);
-	dt->hours = BCD_TO_BIN(buf[RTC8564_REG_HR] & 0x3f);
+	dt->mins = BCD2BIN(buf[RTC8564_REG_MIN] & 0x7f);
+	dt->hours = BCD2BIN(buf[RTC8564_REG_HR] & 0x3f);
 
 	_DBGRTCTM(2, *dt);
 
@@ -255,18 +252,18 @@ rtc8564_set_datetime(struct i2c_client *client, struct rtc_tm *dt, int datetoo)
 
 	buf[RTC8564_REG_CTRL1] = CTRL1(client) | RTC8564_CTRL1_STOP;
 	buf[RTC8564_REG_CTRL2] = CTRL2(client);
-	buf[RTC8564_REG_SEC] = BIN_TO_BCD(dt->secs);
-	buf[RTC8564_REG_MIN] = BIN_TO_BCD(dt->mins);
-	buf[RTC8564_REG_HR] = BIN_TO_BCD(dt->hours);
+	buf[RTC8564_REG_SEC] = BIN2BCD(dt->secs);
+	buf[RTC8564_REG_MIN] = BIN2BCD(dt->mins);
+	buf[RTC8564_REG_HR] = BIN2BCD(dt->hours);
 
 	if (datetoo) {
 		len += 5;
-		buf[RTC8564_REG_DAY] = BIN_TO_BCD(dt->mday);
-		buf[RTC8564_REG_WDAY] = BIN_TO_BCD(dt->wday);
-		buf[RTC8564_REG_MON_CENT] = BIN_TO_BCD(dt->mon) & 0x1f;
+		buf[RTC8564_REG_DAY] = BIN2BCD(dt->mday);
+		buf[RTC8564_REG_WDAY] = BIN2BCD(dt->wday);
+		buf[RTC8564_REG_MON_CENT] = BIN2BCD(dt->mon) & 0x1f;
 		/* century stored in minute alarm reg */
-		buf[RTC8564_REG_YEAR] = BIN_TO_BCD(dt->year % 100);
-		buf[RTC8564_REG_AL_MIN] = BIN_TO_BCD(dt->year / 100);
+		buf[RTC8564_REG_YEAR] = BIN2BCD(dt->year % 100);
+		buf[RTC8564_REG_AL_MIN] = BIN2BCD(dt->year / 100);
 	}
 
 	ret = rtc8564_write(client, 0, buf, len);
@@ -361,10 +358,10 @@ rtc8564_command(struct i2c_client *client, unsigned int cmd, void *arg)
 }
 
 static struct i2c_driver rtc8564_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "RTC8564",
+	.driver = {
+		.name	= "RTC8564",
+	},
 	.id		= I2C_DRIVERID_RTC8564,
-	.flags		= I2C_DF_NOTIFY,
 	.attach_adapter = rtc8564_probe,
 	.detach_client	= rtc8564_detach,
 	.command	= rtc8564_command
diff --git a/drivers/i2c/chips/tps65010.c b/drivers/i2c/chips/tps65010.c
index 280dd7a45db6..e70b3db69edd 100644
--- a/drivers/i2c/chips/tps65010.c
+++ b/drivers/i2c/chips/tps65010.c
@@ -637,9 +637,9 @@ static int __init tps65010_scan_bus(struct i2c_adapter *bus)
 }
 
 static struct i2c_driver tps65010_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "tps65010",
-	.flags		= I2C_DF_NOTIFY,
+	.driver = {
+		.name	= "tps65010",
+	},
 	.attach_adapter	= tps65010_scan_bus,
 	.detach_client	= __exit_p(tps65010_detach_client),
 };
diff --git a/drivers/i2c/chips/x1205.c b/drivers/i2c/chips/x1205.c
index 7da366cdc18c..245fffa92dbd 100644
--- a/drivers/i2c/chips/x1205.c
+++ b/drivers/i2c/chips/x1205.c
@@ -105,9 +105,9 @@ static int x1205_command(struct i2c_client *client, unsigned int cmd,
 	void *arg);
 
 static struct i2c_driver x1205_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "x1205",
-	.flags		= I2C_DF_NOTIFY,
+	.driver = {
+		.name	= "x1205",
+	},
 	.attach_adapter = &x1205_attach,
 	.detach_client	= &x1205_detach,
 };
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 82ea1b7ec914..52b77477df57 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -197,7 +197,7 @@ int i2c_add_adapter(struct i2c_adapter *adap)
 	/* inform drivers of new adapters */
 	list_for_each(item,&drivers) {
 		driver = list_entry(item, struct i2c_driver, list);
-		if (driver->flags & I2C_DF_NOTIFY)
+		if (driver->attach_adapter)
 			/* We ignore the return code; if it fails, too bad */
 			driver->attach_adapter(adap);
 	}
@@ -235,7 +235,8 @@ int i2c_del_adapter(struct i2c_adapter *adap)
 		if (driver->detach_adapter)
 			if ((res = driver->detach_adapter(adap))) {
 				dev_err(&adap->dev, "detach_adapter failed "
-					"for driver [%s]\n", driver->name);
+					"for driver [%s]\n",
+					driver->driver.name);
 				goto out_unlock;
 			}
 	}
@@ -245,10 +246,6 @@ int i2c_del_adapter(struct i2c_adapter *adap)
 	list_for_each_safe(item, _n, &adap->clients) {
 		client = list_entry(item, struct i2c_client, list);
 
-		/* detaching devices is unconditional of the set notify
-		 * flag, as _all_ clients that reside on the adapter
-		 * must be deleted, as this would cause invalid states.
-		 */
 		if ((res=client->driver->detach_client(client))) {
 			dev_err(&adap->dev, "detach_client failed for client "
 				"[%s] at address 0x%02x\n", client->name,
@@ -286,7 +283,7 @@ int i2c_del_adapter(struct i2c_adapter *adap)
  * chips.
  */
 
-int i2c_add_driver(struct i2c_driver *driver)
+int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
 {
 	struct list_head   *item;
 	struct i2c_adapter *adapter;
@@ -295,8 +292,7 @@ int i2c_add_driver(struct i2c_driver *driver)
 	down(&core_lists);
 
 	/* add the driver to the list of i2c drivers in the driver core */
-	driver->driver.owner = driver->owner;
-	driver->driver.name = driver->name;
+	driver->driver.owner = owner;
 	driver->driver.bus = &i2c_bus_type;
 	driver->driver.probe = i2c_device_probe;
 	driver->driver.remove = i2c_device_remove;
@@ -306,10 +302,10 @@ int i2c_add_driver(struct i2c_driver *driver)
 		goto out_unlock;
 	
 	list_add_tail(&driver->list,&drivers);
-	pr_debug("i2c-core: driver [%s] registered\n", driver->name);
+	pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name);
 
 	/* now look for instances of driver on our adapters */
-	if (driver->flags & I2C_DF_NOTIFY) {
+	if (driver->attach_adapter) {
 		list_for_each(item,&adapters) {
 			adapter = list_entry(item, struct i2c_adapter, list);
 			driver->attach_adapter(adapter);
@@ -320,6 +316,7 @@ int i2c_add_driver(struct i2c_driver *driver)
 	up(&core_lists);
 	return res;
 }
+EXPORT_SYMBOL(i2c_register_driver);
 
 int i2c_del_driver(struct i2c_driver *driver)
 {
@@ -334,17 +331,14 @@ int i2c_del_driver(struct i2c_driver *driver)
 	/* Have a look at each adapter, if clients of this driver are still
 	 * attached. If so, detach them to be able to kill the driver 
 	 * afterwards.
-	 *
-	 * Removing clients does not depend on the notify flag, else
-	 * invalid operation might (will!) result, when using stale client
-	 * pointers.
 	 */
 	list_for_each(item1,&adapters) {
 		adap = list_entry(item1, struct i2c_adapter, list);
 		if (driver->detach_adapter) {
 			if ((res = driver->detach_adapter(adap))) {
 				dev_err(&adap->dev, "detach_adapter failed "
-					"for driver [%s]\n", driver->name);
+					"for driver [%s]\n",
+					driver->driver.name);
 				goto out_unlock;
 			}
 		} else {
@@ -368,7 +362,7 @@ int i2c_del_driver(struct i2c_driver *driver)
 
 	driver_unregister(&driver->driver);
 	list_del(&driver->list);
-	pr_debug("i2c-core: driver [%s] unregistered\n", driver->name);
+	pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name);
 
  out_unlock:
 	up(&core_lists);
@@ -419,8 +413,7 @@ int i2c_attach_client(struct i2c_client *client)
 		}
 	}
 
-	if (client->flags & I2C_CLIENT_ALLOW_USE)
-		client->usage_count = 0;
+	client->usage_count = 0;
 
 	client->dev.parent = &client->adapter->dev;
 	client->dev.driver = &client->driver->driver;
@@ -443,8 +436,7 @@ int i2c_detach_client(struct i2c_client *client)
 	struct i2c_adapter *adapter = client->adapter;
 	int res = 0;
 	
-	if ((client->flags & I2C_CLIENT_ALLOW_USE)
-	 && (client->usage_count > 0)) {
+	if (client->usage_count > 0) {
 		dev_warn(&client->dev, "Client [%s] still busy, "
 			 "can't detach\n", client->name);
 		return -EBUSY;
@@ -475,10 +467,10 @@ int i2c_detach_client(struct i2c_client *client)
 static int i2c_inc_use_client(struct i2c_client *client)
 {
 
-	if (!try_module_get(client->driver->owner))
+	if (!try_module_get(client->driver->driver.owner))
 		return -ENODEV;
 	if (!try_module_get(client->adapter->owner)) {
-		module_put(client->driver->owner);
+		module_put(client->driver->driver.owner);
 		return -ENODEV;
 	}
 
@@ -487,7 +479,7 @@ static int i2c_inc_use_client(struct i2c_client *client)
 
 static void i2c_dec_use_client(struct i2c_client *client)
 {
-	module_put(client->driver->owner);
+	module_put(client->driver->driver.owner);
 	module_put(client->adapter->owner);
 }
 
@@ -499,33 +491,20 @@ int i2c_use_client(struct i2c_client *client)
 	if (ret)
 		return ret;
 
-	if (client->flags & I2C_CLIENT_ALLOW_USE) {
-		if (client->flags & I2C_CLIENT_ALLOW_MULTIPLE_USE)
-			client->usage_count++;
-		else if (client->usage_count > 0) 
-			goto busy;
-		else 
-			client->usage_count++;
-	}
+	client->usage_count++;
 
 	return 0;
- busy:
-	i2c_dec_use_client(client);
-	return -EBUSY;
 }
 
 int i2c_release_client(struct i2c_client *client)
 {
-	if(client->flags & I2C_CLIENT_ALLOW_USE) {
-		if(client->usage_count>0)
-			client->usage_count--;
-		else {
-			pr_debug("i2c-core: %s used one too many times\n",
-				__FUNCTION__);
-			return -EPERM;
-		}
+	if (!client->usage_count) {
+		pr_debug("i2c-core: %s used one too many times\n",
+			 __FUNCTION__);
+		return -EPERM;
 	}
 	
+	client->usage_count--;
 	i2c_dec_use_client(client);
 	
 	return 0;
@@ -539,14 +518,14 @@ void i2c_clients_command(struct i2c_adapter *adap, unsigned int cmd, void *arg)
 	down(&adap->clist_lock);
 	list_for_each(item,&adap->clients) {
 		client = list_entry(item, struct i2c_client, list);
-		if (!try_module_get(client->driver->owner))
+		if (!try_module_get(client->driver->driver.owner))
 			continue;
 		if (NULL != client->driver->command) {
 			up(&adap->clist_lock);
 			client->driver->command(client,cmd,arg);
 			down(&adap->clist_lock);
 		}
-		module_put(client->driver->owner);
+		module_put(client->driver->driver.owner);
        }
        up(&adap->clist_lock);
 }
@@ -1147,7 +1126,6 @@ EXPORT_SYMBOL_GPL(i2c_bus_type);
 
 EXPORT_SYMBOL(i2c_add_adapter);
 EXPORT_SYMBOL(i2c_del_adapter);
-EXPORT_SYMBOL(i2c_add_driver);
 EXPORT_SYMBOL(i2c_del_driver);
 EXPORT_SYMBOL(i2c_attach_client);
 EXPORT_SYMBOL(i2c_detach_client);
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index 8af0bd1424d2..ed7eed388bae 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -42,8 +42,7 @@ static struct i2c_client i2cdev_client_template;
 struct i2c_dev {
 	int minor;
 	struct i2c_adapter *adap;
-	struct class_device class_dev;
-	struct completion released;	/* FIXME, we need a class_device_unregister() */
+	struct class_device *class_dev;
 };
 #define to_i2c_dev(d) container_of(d, struct i2c_dev, class_dev)
 
@@ -105,7 +104,10 @@ static void return_i2c_dev(struct i2c_dev *i2c_dev)
 
 static ssize_t show_adapter_name(struct class_device *class_dev, char *buf)
 {
-	struct i2c_dev *i2c_dev = to_i2c_dev(class_dev);
+	struct i2c_dev *i2c_dev = i2c_dev_get_by_minor(MINOR(class_dev->devt));
+
+	if (!i2c_dev)
+		return -ENODEV;
 	return sprintf(buf, "%s\n", i2c_dev->adap->name);
 }
 static CLASS_DEVICE_ATTR(name, S_IRUGO, show_adapter_name, NULL);
@@ -408,21 +410,12 @@ static struct file_operations i2cdev_fops = {
 	.release	= i2cdev_release,
 };
 
-static void release_i2c_dev(struct class_device *dev)
-{
-	struct i2c_dev *i2c_dev = to_i2c_dev(dev);
-	complete(&i2c_dev->released);
-}
-
-static struct class i2c_dev_class = {
-	.name		= "i2c-dev",
-	.release	= &release_i2c_dev,
-};
+static struct class *i2c_dev_class;
 
 static int i2cdev_attach_adapter(struct i2c_adapter *adap)
 {
 	struct i2c_dev *i2c_dev;
-	int retval;
+	struct device *dev;
 
 	i2c_dev = get_free_i2c_dev(adap);
 	if (IS_ERR(i2c_dev))
@@ -434,21 +427,20 @@ static int i2cdev_attach_adapter(struct i2c_adapter *adap)
 	/* register this i2c device with the driver core */
 	i2c_dev->adap = adap;
 	if (adap->dev.parent == &platform_bus)
-		i2c_dev->class_dev.dev = &adap->dev;
+		dev = &adap->dev;
 	else
-		i2c_dev->class_dev.dev = adap->dev.parent;
-	i2c_dev->class_dev.class = &i2c_dev_class;
-	i2c_dev->class_dev.devt = MKDEV(I2C_MAJOR, i2c_dev->minor);
-	snprintf(i2c_dev->class_dev.class_id, BUS_ID_SIZE, "i2c-%d", i2c_dev->minor);
-	retval = class_device_register(&i2c_dev->class_dev);
-	if (retval)
+		dev = adap->dev.parent;
+	i2c_dev->class_dev = class_device_create(i2c_dev_class, NULL,
+						 MKDEV(I2C_MAJOR, i2c_dev->minor),
+						 dev, "i2c-%d", i2c_dev->minor);
+	if (!i2c_dev->class_dev)
 		goto error;
-	class_device_create_file(&i2c_dev->class_dev, &class_device_attr_name);
+	class_device_create_file(i2c_dev->class_dev, &class_device_attr_name);
 	return 0;
 error:
 	return_i2c_dev(i2c_dev);
 	kfree(i2c_dev);
-	return retval;
+	return -ENODEV;
 }
 
 static int i2cdev_detach_adapter(struct i2c_adapter *adap)
@@ -459,10 +451,8 @@ static int i2cdev_detach_adapter(struct i2c_adapter *adap)
 	if (!i2c_dev)
 		return -ENODEV;
 
-	init_completion(&i2c_dev->released);
 	return_i2c_dev(i2c_dev);
-	class_device_unregister(&i2c_dev->class_dev);
-	wait_for_completion(&i2c_dev->released);
+	class_device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, i2c_dev->minor));
 	kfree(i2c_dev);
 
 	pr_debug("i2c-dev: adapter [%s] unregistered\n", adap->name);
@@ -474,21 +464,14 @@ static int i2cdev_detach_client(struct i2c_client *client)
 	return 0;
 }
 
-static int i2cdev_command(struct i2c_client *client, unsigned int cmd,
-                           void *arg)
-{
-	return -1;
-}
-
 static struct i2c_driver i2cdev_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "dev_driver",
+	.driver = {
+		.name	= "dev_driver",
+	},
 	.id		= I2C_DRIVERID_I2CDEV,
-	.flags		= I2C_DF_NOTIFY,
 	.attach_adapter	= i2cdev_attach_adapter,
 	.detach_adapter	= i2cdev_detach_adapter,
 	.detach_client	= i2cdev_detach_client,
-	.command	= i2cdev_command,
 };
 
 static struct i2c_client i2cdev_client_template = {
@@ -507,8 +490,8 @@ static int __init i2c_dev_init(void)
 	if (res)
 		goto out;
 
-	res = class_register(&i2c_dev_class);
-	if (res)
+	i2c_dev_class = class_create(THIS_MODULE, "i2c-dev");
+	if (IS_ERR(i2c_dev_class))
 		goto out_unreg_chrdev;
 
 	res = i2c_add_driver(&i2cdev_driver);
@@ -518,7 +501,7 @@ static int __init i2c_dev_init(void)
 	return 0;
 
 out_unreg_class:
-	class_unregister(&i2c_dev_class);
+	class_destroy(i2c_dev_class);
 out_unreg_chrdev:
 	unregister_chrdev(I2C_MAJOR, "i2c");
 out:
@@ -529,7 +512,7 @@ out:
 static void __exit i2c_dev_exit(void)
 {
 	i2c_del_driver(&i2cdev_driver);
-	class_unregister(&i2c_dev_class);
+	class_destroy(i2c_dev_class);
 	unregister_chrdev(I2C_MAJOR,"i2c");
 }
 
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index b4d7a3efb90f..d31117eb95aa 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -614,7 +614,7 @@ static void cdrom_end_request (ide_drive_t *drive, int uptodate)
 			 */
 			spin_lock_irqsave(&ide_lock, flags);
 			end_that_request_chunk(failed, 0, failed->data_len);
-			end_that_request_last(failed);
+			end_that_request_last(failed, 0);
 			spin_unlock_irqrestore(&ide_lock, flags);
 		}
 
@@ -1735,7 +1735,7 @@ end_request:
 
 	spin_lock_irqsave(&ide_lock, flags);
 	blkdev_dequeue_request(rq);
-	end_that_request_last(rq);
+	end_that_request_last(rq, 1);
 	HWGROUP(drive)->rq = NULL;
 	spin_unlock_irqrestore(&ide_lock, flags);
 	return ide_stopped;
@@ -3509,6 +3509,7 @@ static int __init ide_cdrom_init(void)
 	return driver_register(&ide_cdrom_driver.gen_driver);
 }
 
+MODULE_ALIAS("ide:*m-cdrom*");
 module_init(ide_cdrom_init);
 module_exit(ide_cdrom_exit);
 MODULE_LICENSE("GPL");
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 449522f0540c..4b441720b6ba 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -681,50 +681,9 @@ static ide_proc_entry_t idedisk_proc[] = {
 
 #endif	/* CONFIG_PROC_FS */
 
-static void idedisk_end_flush(request_queue_t *q, struct request *flush_rq)
+static void idedisk_prepare_flush(request_queue_t *q, struct request *rq)
 {
 	ide_drive_t *drive = q->queuedata;
-	struct request *rq = flush_rq->end_io_data;
-	int good_sectors = rq->hard_nr_sectors;
-	int bad_sectors;
-	sector_t sector;
-
-	if (flush_rq->errors & ABRT_ERR) {
-		printk(KERN_ERR "%s: barrier support doesn't work\n", drive->name);
-		blk_queue_ordered(drive->queue, QUEUE_ORDERED_NONE);
-		blk_queue_issue_flush_fn(drive->queue, NULL);
-		good_sectors = 0;
-	} else if (flush_rq->errors) {
-		good_sectors = 0;
-		if (blk_barrier_preflush(rq)) {
-			sector = ide_get_error_location(drive,flush_rq->buffer);
-			if ((sector >= rq->hard_sector) &&
-			    (sector < rq->hard_sector + rq->hard_nr_sectors))
-				good_sectors = sector - rq->hard_sector;
-		}
-	}
-
-	if (flush_rq->errors)
-		printk(KERN_ERR "%s: failed barrier write: "
-				"sector=%Lx(good=%d/bad=%d)\n",
-				drive->name, (unsigned long long)rq->sector,
-				good_sectors,
-				(int) (rq->hard_nr_sectors-good_sectors));
-
-	bad_sectors = rq->hard_nr_sectors - good_sectors;
-
-	if (good_sectors)
-		__ide_end_request(drive, rq, 1, good_sectors);
-	if (bad_sectors)
-		__ide_end_request(drive, rq, 0, bad_sectors);
-}
-
-static int idedisk_prepare_flush(request_queue_t *q, struct request *rq)
-{
-	ide_drive_t *drive = q->queuedata;
-
-	if (!drive->wcache)
-		return 0;
 
 	memset(rq->cmd, 0, sizeof(rq->cmd));
 
@@ -735,9 +694,8 @@ static int idedisk_prepare_flush(request_queue_t *q, struct request *rq)
 		rq->cmd[0] = WIN_FLUSH_CACHE;
 
 
-	rq->flags |= REQ_DRIVE_TASK | REQ_SOFTBARRIER;
+	rq->flags |= REQ_DRIVE_TASK;
 	rq->buffer = rq->cmd;
-	return 1;
 }
 
 static int idedisk_issue_flush(request_queue_t *q, struct gendisk *disk,
@@ -794,27 +752,64 @@ static int set_nowerr(ide_drive_t *drive, int arg)
 	return 0;
 }
 
+static void update_ordered(ide_drive_t *drive)
+{
+	struct hd_driveid *id = drive->id;
+	unsigned ordered = QUEUE_ORDERED_NONE;
+	prepare_flush_fn *prep_fn = NULL;
+	issue_flush_fn *issue_fn = NULL;
+
+	if (drive->wcache) {
+		unsigned long long capacity;
+		int barrier;
+		/*
+		 * We must avoid issuing commands a drive does not
+		 * understand or we may crash it. We check flush cache
+		 * is supported. We also check we have the LBA48 flush
+		 * cache if the drive capacity is too large. By this
+		 * time we have trimmed the drive capacity if LBA48 is
+		 * not available so we don't need to recheck that.
+		 */
+		capacity = idedisk_capacity(drive);
+		barrier = ide_id_has_flush_cache(id) &&
+			(drive->addressing == 0 || capacity <= (1ULL << 28) ||
+			 ide_id_has_flush_cache_ext(id));
+
+		printk(KERN_INFO "%s: cache flushes %ssupported\n",
+		       drive->name, barrier ? "" : "not");
+
+		if (barrier) {
+			ordered = QUEUE_ORDERED_DRAIN_FLUSH;
+			prep_fn = idedisk_prepare_flush;
+			issue_fn = idedisk_issue_flush;
+		}
+	} else
+		ordered = QUEUE_ORDERED_DRAIN;
+
+	blk_queue_ordered(drive->queue, ordered, prep_fn);
+	blk_queue_issue_flush_fn(drive->queue, issue_fn);
+}
+
 static int write_cache(ide_drive_t *drive, int arg)
 {
 	ide_task_t args;
-	int err;
-
-	if (!ide_id_has_flush_cache(drive->id))
-		return 1;
+	int err = 1;
 
-	memset(&args, 0, sizeof(ide_task_t));
-	args.tfRegister[IDE_FEATURE_OFFSET]	= (arg) ?
+	if (ide_id_has_flush_cache(drive->id)) {
+		memset(&args, 0, sizeof(ide_task_t));
+		args.tfRegister[IDE_FEATURE_OFFSET]	= (arg) ?
 			SETFEATURES_EN_WCACHE : SETFEATURES_DIS_WCACHE;
-	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_SETFEATURES;
-	args.command_type			= IDE_DRIVE_TASK_NO_DATA;
-	args.handler				= &task_no_data_intr;
+		args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_SETFEATURES;
+		args.command_type		= IDE_DRIVE_TASK_NO_DATA;
+		args.handler			= &task_no_data_intr;
+		err = ide_raw_taskfile(drive, &args, NULL);
+		if (err == 0)
+			drive->wcache = arg;
+	}
 
-	err = ide_raw_taskfile(drive, &args, NULL);
-	if (err)
-		return err;
+	update_ordered(drive);
 
-	drive->wcache = arg;
-	return 0;
+	return err;
 }
 
 static int do_idedisk_flushcache (ide_drive_t *drive)
@@ -888,7 +883,6 @@ static void idedisk_setup (ide_drive_t *drive)
 {
 	struct hd_driveid *id = drive->id;
 	unsigned long long capacity;
-	int barrier;
 
 	idedisk_add_settings(drive);
 
@@ -992,31 +986,6 @@ static void idedisk_setup (ide_drive_t *drive)
 		drive->wcache = 1;
 
 	write_cache(drive, 1);
-
-	/*
-	 * We must avoid issuing commands a drive does not understand
-	 * or we may crash it. We check flush cache is supported. We also
-	 * check we have the LBA48 flush cache if the drive capacity is
-	 * too large. By this time we have trimmed the drive capacity if
-	 * LBA48 is not available so we don't need to recheck that.
-	 */
-	barrier = 0;
-	if (ide_id_has_flush_cache(id))
-		barrier = 1;
-	if (drive->addressing == 1) {
-		/* Can't issue the correct flush ? */
-		if (capacity > (1ULL << 28) && !ide_id_has_flush_cache_ext(id))
-			barrier = 0;
-	}
-
-	printk(KERN_INFO "%s: cache flushes %ssupported\n",
-		drive->name, barrier ? "" : "not ");
-	if (barrier) {
-		blk_queue_ordered(drive->queue, QUEUE_ORDERED_FLUSH);
-		drive->queue->prepare_flush_fn = idedisk_prepare_flush;
-		drive->queue->end_flush_fn = idedisk_end_flush;
-		blk_queue_issue_flush_fn(drive->queue, idedisk_issue_flush);
-	}
 }
 
 static void ide_cacheflush_p(ide_drive_t *drive)
@@ -1271,6 +1240,7 @@ static int __init idedisk_init(void)
 	return driver_register(&idedisk_driver.gen_driver);
 }
 
+MODULE_ALIAS("ide:*m-disk*");
 module_init(idedisk_init);
 module_exit(idedisk_exit);
 MODULE_LICENSE("GPL");
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index 9e293c8063dc..fba3fffc2d66 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -2197,6 +2197,7 @@ static int __init idefloppy_init(void)
 	return driver_register(&idefloppy_driver.gen_driver);
 }
 
+MODULE_ALIAS("ide:*m-floppy*");
 module_init(idefloppy_init);
 module_exit(idefloppy_exit);
 MODULE_LICENSE("GPL");
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index ecfafcdafea4..b5dc6df8e67d 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -89,7 +89,7 @@ int __ide_end_request(ide_drive_t *drive, struct request *rq, int uptodate,
 
 		blkdev_dequeue_request(rq);
 		HWGROUP(drive)->rq = NULL;
-		end_that_request_last(rq);
+		end_that_request_last(rq, uptodate);
 		ret = 0;
 	}
 	return ret;
@@ -119,10 +119,7 @@ int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors)
 	if (!nr_sectors)
 		nr_sectors = rq->hard_cur_sectors;
 
-	if (blk_complete_barrier_rq_locked(drive->queue, rq, nr_sectors))
-		ret = rq->nr_sectors != 0;
-	else
-		ret = __ide_end_request(drive, rq, uptodate, nr_sectors);
+	ret = __ide_end_request(drive, rq, uptodate, nr_sectors);
 
 	spin_unlock_irqrestore(&ide_lock, flags);
 	return ret;
@@ -247,7 +244,7 @@ static void ide_complete_pm_request (ide_drive_t *drive, struct request *rq)
 	}
 	blkdev_dequeue_request(rq);
 	HWGROUP(drive)->rq = NULL;
-	end_that_request_last(rq);
+	end_that_request_last(rq, 1);
 	spin_unlock_irqrestore(&ide_lock, flags);
 }
 
@@ -379,7 +376,7 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
 	blkdev_dequeue_request(rq);
 	HWGROUP(drive)->rq = NULL;
 	rq->errors = err;
-	end_that_request_last(rq);
+	end_that_request_last(rq, !rq->errors);
 	spin_unlock_irqrestore(&ide_lock, flags);
 }
 
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index 7d7944ed4158..fab9b2b02504 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -4947,6 +4947,7 @@ out:
 	return error;
 }
 
+MODULE_ALIAS("ide:*m-tape*");
 module_init(idetape_init);
 module_exit(idetape_exit);
 MODULE_ALIAS_CHARDEV_MAJOR(IDETAPE_MAJOR);
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 8af179b531c3..4b524f6b3ecd 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -1904,9 +1904,69 @@ static int ide_bus_match(struct device *dev, struct device_driver *drv)
 	return 1;
 }
 
+static char *media_string(ide_drive_t *drive)
+{
+	switch (drive->media) {
+	case ide_disk:
+		return "disk";
+	case ide_cdrom:
+		return "cdrom";
+	case ide_tape:
+		return "tape";
+	case ide_floppy:
+		return "floppy";
+	default:
+		return "UNKNOWN";
+	}
+}
+
+static ssize_t media_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	ide_drive_t *drive = to_ide_device(dev);
+	return sprintf(buf, "%s\n", media_string(drive));
+}
+
+static ssize_t drivename_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	ide_drive_t *drive = to_ide_device(dev);
+	return sprintf(buf, "%s\n", drive->name);
+}
+
+static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	ide_drive_t *drive = to_ide_device(dev);
+	return sprintf(buf, "ide:m-%s\n", media_string(drive));
+}
+
+static struct device_attribute ide_dev_attrs[] = {
+	__ATTR_RO(media),
+	__ATTR_RO(drivename),
+	__ATTR_RO(modalias),
+	__ATTR_NULL
+};
+
+static int ide_uevent(struct device *dev, char **envp, int num_envp,
+		      char *buffer, int buffer_size)
+{
+	ide_drive_t *drive = to_ide_device(dev);
+	int i = 0;
+	int length = 0;
+
+	add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
+		       "MEDIA=%s", media_string(drive));
+	add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
+		       "DRIVENAME=%s", drive->name);
+	add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
+		       "MODALIAS=ide:m-%s", media_string(drive));
+	envp[i] = NULL;
+	return 0;
+}
+
 struct bus_type ide_bus_type = {
 	.name		= "ide",
 	.match		= ide_bus_match,
+	.uevent		= ide_uevent,
+	.dev_attrs	= ide_dev_attrs,
 	.suspend	= generic_ide_suspend,
 	.resume		= generic_ide_resume,
 };
diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c
index ef79805218e4..4c2af9020905 100644
--- a/drivers/ide/legacy/ide-cs.c
+++ b/drivers/ide/legacy/ide-cs.c
@@ -88,15 +88,12 @@ typedef struct ide_info_t {
 } ide_info_t;
 
 static void ide_release(dev_link_t *);
-static int ide_event(event_t event, int priority,
-		     event_callback_args_t *args);
+static void ide_config(dev_link_t *);
+
+static void ide_detach(struct pcmcia_device *p_dev);
 
-static dev_info_t dev_info = "ide-cs";
 
-static dev_link_t *ide_attach(void);
-static void ide_detach(dev_link_t *);
 
-static dev_link_t *dev_list = NULL;
 
 /*======================================================================
 
@@ -106,18 +103,17 @@ static dev_link_t *dev_list = NULL;
 
 ======================================================================*/
 
-static dev_link_t *ide_attach(void)
+static int ide_attach(struct pcmcia_device *p_dev)
 {
     ide_info_t *info;
     dev_link_t *link;
-    client_reg_t client_reg;
-    int ret;
-    
+
     DEBUG(0, "ide_attach()\n");
 
     /* Create new ide device */
     info = kzalloc(sizeof(*info), GFP_KERNEL);
-    if (!info) return NULL;
+    if (!info)
+	return -ENOMEM;
     link = &info->link; link->priv = info;
 
     link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
@@ -128,21 +124,14 @@ static dev_link_t *ide_attach(void)
     link->conf.Attributes = CONF_ENABLE_IRQ;
     link->conf.Vcc = 50;
     link->conf.IntType = INT_MEMORY_AND_IO;
-    
-    /* Register with Card Services */
-    link->next = dev_list;
-    dev_list = link;
-    client_reg.dev_info = &dev_info;
-    client_reg.Version = 0x0210;
-    client_reg.event_callback_args.client_data = link;
-    ret = pcmcia_register_client(&link->handle, &client_reg);
-    if (ret != CS_SUCCESS) {
-	cs_error(link->handle, RegisterClient, ret);
-	ide_detach(link);
-	return NULL;
-    }
-    
-    return link;
+
+    link->handle = p_dev;
+    p_dev->instance = link;
+
+    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+    ide_config(link);
+
+    return 0;
 } /* ide_attach */
 
 /*======================================================================
@@ -154,32 +143,16 @@ static dev_link_t *ide_attach(void)
 
 ======================================================================*/
 
-static void ide_detach(dev_link_t *link)
+static void ide_detach(struct pcmcia_device *p_dev)
 {
-    dev_link_t **linkp;
-    int ret;
+    dev_link_t *link = dev_to_instance(p_dev);
 
     DEBUG(0, "ide_detach(0x%p)\n", link);
-    
-    /* Locate device structure */
-    for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
-	if (*linkp == link) break;
-    if (*linkp == NULL)
-	return;
 
     if (link->state & DEV_CONFIG)
 	ide_release(link);
-    
-    if (link->handle) {
-	ret = pcmcia_deregister_client(link->handle);
-	if (ret != CS_SUCCESS)
-	    cs_error(link->handle, DeregisterClient, ret);
-    }
-    
-    /* Unlink, free device structure */
-    *linkp = link->next;
+
     kfree(link->priv);
-    
 } /* ide_detach */
 
 static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq, struct pcmcia_device *handle)
@@ -406,6 +379,28 @@ void ide_release(dev_link_t *link)
 
 } /* ide_release */
 
+static int ide_suspend(struct pcmcia_device *dev)
+{
+	dev_link_t *link = dev_to_instance(dev);
+
+	link->state |= DEV_SUSPEND;
+	if (link->state & DEV_CONFIG)
+		pcmcia_release_configuration(link->handle);
+
+	return 0;
+}
+
+static int ide_resume(struct pcmcia_device *dev)
+{
+	dev_link_t *link = dev_to_instance(dev);
+
+	link->state &= ~DEV_SUSPEND;
+	if (DEV_OK(link))
+		pcmcia_request_configuration(link->handle, &link->conf);
+
+	return 0;
+}
+
 /*======================================================================
 
     The card status event handler.  Mostly, this schedules other
@@ -415,48 +410,15 @@ void ide_release(dev_link_t *link)
     
 ======================================================================*/
 
-int ide_event(event_t event, int priority,
-	      event_callback_args_t *args)
-{
-    dev_link_t *link = args->client_data;
-
-    DEBUG(1, "ide_event(0x%06x)\n", event);
-    
-    switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-	link->state &= ~DEV_PRESENT;
-	if (link->state & DEV_CONFIG)
-		ide_release(link);
-	break;
-    case CS_EVENT_CARD_INSERTION:
-	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-	ide_config(link);
-	break;
-    case CS_EVENT_PM_SUSPEND:
-	link->state |= DEV_SUSPEND;
-	/* Fall through... */
-    case CS_EVENT_RESET_PHYSICAL:
-	if (link->state & DEV_CONFIG)
-	    pcmcia_release_configuration(link->handle);
-	break;
-    case CS_EVENT_PM_RESUME:
-	link->state &= ~DEV_SUSPEND;
-	/* Fall through... */
-    case CS_EVENT_CARD_RESET:
-	if (DEV_OK(link))
-	    pcmcia_request_configuration(link->handle, &link->conf);
-	break;
-    }
-    return 0;
-} /* ide_event */
-
 static struct pcmcia_device_id ide_ids[] = {
 	PCMCIA_DEVICE_FUNC_ID(4),
+	PCMCIA_DEVICE_MANF_CARD(0x0007, 0x0000),	/* Hitachi */
 	PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704),
 	PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401),
 	PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000),	/* Toshiba */
 	PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d),
 	PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000),	/* Samsung */
+ 	PCMCIA_DEVICE_MANF_CARD(0x0319, 0x0000),	/* Hitachi */
 	PCMCIA_DEVICE_MANF_CARD(0x2080, 0x0001),
 	PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0200),	/* Lexar */
 	PCMCIA_DEVICE_PROD_ID123("Caravelle", "PSC-IDE ", "PSC000", 0x8c36137c, 0xd0693ab8, 0x2768a9f0),
@@ -471,6 +433,8 @@ static struct pcmcia_device_id ide_ids[] = {
 	PCMCIA_DEVICE_PROD_ID12("EXP   ", "CD-ROM", 0x0a5c52fd, 0x66536591),
 	PCMCIA_DEVICE_PROD_ID12("EXP   ", "PnPIDE", 0x0a5c52fd, 0x0c694728),
 	PCMCIA_DEVICE_PROD_ID12("FREECOM", "PCCARD-IDE", 0x5714cbf7, 0x48e0ab8e),
+	PCMCIA_DEVICE_PROD_ID12("HITACHI", "FLASH", 0xf4f43949, 0x9eb86aae),
+	PCMCIA_DEVICE_PROD_ID12("HITACHI", "microdrive", 0xf4f43949, 0xa6d76178),
 	PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753),
 	PCMCIA_DEVICE_PROD_ID12("IO DATA", "CBIDE2      ", 0x547e66dc, 0x8671043b),
 	PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDE", 0x547e66dc, 0x5c5ab149),
@@ -494,10 +458,11 @@ static struct pcmcia_driver ide_cs_driver = {
 	.drv		= {
 		.name	= "ide-cs",
 	},
-	.attach		= ide_attach,
-	.event		= ide_event,
-	.detach		= ide_detach,
+	.probe		= ide_attach,
+	.remove		= ide_detach,
 	.id_table       = ide_ids,
+	.suspend	= ide_suspend,
+	.resume		= ide_resume,
 };
 
 static int __init init_ide_cs(void)
@@ -508,7 +473,6 @@ static int __init init_ide_cs(void)
 static void __exit exit_ide_cs(void)
 {
 	pcmcia_unregister_driver(&ide_cs_driver);
-	BUG_ON(dev_list != NULL);
 }
 
 late_initcall(init_ide_cs);
diff --git a/drivers/ieee1394/.gitignore b/drivers/ieee1394/.gitignore
new file mode 100644
index 000000000000..33da10a25323
--- /dev/null
+++ b/drivers/ieee1394/.gitignore
@@ -0,0 +1 @@
+oui.c
diff --git a/drivers/ieee1394/Kconfig b/drivers/ieee1394/Kconfig
index 25103a0ef9b3..39142e2f804b 100644
--- a/drivers/ieee1394/Kconfig
+++ b/drivers/ieee1394/Kconfig
@@ -169,27 +169,4 @@ config IEEE1394_RAWIO
 	  To compile this driver as a module, say M here: the
 	  module will be called raw1394.
 
-config IEEE1394_CMP
-	tristate "IEC61883-1 Plug support"
-	depends on IEEE1394
-	help
-	  This option enables the Connection Management Procedures
-	  (IEC61883-1) driver, which implements input and output plugs.
-
-	  To compile this driver as a module, say M here: the
-	  module will be called cmp.
-
-config IEEE1394_AMDTP
-	tristate "IEC61883-6 (Audio transmission) support"
-	depends on IEEE1394 && IEEE1394_OHCI1394 && IEEE1394_CMP
-	help
-	  This option enables the Audio & Music Data Transmission Protocol
-	  (IEC61883-6) driver, which implements audio transmission over
-	  IEEE1394.
-
-	  The userspace interface is documented in amdtp.h.
-
-	  To compile this driver as a module, say M here: the
-	  module will be called amdtp.
-
 endmenu
diff --git a/drivers/ieee1394/Makefile b/drivers/ieee1394/Makefile
index e8b4d48d376e..6f53611fe255 100644
--- a/drivers/ieee1394/Makefile
+++ b/drivers/ieee1394/Makefile
@@ -14,8 +14,6 @@ obj-$(CONFIG_IEEE1394_RAWIO) += raw1394.o
 obj-$(CONFIG_IEEE1394_SBP2) += sbp2.o
 obj-$(CONFIG_IEEE1394_DV1394) += dv1394.o
 obj-$(CONFIG_IEEE1394_ETH1394) += eth1394.o
-obj-$(CONFIG_IEEE1394_AMDTP) += amdtp.o
-obj-$(CONFIG_IEEE1394_CMP) += cmp.o
 
 quiet_cmd_oui2c = OUI2C   $@
       cmd_oui2c = $(CONFIG_SHELL) $(srctree)/$(src)/oui2c.sh < $< > $@
diff --git a/drivers/ieee1394/csr1212.c b/drivers/ieee1394/csr1212.c
index 61ddd5d37eff..15773544234b 100644
--- a/drivers/ieee1394/csr1212.c
+++ b/drivers/ieee1394/csr1212.c
@@ -1261,7 +1261,7 @@ static int csr1212_parse_bus_info_block(struct csr1212_csr *csr)
 		return CSR1212_EINVAL;
 #endif
 
-	cr = CSR1212_MALLOC(sizeof(struct csr1212_cache_region));
+	cr = CSR1212_MALLOC(sizeof(*cr));
 	if (!cr)
 		return CSR1212_ENOMEM;
 
@@ -1393,8 +1393,7 @@ int csr1212_parse_keyval(struct csr1212_keyval *kv,
 	case CSR1212_KV_TYPE_LEAF:
 		if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM) {
 			kv->value.leaf.data = CSR1212_MALLOC(quads_to_bytes(kvi_len));
-			if (!kv->value.leaf.data)
-			{
+			if (!kv->value.leaf.data) {
 				ret = CSR1212_ENOMEM;
 				goto fail;
 			}
@@ -1462,7 +1461,7 @@ int _csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv)
 		cache->next = NULL;
 		csr->cache_tail = cache;
 		cache->filled_head =
-			CSR1212_MALLOC(sizeof(struct csr1212_cache_region));
+			CSR1212_MALLOC(sizeof(*cache->filled_head));
 		if (!cache->filled_head) {
 			return CSR1212_ENOMEM;
 		}
@@ -1484,7 +1483,7 @@ int _csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv)
 	/* Now seach read portions of the cache to see if it is there. */
 	for (cr = cache->filled_head; cr; cr = cr->next) {
 		if (cache_index < cr->offset_start) {
-			newcr = CSR1212_MALLOC(sizeof(struct csr1212_cache_region));
+			newcr = CSR1212_MALLOC(sizeof(*newcr));
 			if (!newcr)
 				return CSR1212_ENOMEM;
 
@@ -1508,7 +1507,7 @@ int _csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv)
 
 	if (!cr) {
 		cr = cache->filled_tail;
-		newcr = CSR1212_MALLOC(sizeof(struct csr1212_cache_region));
+		newcr = CSR1212_MALLOC(sizeof(*newcr));
 		if (!newcr)
 			return CSR1212_ENOMEM;
 
@@ -1611,15 +1610,17 @@ int csr1212_parse_csr(struct csr1212_csr *csr)
 	csr->root_kv->valid = 0;
 	csr->root_kv->next = csr->root_kv;
 	csr->root_kv->prev = csr->root_kv;
-	csr1212_get_keyval(csr, csr->root_kv);
+	ret = _csr1212_read_keyval(csr, csr->root_kv);
+	if (ret != CSR1212_SUCCESS)
+		return ret;
 
 	/* Scan through the Root directory finding all extended ROM regions
 	 * and make cache regions for them */
 	for (dentry = csr->root_kv->value.directory.dentries_head;
 	     dentry; dentry = dentry->next) {
-		if (dentry->kv->key.id == CSR1212_KV_ID_EXTENDED_ROM) {
-			csr1212_get_keyval(csr, dentry->kv);
-
+		if (dentry->kv->key.id == CSR1212_KV_ID_EXTENDED_ROM &&
+			!dentry->kv->valid) {
+			ret = _csr1212_read_keyval(csr, dentry->kv);
 			if (ret != CSR1212_SUCCESS)
 				return ret;
 		}
diff --git a/drivers/ieee1394/csr1212.h b/drivers/ieee1394/csr1212.h
index 28c5f4b726e2..cecd5871f2de 100644
--- a/drivers/ieee1394/csr1212.h
+++ b/drivers/ieee1394/csr1212.h
@@ -646,7 +646,7 @@ static inline struct csr1212_csr_rom_cache *csr1212_rom_cache_malloc(u_int32_t o
 {
 	struct csr1212_csr_rom_cache *cache;
 
-	cache = CSR1212_MALLOC(sizeof(struct csr1212_csr_rom_cache) + size);
+	cache = CSR1212_MALLOC(sizeof(*cache) + size);
 	if (!cache)
 		return NULL;
 
diff --git a/drivers/ieee1394/dma.c b/drivers/ieee1394/dma.c
index b79ddb43e746..9fb2769d9abc 100644
--- a/drivers/ieee1394/dma.c
+++ b/drivers/ieee1394/dma.c
@@ -23,7 +23,8 @@ void dma_prog_region_init(struct dma_prog_region *prog)
 	prog->bus_addr = 0;
 }
 
-int  dma_prog_region_alloc(struct dma_prog_region *prog, unsigned long n_bytes, struct pci_dev *dev)
+int dma_prog_region_alloc(struct dma_prog_region *prog, unsigned long n_bytes,
+			  struct pci_dev *dev)
 {
 	/* round up to page size */
 	n_bytes = PAGE_ALIGN(n_bytes);
@@ -32,7 +33,8 @@ int  dma_prog_region_alloc(struct dma_prog_region *prog, unsigned long n_bytes,
 
 	prog->kvirt = pci_alloc_consistent(dev, n_bytes, &prog->bus_addr);
 	if (!prog->kvirt) {
-		printk(KERN_ERR "dma_prog_region_alloc: pci_alloc_consistent() failed\n");
+		printk(KERN_ERR
+		       "dma_prog_region_alloc: pci_alloc_consistent() failed\n");
 		dma_prog_region_free(prog);
 		return -ENOMEM;
 	}
@@ -45,7 +47,8 @@ int  dma_prog_region_alloc(struct dma_prog_region *prog, unsigned long n_bytes,
 void dma_prog_region_free(struct dma_prog_region *prog)
 {
 	if (prog->kvirt) {
-		pci_free_consistent(prog->dev, prog->n_pages << PAGE_SHIFT, prog->kvirt, prog->bus_addr);
+		pci_free_consistent(prog->dev, prog->n_pages << PAGE_SHIFT,
+				    prog->kvirt, prog->bus_addr);
 	}
 
 	prog->kvirt = NULL;
@@ -65,7 +68,8 @@ void dma_region_init(struct dma_region *dma)
 	dma->sglist = NULL;
 }
 
-int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes, struct pci_dev *dev, int direction)
+int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes,
+		     struct pci_dev *dev, int direction)
 {
 	unsigned int i;
 
@@ -95,14 +99,16 @@ int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes, struct pci_d
 
 	/* fill scatter/gather list with pages */
 	for (i = 0; i < dma->n_pages; i++) {
-		unsigned long va = (unsigned long) dma->kvirt + (i << PAGE_SHIFT);
+		unsigned long va =
+		    (unsigned long)dma->kvirt + (i << PAGE_SHIFT);
 
 		dma->sglist[i].page = vmalloc_to_page((void *)va);
 		dma->sglist[i].length = PAGE_SIZE;
 	}
 
 	/* map sglist to the IOMMU */
-	dma->n_dma_pages = pci_map_sg(dev, dma->sglist, dma->n_pages, direction);
+	dma->n_dma_pages =
+	    pci_map_sg(dev, dma->sglist, dma->n_pages, direction);
 
 	if (dma->n_dma_pages == 0) {
 		printk(KERN_ERR "dma_region_alloc: pci_map_sg() failed\n");
@@ -114,7 +120,7 @@ int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes, struct pci_d
 
 	return 0;
 
-err:
+      err:
 	dma_region_free(dma);
 	return -ENOMEM;
 }
@@ -122,7 +128,8 @@ err:
 void dma_region_free(struct dma_region *dma)
 {
 	if (dma->n_dma_pages) {
-		pci_unmap_sg(dma->dev, dma->sglist, dma->n_pages, dma->direction);
+		pci_unmap_sg(dma->dev, dma->sglist, dma->n_pages,
+			     dma->direction);
 		dma->n_dma_pages = 0;
 		dma->dev = NULL;
 	}
@@ -137,7 +144,8 @@ void dma_region_free(struct dma_region *dma)
 
 /* find the scatterlist index and remaining offset corresponding to a
    given offset from the beginning of the buffer */
-static inline int dma_region_find(struct dma_region *dma, unsigned long offset, unsigned long *rem)
+static inline int dma_region_find(struct dma_region *dma, unsigned long offset,
+				  unsigned long *rem)
 {
 	int i;
 	unsigned long off = offset;
@@ -156,15 +164,18 @@ static inline int dma_region_find(struct dma_region *dma, unsigned long offset,
 	return i;
 }
 
-dma_addr_t dma_region_offset_to_bus(struct dma_region *dma, unsigned long offset)
+dma_addr_t dma_region_offset_to_bus(struct dma_region * dma,
+				    unsigned long offset)
 {
 	unsigned long rem = 0;
 
-	struct scatterlist *sg = &dma->sglist[dma_region_find(dma, offset, &rem)];
+	struct scatterlist *sg =
+	    &dma->sglist[dma_region_find(dma, offset, &rem)];
 	return sg_dma_address(sg) + rem;
 }
 
-void dma_region_sync_for_cpu(struct dma_region *dma, unsigned long offset, unsigned long len)
+void dma_region_sync_for_cpu(struct dma_region *dma, unsigned long offset,
+			     unsigned long len)
 {
 	int first, last;
 	unsigned long rem;
@@ -175,10 +186,12 @@ void dma_region_sync_for_cpu(struct dma_region *dma, unsigned long offset, unsig
 	first = dma_region_find(dma, offset, &rem);
 	last = dma_region_find(dma, offset + len - 1, &rem);
 
-	pci_dma_sync_sg_for_cpu(dma->dev, &dma->sglist[first], last - first + 1, dma->direction);
+	pci_dma_sync_sg_for_cpu(dma->dev, &dma->sglist[first], last - first + 1,
+				dma->direction);
 }
 
-void dma_region_sync_for_device(struct dma_region *dma, unsigned long offset, unsigned long len)
+void dma_region_sync_for_device(struct dma_region *dma, unsigned long offset,
+				unsigned long len)
 {
 	int first, last;
 	unsigned long rem;
@@ -189,44 +202,47 @@ void dma_region_sync_for_device(struct dma_region *dma, unsigned long offset, un
 	first = dma_region_find(dma, offset, &rem);
 	last = dma_region_find(dma, offset + len - 1, &rem);
 
-	pci_dma_sync_sg_for_device(dma->dev, &dma->sglist[first], last - first + 1, dma->direction);
+	pci_dma_sync_sg_for_device(dma->dev, &dma->sglist[first],
+				   last - first + 1, dma->direction);
 }
 
 #ifdef CONFIG_MMU
 
 /* nopage() handler for mmap access */
 
-static struct page*
-dma_region_pagefault(struct vm_area_struct *area, unsigned long address, int *type)
+static struct page *dma_region_pagefault(struct vm_area_struct *area,
+					 unsigned long address, int *type)
 {
 	unsigned long offset;
 	unsigned long kernel_virt_addr;
 	struct page *ret = NOPAGE_SIGBUS;
 
-	struct dma_region *dma = (struct dma_region*) area->vm_private_data;
+	struct dma_region *dma = (struct dma_region *)area->vm_private_data;
 
 	if (!dma->kvirt)
 		goto out;
 
-	if ( (address < (unsigned long) area->vm_start) ||
-	    (address > (unsigned long) area->vm_start + (dma->n_pages << PAGE_SHIFT)) )
+	if ((address < (unsigned long)area->vm_start) ||
+	    (address >
+	     (unsigned long)area->vm_start + (dma->n_pages << PAGE_SHIFT)))
 		goto out;
 
 	if (type)
 		*type = VM_FAULT_MINOR;
 	offset = address - area->vm_start;
-	kernel_virt_addr = (unsigned long) dma->kvirt + offset;
-	ret = vmalloc_to_page((void*) kernel_virt_addr);
+	kernel_virt_addr = (unsigned long)dma->kvirt + offset;
+	ret = vmalloc_to_page((void *)kernel_virt_addr);
 	get_page(ret);
-out:
+      out:
 	return ret;
 }
 
 static struct vm_operations_struct dma_region_vm_ops = {
-	.nopage	= dma_region_pagefault,
+	.nopage = dma_region_pagefault,
 };
 
-int dma_region_mmap(struct dma_region *dma, struct file *file, struct vm_area_struct *vma)
+int dma_region_mmap(struct dma_region *dma, struct file *file,
+		    struct vm_area_struct *vma)
 {
 	unsigned long size;
 
@@ -250,11 +266,12 @@ int dma_region_mmap(struct dma_region *dma, struct file *file, struct vm_area_st
 	return 0;
 }
 
-#else /* CONFIG_MMU */
+#else				/* CONFIG_MMU */
 
-int dma_region_mmap(struct dma_region *dma, struct file *file, struct vm_area_struct *vma)
+int dma_region_mmap(struct dma_region *dma, struct file *file,
+		    struct vm_area_struct *vma)
 {
 	return -EINVAL;
 }
 
-#endif /* CONFIG_MMU */
+#endif				/* CONFIG_MMU */
diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
index cbbbe14b8849..196db7439272 100644
--- a/drivers/ieee1394/dv1394.c
+++ b/drivers/ieee1394/dv1394.c
@@ -123,15 +123,6 @@
 
 #include "ohci1394.h"
 
-#ifndef virt_to_page
-#define virt_to_page(x) MAP_NR(x)
-#endif
-
-#ifndef vmalloc_32
-#define vmalloc_32(x) vmalloc(x)
-#endif
-
-
 /* DEBUG LEVELS:
    0 - no debugging messages
    1 - some debugging messages, but none during DMA frame transmission
@@ -2218,14 +2209,12 @@ static int dv1394_init(struct ti_ohci *ohci, enum pal_or_ntsc format, enum modes
 	unsigned long flags;
 	int i;
 
-	video = kmalloc(sizeof(struct video_card), GFP_KERNEL);
+	video = kzalloc(sizeof(*video), GFP_KERNEL);
 	if (!video) {
 		printk(KERN_ERR "dv1394: cannot allocate video_card\n");
 		goto err;
 	}
 
-	memset(video, 0, sizeof(struct video_card));
-
 	video->ohci = ohci;
 	/* lower 2 bits of id indicate which of four "plugs"
 	   per host */
diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c
index c9e92d85c893..30fa0d43a43a 100644
--- a/drivers/ieee1394/eth1394.c
+++ b/drivers/ieee1394/eth1394.c
@@ -88,9 +88,6 @@
 	printk(KERN_ERR "%s:%s[%d]: " fmt "\n", driver_name, __FUNCTION__, __LINE__, ## args)
 #define TRACE() printk(KERN_ERR "%s:%s[%d] ---- TRACE\n", driver_name, __FUNCTION__, __LINE__)
 
-static char version[] __devinitdata =
-	"$Rev: 1312 $ Ben Collins <bcollins@debian.org>";
-
 struct fragment_info {
 	struct list_head list;
 	int offset;
@@ -355,12 +352,12 @@ static int eth1394_probe(struct device *dev)
 	if (!hi)
 		return -ENOENT;
 
-	new_node = kmalloc(sizeof(struct eth1394_node_ref),
+	new_node = kmalloc(sizeof(*new_node),
 			   in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
 	if (!new_node)
 		return -ENOMEM;
 
-	node_info = kmalloc(sizeof(struct eth1394_node_info),
+	node_info = kmalloc(sizeof(*node_info),
 			    in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
 	if (!node_info) {
 		kfree(new_node);
@@ -436,12 +433,12 @@ static int eth1394_update(struct unit_directory *ud)
 	node = eth1394_find_node(&priv->ip_node_list, ud);
 
 	if (!node) {
-		node = kmalloc(sizeof(struct eth1394_node_ref),
+		node = kmalloc(sizeof(*node),
 			       in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
 		if (!node)
 			return -ENOMEM;
 
-		node_info = kmalloc(sizeof(struct eth1394_node_info),
+		node_info = kmalloc(sizeof(*node_info),
 				    in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
 		if (!node_info) {
 			kfree(node);
@@ -566,7 +563,6 @@ static void ether1394_add_host (struct hpsb_host *host)
 	struct eth1394_host_info *hi = NULL;
 	struct net_device *dev = NULL;
 	struct eth1394_priv *priv;
-	static int version_printed = 0;
 	u64 fifo_addr;
 
 	if (!(host->config_roms & HPSB_CONFIG_ROM_ENTRY_IP1394))
@@ -581,9 +577,6 @@ static void ether1394_add_host (struct hpsb_host *host)
 	if (fifo_addr == ~0ULL)
 		goto out;
 
-	if (version_printed++ == 0)
-		ETH1394_PRINT_G (KERN_INFO, "%s\n", version);
-
 	/* We should really have our own alloc_hpsbdev() function in
 	 * net_init.c instead of calling the one for ethernet then hijacking
 	 * it for ourselves.  That way we'd be a real networking device. */
@@ -1021,7 +1014,7 @@ static inline int new_fragment(struct list_head *frag_info, int offset, int len)
 		}
 	}
 
-	new = kmalloc(sizeof(struct fragment_info), GFP_ATOMIC);
+	new = kmalloc(sizeof(*new), GFP_ATOMIC);
 	if (!new)
 		return -ENOMEM;
 
@@ -1040,7 +1033,7 @@ static inline int new_partial_datagram(struct net_device *dev,
 {
 	struct partial_datagram *new;
 
-	new = kmalloc(sizeof(struct partial_datagram), GFP_ATOMIC);
+	new = kmalloc(sizeof(*new), GFP_ATOMIC);
 	if (!new)
 		return -ENOMEM;
 
@@ -1768,7 +1761,6 @@ fail:
 static void ether1394_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
 	strcpy (info->driver, driver_name);
-	strcpy (info->version, "$Rev: 1312 $");
 	/* FIXME XXX provide sane businfo */
 	strcpy (info->bus_info, "ieee1394");
 }
diff --git a/drivers/ieee1394/highlevel.c b/drivers/ieee1394/highlevel.c
index 997e1bf6297f..734b121a0554 100644
--- a/drivers/ieee1394/highlevel.c
+++ b/drivers/ieee1394/highlevel.c
@@ -101,12 +101,10 @@ void *hpsb_create_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host,
 		return NULL;
 	}
 
-	hi = kmalloc(sizeof(*hi) + data_size, GFP_ATOMIC);
+	hi = kzalloc(sizeof(*hi) + data_size, GFP_ATOMIC);
 	if (!hi)
 		return NULL;
 
-	memset(hi, 0, sizeof(*hi) + data_size);
-
 	if (data_size) {
 		data = hi->data = hi + 1;
 		hi->size = data_size;
@@ -326,11 +324,9 @@ u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl,
 		return retval;
 	}
 
-	as = (struct hpsb_address_serve *)
-		kmalloc(sizeof(struct hpsb_address_serve), GFP_KERNEL);
-	if (as == NULL) {
+	as = kmalloc(sizeof(*as), GFP_KERNEL);
+	if (!as)
 		return retval;
-	}
 
 	INIT_LIST_HEAD(&as->host_list);
 	INIT_LIST_HEAD(&as->hl_list);
@@ -383,11 +379,9 @@ int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
                 return 0;
         }
 
-        as = (struct hpsb_address_serve *)
-                kmalloc(sizeof(struct hpsb_address_serve), GFP_ATOMIC);
-        if (as == NULL) {
-                return 0;
-        }
+	as = kmalloc(sizeof(*as), GFP_ATOMIC);
+	if (!as)
+		return 0;
 
         INIT_LIST_HEAD(&as->host_list);
         INIT_LIST_HEAD(&as->hl_list);
diff --git a/drivers/ieee1394/hosts.c b/drivers/ieee1394/hosts.c
index aeeaeb670d03..ba09741fc826 100644
--- a/drivers/ieee1394/hosts.c
+++ b/drivers/ieee1394/hosts.c
@@ -61,12 +61,12 @@ static void delayed_reset_bus(void * __reset_info)
 
 static int dummy_transmit_packet(struct hpsb_host *h, struct hpsb_packet *p)
 {
-        return 0;
+	return 0;
 }
 
 static int dummy_devctl(struct hpsb_host *h, enum devctl_cmd c, int arg)
 {
-        return -1;
+	return -1;
 }
 
 static int dummy_isoctl(struct hpsb_iso *iso, enum isoctl_cmd command, unsigned long arg)
@@ -75,9 +75,9 @@ static int dummy_isoctl(struct hpsb_iso *iso, enum isoctl_cmd command, unsigned
 }
 
 static struct hpsb_host_driver dummy_driver = {
-        .transmit_packet = dummy_transmit_packet,
-        .devctl =          dummy_devctl,
-	.isoctl =          dummy_isoctl
+	.transmit_packet = dummy_transmit_packet,
+	.devctl =	   dummy_devctl,
+	.isoctl =	   dummy_isoctl
 };
 
 static int alloc_hostnum_cb(struct hpsb_host *host, void *__data)
@@ -110,13 +110,13 @@ static DECLARE_MUTEX(host_num_alloc);
 struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
 				  struct device *dev)
 {
-        struct hpsb_host *h;
+	struct hpsb_host *h;
 	int i;
 	int hostnum = 0;
 
-        h = kmalloc(sizeof(struct hpsb_host) + extra, SLAB_KERNEL);
-        if (!h) return NULL;
-        memset(h, 0, sizeof(struct hpsb_host) + extra);
+	h = kzalloc(sizeof(*h) + extra, SLAB_KERNEL);
+	if (!h)
+		return NULL;
 
 	h->csr.rom = csr1212_create_csr(&csr_bus_ops, CSR_BUS_INFO_SIZE, h);
 	if (!h->csr.rom) {
@@ -125,7 +125,7 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
 	}
 
 	h->hostdata = h + 1;
-        h->driver = drv;
+	h->driver = drv;
 
 	skb_queue_head_init(&h->pending_packet_queue);
 	INIT_LIST_HEAD(&h->addr_space);
@@ -145,8 +145,8 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
 	h->timeout.function = abort_timedouts;
 	h->timeout_interval = HZ / 20; // 50ms by default
 
-        h->topology_map = h->csr.topology_map + 3;
-        h->speed_map = (u8 *)(h->csr.speed_map + 2);
+	h->topology_map = h->csr.topology_map + 3;
+	h->speed_map = (u8 *)(h->csr.speed_map + 2);
 
 	down(&host_num_alloc);
 
@@ -186,14 +186,14 @@ int hpsb_add_host(struct hpsb_host *host)
 
 void hpsb_remove_host(struct hpsb_host *host)
 {
-        host->is_shutdown = 1;
+	host->is_shutdown = 1;
 
 	cancel_delayed_work(&host->delayed_reset);
 	flush_scheduled_work();
 
-        host->driver = &dummy_driver;
+	host->driver = &dummy_driver;
 
-        highlevel_remove_host(host);
+	highlevel_remove_host(host);
 
 	hpsb_remove_extra_config_roms(host);
 
diff --git a/drivers/ieee1394/hosts.h b/drivers/ieee1394/hosts.h
index ae9b02cc013f..07d188ca8495 100644
--- a/drivers/ieee1394/hosts.h
+++ b/drivers/ieee1394/hosts.h
@@ -17,47 +17,47 @@ struct hpsb_packet;
 struct hpsb_iso;
 
 struct hpsb_host {
-        struct list_head host_list;
+	struct list_head host_list;
 
-        void *hostdata;
+	void *hostdata;
 
-        atomic_t generation;
+	atomic_t generation;
 
 	struct sk_buff_head pending_packet_queue;
 
 	struct timer_list timeout;
 	unsigned long timeout_interval;
 
-        unsigned char iso_listen_count[64];
+	unsigned char iso_listen_count[64];
 
-        int node_count; /* number of identified nodes on this bus */
-        int selfid_count; /* total number of SelfIDs received */
+	int node_count; /* number of identified nodes on this bus */
+	int selfid_count; /* total number of SelfIDs received */
 	int nodes_active; /* number of nodes that are actually active */
 
-        nodeid_t node_id; /* node ID of this host */
-        nodeid_t irm_id; /* ID of this bus' isochronous resource manager */
-        nodeid_t busmgr_id; /* ID of this bus' bus manager */
+	nodeid_t node_id; /* node ID of this host */
+	nodeid_t irm_id; /* ID of this bus' isochronous resource manager */
+	nodeid_t busmgr_id; /* ID of this bus' bus manager */
 
-        /* this nodes state */
-        unsigned in_bus_reset:1;
-        unsigned is_shutdown:1;
+	/* this nodes state */
+	unsigned in_bus_reset:1;
+	unsigned is_shutdown:1;
 	unsigned resume_packet_sent:1;
 
-        /* this nodes' duties on the bus */
-        unsigned is_root:1;
-        unsigned is_cycmst:1;
-        unsigned is_irm:1;
-        unsigned is_busmgr:1;
+	/* this nodes' duties on the bus */
+	unsigned is_root:1;
+	unsigned is_cycmst:1;
+	unsigned is_irm:1;
+	unsigned is_busmgr:1;
 
-        int reset_retries;
-        quadlet_t *topology_map;
-        u8 *speed_map;
-        struct csr_control csr;
+	int reset_retries;
+	quadlet_t *topology_map;
+	u8 *speed_map;
+	struct csr_control csr;
 
 	/* Per node tlabel pool allocation */
 	struct hpsb_tlabel_pool tpool[64];
 
-        struct hpsb_host_driver *driver;
+	struct hpsb_host_driver *driver;
 
 	struct pci_dev *pdev;
 
@@ -77,34 +77,34 @@ struct hpsb_host {
 
 
 enum devctl_cmd {
-        /* Host is requested to reset its bus and cancel all outstanding async
-         * requests.  If arg == 1, it shall also attempt to become root on the
-         * bus.  Return void. */
-        RESET_BUS,
-
-        /* Arg is void, return value is the hardware cycle counter value. */
-        GET_CYCLE_COUNTER,
-
-        /* Set the hardware cycle counter to the value in arg, return void.
-         * FIXME - setting is probably not required. */
-        SET_CYCLE_COUNTER,
-
-        /* Configure hardware for new bus ID in arg, return void. */
-        SET_BUS_ID,
-
-        /* If arg true, start sending cycle start packets, stop if arg == 0.
-         * Return void. */
-        ACT_CYCLE_MASTER,
-
-        /* Cancel all outstanding async requests without resetting the bus.
-         * Return void. */
-        CANCEL_REQUESTS,
-
-        /* Start or stop receiving isochronous channel in arg.  Return void.
-         * This acts as an optimization hint, hosts are not required not to
-         * listen on unrequested channels. */
-        ISO_LISTEN_CHANNEL,
-        ISO_UNLISTEN_CHANNEL
+	/* Host is requested to reset its bus and cancel all outstanding async
+	 * requests.  If arg == 1, it shall also attempt to become root on the
+	 * bus.  Return void. */
+	RESET_BUS,
+
+	/* Arg is void, return value is the hardware cycle counter value. */
+	GET_CYCLE_COUNTER,
+
+	/* Set the hardware cycle counter to the value in arg, return void.
+	 * FIXME - setting is probably not required. */
+	SET_CYCLE_COUNTER,
+
+	/* Configure hardware for new bus ID in arg, return void. */
+	SET_BUS_ID,
+
+	/* If arg true, start sending cycle start packets, stop if arg == 0.
+	 * Return void. */
+	ACT_CYCLE_MASTER,
+
+	/* Cancel all outstanding async requests without resetting the bus.
+	 * Return void. */
+	CANCEL_REQUESTS,
+
+	/* Start or stop receiving isochronous channel in arg.  Return void.
+	 * This acts as an optimization hint, hosts are not required not to
+	 * listen on unrequested channels. */
+	ISO_LISTEN_CHANNEL,
+	ISO_UNLISTEN_CHANNEL
 };
 
 enum isoctl_cmd {
@@ -135,13 +135,13 @@ enum isoctl_cmd {
 };
 
 enum reset_types {
-        /* 166 microsecond reset -- only type of reset available on
-           non-1394a capable controllers */
-        LONG_RESET,
+	/* 166 microsecond reset -- only type of reset available on
+	   non-1394a capable controllers */
+	LONG_RESET,
 
-        /* Short (arbitrated) reset -- only available on 1394a capable
-           controllers */
-        SHORT_RESET,
+	/* Short (arbitrated) reset -- only available on 1394a capable
+	   controllers */
+	SHORT_RESET,
 
 	/* Variants that set force_root before issueing the bus reset */
 	LONG_RESET_FORCE_ROOT, SHORT_RESET_FORCE_ROOT,
@@ -159,22 +159,22 @@ struct hpsb_host_driver {
 	 * reads to the ConfigROM on its own. */
 	void (*set_hw_config_rom) (struct hpsb_host *host, quadlet_t *config_rom);
 
-        /* This function shall implement packet transmission based on
-         * packet->type.  It shall CRC both parts of the packet (unless
-         * packet->type == raw) and do byte-swapping as necessary or instruct
-         * the hardware to do so.  It can return immediately after the packet
-         * was queued for sending.  After sending, hpsb_sent_packet() has to be
-         * called.  Return 0 on success, negative errno on failure.
-         * NOTE: The function must be callable in interrupt context.
-         */
-        int (*transmit_packet) (struct hpsb_host *host,
-                                struct hpsb_packet *packet);
-
-        /* This function requests miscellanous services from the driver, see
-         * above for command codes and expected actions.  Return -1 for unknown
-         * command, though that should never happen.
-         */
-        int (*devctl) (struct hpsb_host *host, enum devctl_cmd command, int arg);
+	/* This function shall implement packet transmission based on
+	 * packet->type.  It shall CRC both parts of the packet (unless
+	 * packet->type == raw) and do byte-swapping as necessary or instruct
+	 * the hardware to do so.  It can return immediately after the packet
+	 * was queued for sending.  After sending, hpsb_sent_packet() has to be
+	 * called.  Return 0 on success, negative errno on failure.
+	 * NOTE: The function must be callable in interrupt context.
+	 */
+	int (*transmit_packet) (struct hpsb_host *host,
+				struct hpsb_packet *packet);
+
+	/* This function requests miscellanous services from the driver, see
+	 * above for command codes and expected actions.  Return -1 for unknown
+	 * command, though that should never happen.
+	 */
+	int (*devctl) (struct hpsb_host *host, enum devctl_cmd command, int arg);
 
 	 /* ISO transmission/reception functions. Return 0 on success, -1
 	  * (or -EXXX errno code) on failure. If the low-level driver does not
@@ -182,15 +182,15 @@ struct hpsb_host_driver {
 	  */
 	int (*isoctl) (struct hpsb_iso *iso, enum isoctl_cmd command, unsigned long arg);
 
-        /* This function is mainly to redirect local CSR reads/locks to the iso
-         * management registers (bus manager id, bandwidth available, channels
-         * available) to the hardware registers in OHCI.  reg is 0,1,2,3 for bus
-         * mgr, bwdth avail, ch avail hi, ch avail lo respectively (the same ids
-         * as OHCI uses).  data and compare are the new data and expected data
-         * respectively, return value is the old value.
-         */
-        quadlet_t (*hw_csr_reg) (struct hpsb_host *host, int reg,
-                                 quadlet_t data, quadlet_t compare);
+	/* This function is mainly to redirect local CSR reads/locks to the iso
+	 * management registers (bus manager id, bandwidth available, channels
+	 * available) to the hardware registers in OHCI.  reg is 0,1,2,3 for bus
+	 * mgr, bwdth avail, ch avail hi, ch avail lo respectively (the same ids
+	 * as OHCI uses).  data and compare are the new data and expected data
+	 * respectively, return value is the old value.
+	 */
+	quadlet_t (*hw_csr_reg) (struct hpsb_host *host, int reg,
+				 quadlet_t data, quadlet_t compare);
 };
 
 
diff --git a/drivers/ieee1394/ieee1394-ioctl.h b/drivers/ieee1394/ieee1394-ioctl.h
index f92b566363d5..156703986348 100644
--- a/drivers/ieee1394/ieee1394-ioctl.h
+++ b/drivers/ieee1394/ieee1394-ioctl.h
@@ -7,14 +7,6 @@
 #include <linux/ioctl.h>
 #include <linux/types.h>
 
-
-/* AMDTP Gets 6 */
-#define AMDTP_IOC_CHANNEL	_IOW('#', 0x00, struct amdtp_ioctl)
-#define AMDTP_IOC_PLUG		_IOW('#', 0x01, struct amdtp_ioctl)
-#define AMDTP_IOC_PING		_IOW('#', 0x02, struct amdtp_ioctl)
-#define AMDTP_IOC_ZAP		_IO ('#', 0x03)
-
-
 /* DV1394 Gets 10 */
 
 /* Get the driver ready to transmit video.  pass a struct dv1394_init* as
diff --git a/drivers/ieee1394/ieee1394.h b/drivers/ieee1394/ieee1394.h
index b634a9bb365c..936d776de00a 100644
--- a/drivers/ieee1394/ieee1394.h
+++ b/drivers/ieee1394/ieee1394.h
@@ -62,6 +62,7 @@
 extern const char *hpsb_speedto_str[];
 
 
+/* 1394a cable PHY packets */
 #define SELFID_PWRCL_NO_POWER    0x0
 #define SELFID_PWRCL_PROVIDE_15W 0x1
 #define SELFID_PWRCL_PROVIDE_30W 0x2
@@ -76,8 +77,24 @@ extern const char *hpsb_speedto_str[];
 #define SELFID_PORT_NCONN        0x1
 #define SELFID_PORT_NONE         0x0
 
+#define PHYPACKET_LINKON			0x40000000
+#define PHYPACKET_PHYCONFIG_R			0x00800000
+#define PHYPACKET_PHYCONFIG_T			0x00400000
+#define EXTPHYPACKET_TYPE_PING			0x00000000
+#define EXTPHYPACKET_TYPE_REMOTEACCESS_BASE	0x00040000
+#define EXTPHYPACKET_TYPE_REMOTEACCESS_PAGED	0x00140000
+#define EXTPHYPACKET_TYPE_REMOTEREPLY_BASE	0x000C0000
+#define EXTPHYPACKET_TYPE_REMOTEREPLY_PAGED	0x001C0000
+#define EXTPHYPACKET_TYPE_REMOTECOMMAND		0x00200000
+#define EXTPHYPACKET_TYPE_REMOTECONFIRMATION	0x00280000
+#define EXTPHYPACKET_TYPE_RESUME		0x003C0000
 
-/* 1394a PHY bitmasks */
+#define EXTPHYPACKET_TYPEMASK			0xC0FC0000
+
+#define PHYPACKET_PORT_SHIFT     24
+#define PHYPACKET_GAPCOUNT_SHIFT 16
+
+/* 1394a PHY register map bitmasks */
 #define PHY_00_PHYSICAL_ID       0xFC
 #define PHY_00_R                 0x02 /* Root */
 #define PHY_00_PS                0x01 /* Power Status*/
diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c
index 32a1e016c85e..25ef5a86f5f0 100644
--- a/drivers/ieee1394/ieee1394_core.c
+++ b/drivers/ieee1394/ieee1394_core.c
@@ -179,34 +179,34 @@ void hpsb_free_packet(struct hpsb_packet *packet)
 
 int hpsb_reset_bus(struct hpsb_host *host, int type)
 {
-        if (!host->in_bus_reset) {
-                host->driver->devctl(host, RESET_BUS, type);
-                return 0;
-        } else {
-                return 1;
-        }
+	if (!host->in_bus_reset) {
+		host->driver->devctl(host, RESET_BUS, type);
+		return 0;
+	} else {
+		return 1;
+	}
 }
 
 
 int hpsb_bus_reset(struct hpsb_host *host)
 {
-        if (host->in_bus_reset) {
-                HPSB_NOTICE("%s called while bus reset already in progress",
+	if (host->in_bus_reset) {
+		HPSB_NOTICE("%s called while bus reset already in progress",
 			    __FUNCTION__);
-                return 1;
-        }
+		return 1;
+	}
 
-        abort_requests(host);
-        host->in_bus_reset = 1;
-        host->irm_id = -1;
+	abort_requests(host);
+	host->in_bus_reset = 1;
+	host->irm_id = -1;
 	host->is_irm = 0;
-        host->busmgr_id = -1;
+	host->busmgr_id = -1;
 	host->is_busmgr = 0;
 	host->is_cycmst = 0;
-        host->node_count = 0;
-        host->selfid_count = 0;
+	host->node_count = 0;
+	host->selfid_count = 0;
 
-        return 0;
+	return 0;
 }
 
 
@@ -216,150 +216,156 @@ int hpsb_bus_reset(struct hpsb_host *host)
  */
 static int check_selfids(struct hpsb_host *host)
 {
-        int nodeid = -1;
-        int rest_of_selfids = host->selfid_count;
-        struct selfid *sid = (struct selfid *)host->topology_map;
-        struct ext_selfid *esid;
-        int esid_seq = 23;
+	int nodeid = -1;
+	int rest_of_selfids = host->selfid_count;
+	struct selfid *sid = (struct selfid *)host->topology_map;
+	struct ext_selfid *esid;
+	int esid_seq = 23;
 
 	host->nodes_active = 0;
 
-        while (rest_of_selfids--) {
-                if (!sid->extended) {
-                        nodeid++;
-                        esid_seq = 0;
+	while (rest_of_selfids--) {
+		if (!sid->extended) {
+			nodeid++;
+			esid_seq = 0;
 
-                        if (sid->phy_id != nodeid) {
-                                HPSB_INFO("SelfIDs failed monotony check with "
-                                          "%d", sid->phy_id);
-                                return 0;
-                        }
+			if (sid->phy_id != nodeid) {
+				HPSB_INFO("SelfIDs failed monotony check with "
+					  "%d", sid->phy_id);
+				return 0;
+			}
 
 			if (sid->link_active) {
 				host->nodes_active++;
 				if (sid->contender)
 					host->irm_id = LOCAL_BUS | sid->phy_id;
 			}
-                } else {
-                        esid = (struct ext_selfid *)sid;
-
-                        if ((esid->phy_id != nodeid)
-                            || (esid->seq_nr != esid_seq)) {
-                                HPSB_INFO("SelfIDs failed monotony check with "
-                                          "%d/%d", esid->phy_id, esid->seq_nr);
-                                return 0;
-                        }
-                        esid_seq++;
-                }
-                sid++;
-        }
-
-        esid = (struct ext_selfid *)(sid - 1);
-        while (esid->extended) {
-                if ((esid->porta == 0x2) || (esid->portb == 0x2)
-                    || (esid->portc == 0x2) || (esid->portd == 0x2)
-                    || (esid->porte == 0x2) || (esid->portf == 0x2)
-                    || (esid->portg == 0x2) || (esid->porth == 0x2)) {
+		} else {
+			esid = (struct ext_selfid *)sid;
+
+			if ((esid->phy_id != nodeid)
+			    || (esid->seq_nr != esid_seq)) {
+				HPSB_INFO("SelfIDs failed monotony check with "
+					  "%d/%d", esid->phy_id, esid->seq_nr);
+				return 0;
+			}
+			esid_seq++;
+		}
+		sid++;
+	}
+
+	esid = (struct ext_selfid *)(sid - 1);
+	while (esid->extended) {
+		if ((esid->porta == SELFID_PORT_PARENT) ||
+		    (esid->portb == SELFID_PORT_PARENT) ||
+		    (esid->portc == SELFID_PORT_PARENT) ||
+		    (esid->portd == SELFID_PORT_PARENT) ||
+		    (esid->porte == SELFID_PORT_PARENT) ||
+		    (esid->portf == SELFID_PORT_PARENT) ||
+		    (esid->portg == SELFID_PORT_PARENT) ||
+		    (esid->porth == SELFID_PORT_PARENT)) {
 			HPSB_INFO("SelfIDs failed root check on "
 				  "extended SelfID");
 			return 0;
-                }
-                esid--;
-        }
+		}
+		esid--;
+	}
 
-        sid = (struct selfid *)esid;
-        if ((sid->port0 == 0x2) || (sid->port1 == 0x2) || (sid->port2 == 0x2)) {
+	sid = (struct selfid *)esid;
+	if ((sid->port0 == SELFID_PORT_PARENT) ||
+	    (sid->port1 == SELFID_PORT_PARENT) ||
+	    (sid->port2 == SELFID_PORT_PARENT)) {
 		HPSB_INFO("SelfIDs failed root check");
 		return 0;
-        }
+	}
 
 	host->node_count = nodeid + 1;
-        return 1;
+	return 1;
 }
 
 static void build_speed_map(struct hpsb_host *host, int nodecount)
 {
 	u8 speedcap[nodecount];
 	u8 cldcnt[nodecount];
-        u8 *map = host->speed_map;
-        struct selfid *sid;
-        struct ext_selfid *esid;
-        int i, j, n;
-
-        for (i = 0; i < (nodecount * 64); i += 64) {
-                for (j = 0; j < nodecount; j++) {
-                        map[i+j] = IEEE1394_SPEED_MAX;
-                }
-        }
-
-        for (i = 0; i < nodecount; i++) {
-                cldcnt[i] = 0;
-        }
-
-        /* find direct children count and speed */
-        for (sid = (struct selfid *)&host->topology_map[host->selfid_count-1],
-                     n = nodecount - 1;
-             (void *)sid >= (void *)host->topology_map; sid--) {
-                if (sid->extended) {
-                        esid = (struct ext_selfid *)sid;
-
-                        if (esid->porta == 0x3) cldcnt[n]++;
-                        if (esid->portb == 0x3) cldcnt[n]++;
-                        if (esid->portc == 0x3) cldcnt[n]++;
-                        if (esid->portd == 0x3) cldcnt[n]++;
-                        if (esid->porte == 0x3) cldcnt[n]++;
-                        if (esid->portf == 0x3) cldcnt[n]++;
-                        if (esid->portg == 0x3) cldcnt[n]++;
-                        if (esid->porth == 0x3) cldcnt[n]++;
+	u8 *map = host->speed_map;
+	struct selfid *sid;
+	struct ext_selfid *esid;
+	int i, j, n;
+
+	for (i = 0; i < (nodecount * 64); i += 64) {
+		for (j = 0; j < nodecount; j++) {
+			map[i+j] = IEEE1394_SPEED_MAX;
+		}
+	}
+
+	for (i = 0; i < nodecount; i++) {
+		cldcnt[i] = 0;
+	}
+
+	/* find direct children count and speed */
+	for (sid = (struct selfid *)&host->topology_map[host->selfid_count-1],
+		     n = nodecount - 1;
+	     (void *)sid >= (void *)host->topology_map; sid--) {
+		if (sid->extended) {
+			esid = (struct ext_selfid *)sid;
+
+			if (esid->porta == SELFID_PORT_CHILD) cldcnt[n]++;
+			if (esid->portb == SELFID_PORT_CHILD) cldcnt[n]++;
+			if (esid->portc == SELFID_PORT_CHILD) cldcnt[n]++;
+			if (esid->portd == SELFID_PORT_CHILD) cldcnt[n]++;
+			if (esid->porte == SELFID_PORT_CHILD) cldcnt[n]++;
+			if (esid->portf == SELFID_PORT_CHILD) cldcnt[n]++;
+			if (esid->portg == SELFID_PORT_CHILD) cldcnt[n]++;
+			if (esid->porth == SELFID_PORT_CHILD) cldcnt[n]++;
                 } else {
-                        if (sid->port0 == 0x3) cldcnt[n]++;
-                        if (sid->port1 == 0x3) cldcnt[n]++;
-                        if (sid->port2 == 0x3) cldcnt[n]++;
-
-                        speedcap[n] = sid->speed;
-                        n--;
-                }
-        }
-
-        /* set self mapping */
-        for (i = 0; i < nodecount; i++) {
-                map[64*i + i] = speedcap[i];
-        }
-
-        /* fix up direct children count to total children count;
-         * also fix up speedcaps for sibling and parent communication */
-        for (i = 1; i < nodecount; i++) {
-                for (j = cldcnt[i], n = i - 1; j > 0; j--) {
-                        cldcnt[i] += cldcnt[n];
-                        speedcap[n] = min(speedcap[n], speedcap[i]);
-                        n -= cldcnt[n] + 1;
-                }
-        }
-
-        for (n = 0; n < nodecount; n++) {
-                for (i = n - cldcnt[n]; i <= n; i++) {
-                        for (j = 0; j < (n - cldcnt[n]); j++) {
-                                map[j*64 + i] = map[i*64 + j] =
-                                        min(map[i*64 + j], speedcap[n]);
-                        }
-                        for (j = n + 1; j < nodecount; j++) {
-                                map[j*64 + i] = map[i*64 + j] =
-                                        min(map[i*64 + j], speedcap[n]);
-                        }
-                }
-        }
+			if (sid->port0 == SELFID_PORT_CHILD) cldcnt[n]++;
+			if (sid->port1 == SELFID_PORT_CHILD) cldcnt[n]++;
+			if (sid->port2 == SELFID_PORT_CHILD) cldcnt[n]++;
+
+			speedcap[n] = sid->speed;
+			n--;
+		}
+	}
+
+	/* set self mapping */
+	for (i = 0; i < nodecount; i++) {
+		map[64*i + i] = speedcap[i];
+	}
+
+	/* fix up direct children count to total children count;
+	 * also fix up speedcaps for sibling and parent communication */
+	for (i = 1; i < nodecount; i++) {
+		for (j = cldcnt[i], n = i - 1; j > 0; j--) {
+			cldcnt[i] += cldcnt[n];
+			speedcap[n] = min(speedcap[n], speedcap[i]);
+			n -= cldcnt[n] + 1;
+		}
+	}
+
+	for (n = 0; n < nodecount; n++) {
+		for (i = n - cldcnt[n]; i <= n; i++) {
+			for (j = 0; j < (n - cldcnt[n]); j++) {
+				map[j*64 + i] = map[i*64 + j] =
+					min(map[i*64 + j], speedcap[n]);
+			}
+			for (j = n + 1; j < nodecount; j++) {
+				map[j*64 + i] = map[i*64 + j] =
+					min(map[i*64 + j], speedcap[n]);
+			}
+		}
+	}
 }
 
 
 void hpsb_selfid_received(struct hpsb_host *host, quadlet_t sid)
 {
-        if (host->in_bus_reset) {
-                HPSB_VERBOSE("Including SelfID 0x%x", sid);
-                host->topology_map[host->selfid_count++] = sid;
-        } else {
-                HPSB_NOTICE("Spurious SelfID packet (0x%08x) received from bus %d",
+	if (host->in_bus_reset) {
+		HPSB_VERBOSE("Including SelfID 0x%x", sid);
+		host->topology_map[host->selfid_count++] = sid;
+	} else {
+		HPSB_NOTICE("Spurious SelfID packet (0x%08x) received from bus %d",
 			    sid, NODEID_TO_BUS(host->node_id));
-        }
+	}
 }
 
 void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot)
@@ -367,50 +373,50 @@ void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot)
 	if (!host->in_bus_reset)
 		HPSB_NOTICE("SelfID completion called outside of bus reset!");
 
-        host->node_id = LOCAL_BUS | phyid;
-        host->is_root = isroot;
+	host->node_id = LOCAL_BUS | phyid;
+	host->is_root = isroot;
 
-        if (!check_selfids(host)) {
-                if (host->reset_retries++ < 20) {
-                        /* selfid stage did not complete without error */
-                        HPSB_NOTICE("Error in SelfID stage, resetting");
+	if (!check_selfids(host)) {
+		if (host->reset_retries++ < 20) {
+			/* selfid stage did not complete without error */
+			HPSB_NOTICE("Error in SelfID stage, resetting");
 			host->in_bus_reset = 0;
 			/* this should work from ohci1394 now... */
-                        hpsb_reset_bus(host, LONG_RESET);
-                        return;
-                } else {
-                        HPSB_NOTICE("Stopping out-of-control reset loop");
-                        HPSB_NOTICE("Warning - topology map and speed map will not be valid");
+			hpsb_reset_bus(host, LONG_RESET);
+			return;
+		} else {
+			HPSB_NOTICE("Stopping out-of-control reset loop");
+			HPSB_NOTICE("Warning - topology map and speed map will not be valid");
 			host->reset_retries = 0;
-                }
-        } else {
+		}
+	} else {
 		host->reset_retries = 0;
-                build_speed_map(host, host->node_count);
-        }
+		build_speed_map(host, host->node_count);
+	}
 
 	HPSB_VERBOSE("selfid_complete called with successful SelfID stage "
 		     "... irm_id: 0x%X node_id: 0x%X",host->irm_id,host->node_id);
 
-        /* irm_id is kept up to date by check_selfids() */
-        if (host->irm_id == host->node_id) {
-                host->is_irm = 1;
-        } else {
-                host->is_busmgr = 0;
-                host->is_irm = 0;
-        }
+	/* irm_id is kept up to date by check_selfids() */
+	if (host->irm_id == host->node_id) {
+		host->is_irm = 1;
+	} else {
+		host->is_busmgr = 0;
+		host->is_irm = 0;
+	}
 
-        if (isroot) {
+	if (isroot) {
 		host->driver->devctl(host, ACT_CYCLE_MASTER, 1);
 		host->is_cycmst = 1;
 	}
 	atomic_inc(&host->generation);
 	host->in_bus_reset = 0;
-        highlevel_host_reset(host);
+	highlevel_host_reset(host);
 }
 
 
 void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet,
-                      int ackcode)
+		      int ackcode)
 {
 	unsigned long flags;
 
@@ -457,6 +463,7 @@ void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet,
 int hpsb_send_phy_config(struct hpsb_host *host, int rootid, int gapcnt)
 {
 	struct hpsb_packet *packet;
+	quadlet_t d = 0;
 	int retval = 0;
 
 	if (rootid >= ALL_NODES || rootid < -1 || gapcnt > 0x3f || gapcnt < -1 ||
@@ -466,26 +473,16 @@ int hpsb_send_phy_config(struct hpsb_host *host, int rootid, int gapcnt)
 		return -EINVAL;
 	}
 
-	packet = hpsb_alloc_packet(0);
-	if (!packet)
-		return -ENOMEM;
-
-	packet->host = host;
-	packet->header_size = 8;
-	packet->data_size = 0;
-	packet->expect_response = 0;
-	packet->no_waiter = 0;
-	packet->type = hpsb_raw;
-	packet->header[0] = 0;
 	if (rootid != -1)
-		packet->header[0] |= rootid << 24 | 1 << 23;
+		d |= PHYPACKET_PHYCONFIG_R | rootid << PHYPACKET_PORT_SHIFT;
 	if (gapcnt != -1)
-		packet->header[0] |= gapcnt << 16 | 1 << 22;
+		d |= PHYPACKET_PHYCONFIG_T | gapcnt << PHYPACKET_GAPCOUNT_SHIFT;
 
-	packet->header[1] = ~packet->header[0];
+	packet = hpsb_make_phypacket(host, d);
+	if (!packet)
+		return -ENOMEM;
 
 	packet->generation = get_hpsb_generation(host);
-
 	retval = hpsb_send_packet_and_wait(packet);
 	hpsb_free_packet(packet);
 
@@ -510,13 +507,13 @@ int hpsb_send_packet(struct hpsb_packet *packet)
 {
 	struct hpsb_host *host = packet->host;
 
-        if (host->is_shutdown)
+	if (host->is_shutdown)
 		return -EINVAL;
 	if (host->in_bus_reset ||
 	    (packet->generation != get_hpsb_generation(host)))
-                return -EAGAIN;
+		return -EAGAIN;
 
-        packet->state = hpsb_queued;
+	packet->state = hpsb_queued;
 
 	/* This just seems silly to me */
 	WARN_ON(packet->no_waiter && packet->expect_response);
@@ -530,42 +527,42 @@ int hpsb_send_packet(struct hpsb_packet *packet)
 		skb_queue_tail(&host->pending_packet_queue, packet->skb);
 	}
 
-        if (packet->node_id == host->node_id) {
+	if (packet->node_id == host->node_id) {
 		/* it is a local request, so handle it locally */
 
-                quadlet_t *data;
-                size_t size = packet->data_size + packet->header_size;
+		quadlet_t *data;
+		size_t size = packet->data_size + packet->header_size;
 
-                data = kmalloc(size, GFP_ATOMIC);
-                if (!data) {
-                        HPSB_ERR("unable to allocate memory for concatenating header and data");
-                        return -ENOMEM;
-                }
+		data = kmalloc(size, GFP_ATOMIC);
+		if (!data) {
+			HPSB_ERR("unable to allocate memory for concatenating header and data");
+			return -ENOMEM;
+		}
 
-                memcpy(data, packet->header, packet->header_size);
+		memcpy(data, packet->header, packet->header_size);
 
-                if (packet->data_size)
+		if (packet->data_size)
 			memcpy(((u8*)data) + packet->header_size, packet->data, packet->data_size);
 
-                dump_packet("send packet local", packet->header, packet->header_size, -1);
+		dump_packet("send packet local", packet->header, packet->header_size, -1);
 
-                hpsb_packet_sent(host, packet, packet->expect_response ? ACK_PENDING : ACK_COMPLETE);
-                hpsb_packet_received(host, data, size, 0);
+		hpsb_packet_sent(host, packet, packet->expect_response ? ACK_PENDING : ACK_COMPLETE);
+		hpsb_packet_received(host, data, size, 0);
 
-                kfree(data);
+		kfree(data);
 
-                return 0;
-        }
+		return 0;
+	}
 
-        if (packet->type == hpsb_async && packet->node_id != ALL_NODES) {
-                packet->speed_code =
-                        host->speed_map[NODEID_TO_NODE(host->node_id) * 64
-                                       + NODEID_TO_NODE(packet->node_id)];
-        }
+	if (packet->type == hpsb_async && packet->node_id != ALL_NODES) {
+		packet->speed_code =
+			host->speed_map[NODEID_TO_NODE(host->node_id) * 64
+				       + NODEID_TO_NODE(packet->node_id)];
+	}
 
-        dump_packet("send packet", packet->header, packet->header_size, packet->speed_code);
+	dump_packet("send packet", packet->header, packet->header_size, packet->speed_code);
 
-        return host->driver->transmit_packet(host, packet);
+	return host->driver->transmit_packet(host, packet);
 }
 
 /* We could just use complete() directly as the packet complete
@@ -593,81 +590,81 @@ int hpsb_send_packet_and_wait(struct hpsb_packet *packet)
 
 static void send_packet_nocare(struct hpsb_packet *packet)
 {
-        if (hpsb_send_packet(packet) < 0) {
-                hpsb_free_packet(packet);
-        }
+	if (hpsb_send_packet(packet) < 0) {
+		hpsb_free_packet(packet);
+	}
 }
 
 
 static void handle_packet_response(struct hpsb_host *host, int tcode,
 				   quadlet_t *data, size_t size)
 {
-        struct hpsb_packet *packet = NULL;
+	struct hpsb_packet *packet = NULL;
 	struct sk_buff *skb;
-        int tcode_match = 0;
-        int tlabel;
-        unsigned long flags;
+	int tcode_match = 0;
+	int tlabel;
+	unsigned long flags;
 
-        tlabel = (data[0] >> 10) & 0x3f;
+	tlabel = (data[0] >> 10) & 0x3f;
 
 	spin_lock_irqsave(&host->pending_packet_queue.lock, flags);
 
 	skb_queue_walk(&host->pending_packet_queue, skb) {
 		packet = (struct hpsb_packet *)skb->data;
-                if ((packet->tlabel == tlabel)
-                    && (packet->node_id == (data[1] >> 16))){
-                        break;
-                }
+		if ((packet->tlabel == tlabel)
+		    && (packet->node_id == (data[1] >> 16))){
+			break;
+		}
 
 		packet = NULL;
-        }
+	}
 
 	if (packet == NULL) {
-                HPSB_DEBUG("unsolicited response packet received - no tlabel match");
-                dump_packet("contents", data, 16, -1);
+		HPSB_DEBUG("unsolicited response packet received - no tlabel match");
+		dump_packet("contents", data, 16, -1);
 		spin_unlock_irqrestore(&host->pending_packet_queue.lock, flags);
-                return;
-        }
+		return;
+	}
 
-        switch (packet->tcode) {
-        case TCODE_WRITEQ:
-        case TCODE_WRITEB:
-                if (tcode != TCODE_WRITE_RESPONSE)
+	switch (packet->tcode) {
+	case TCODE_WRITEQ:
+	case TCODE_WRITEB:
+		if (tcode != TCODE_WRITE_RESPONSE)
 			break;
 		tcode_match = 1;
 		memcpy(packet->header, data, 12);
-                break;
-        case TCODE_READQ:
-                if (tcode != TCODE_READQ_RESPONSE)
+		break;
+	case TCODE_READQ:
+		if (tcode != TCODE_READQ_RESPONSE)
 			break;
 		tcode_match = 1;
 		memcpy(packet->header, data, 16);
-                break;
-        case TCODE_READB:
-                if (tcode != TCODE_READB_RESPONSE)
+		break;
+	case TCODE_READB:
+		if (tcode != TCODE_READB_RESPONSE)
 			break;
 		tcode_match = 1;
 		BUG_ON(packet->skb->len - sizeof(*packet) < size - 16);
 		memcpy(packet->header, data, 16);
 		memcpy(packet->data, data + 4, size - 16);
-                break;
-        case TCODE_LOCK_REQUEST:
-                if (tcode != TCODE_LOCK_RESPONSE)
+		break;
+	case TCODE_LOCK_REQUEST:
+		if (tcode != TCODE_LOCK_RESPONSE)
 			break;
 		tcode_match = 1;
 		size = min((size - 16), (size_t)8);
 		BUG_ON(packet->skb->len - sizeof(*packet) < size);
 		memcpy(packet->header, data, 16);
 		memcpy(packet->data, data + 4, size);
-                break;
-        }
+		break;
+	}
 
-        if (!tcode_match) {
+	if (!tcode_match) {
 		spin_unlock_irqrestore(&host->pending_packet_queue.lock, flags);
-                HPSB_INFO("unsolicited response packet received - tcode mismatch");
-                dump_packet("contents", data, 16, -1);
-                return;
-        }
+		HPSB_INFO("unsolicited response packet received - tcode mismatch");
+		dump_packet("contents", data, 16, -1);
+		return;
+	}
 
 	__skb_unlink(skb, &host->pending_packet_queue);
 
@@ -686,27 +683,27 @@ static void handle_packet_response(struct hpsb_host *host, int tcode,
 static struct hpsb_packet *create_reply_packet(struct hpsb_host *host,
 					       quadlet_t *data, size_t dsize)
 {
-        struct hpsb_packet *p;
+	struct hpsb_packet *p;
 
-        p = hpsb_alloc_packet(dsize);
-        if (unlikely(p == NULL)) {
-                /* FIXME - send data_error response */
-                return NULL;
-        }
+	p = hpsb_alloc_packet(dsize);
+	if (unlikely(p == NULL)) {
+		/* FIXME - send data_error response */
+		return NULL;
+	}
 
-        p->type = hpsb_async;
-        p->state = hpsb_unused;
-        p->host = host;
-        p->node_id = data[1] >> 16;
-        p->tlabel = (data[0] >> 10) & 0x3f;
-        p->no_waiter = 1;
+	p->type = hpsb_async;
+	p->state = hpsb_unused;
+	p->host = host;
+	p->node_id = data[1] >> 16;
+	p->tlabel = (data[0] >> 10) & 0x3f;
+	p->no_waiter = 1;
 
 	p->generation = get_hpsb_generation(host);
 
 	if (dsize % 4)
 		p->data[dsize / 4] = 0;
 
-        return p;
+	return p;
 }
 
 #define PREP_ASYNC_HEAD_RCODE(tc) \
@@ -717,7 +714,7 @@ static struct hpsb_packet *create_reply_packet(struct hpsb_host *host,
 	packet->header[2] = 0
 
 static void fill_async_readquad_resp(struct hpsb_packet *packet, int rcode,
-                              quadlet_t data)
+			      quadlet_t data)
 {
 	PREP_ASYNC_HEAD_RCODE(TCODE_READQ_RESPONSE);
 	packet->header[3] = data;
@@ -726,7 +723,7 @@ static void fill_async_readquad_resp(struct hpsb_packet *packet, int rcode,
 }
 
 static void fill_async_readblock_resp(struct hpsb_packet *packet, int rcode,
-                               int length)
+			       int length)
 {
 	if (rcode != RCODE_COMPLETE)
 		length = 0;
@@ -746,7 +743,7 @@ static void fill_async_write_resp(struct hpsb_packet *packet, int rcode)
 }
 
 static void fill_async_lock_resp(struct hpsb_packet *packet, int rcode, int extcode,
-                          int length)
+			  int length)
 {
 	if (rcode != RCODE_COMPLETE)
 		length = 0;
@@ -758,184 +755,184 @@ static void fill_async_lock_resp(struct hpsb_packet *packet, int rcode, int extc
 }
 
 #define PREP_REPLY_PACKET(length) \
-                packet = create_reply_packet(host, data, length); \
-                if (packet == NULL) break
+		packet = create_reply_packet(host, data, length); \
+		if (packet == NULL) break
 
 static void handle_incoming_packet(struct hpsb_host *host, int tcode,
 				   quadlet_t *data, size_t size, int write_acked)
 {
-        struct hpsb_packet *packet;
-        int length, rcode, extcode;
-        quadlet_t buffer;
-        nodeid_t source = data[1] >> 16;
-        nodeid_t dest = data[0] >> 16;
-        u16 flags = (u16) data[0];
-        u64 addr;
-
-        /* big FIXME - no error checking is done for an out of bounds length */
-
-        switch (tcode) {
-        case TCODE_WRITEQ:
-                addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
-                rcode = highlevel_write(host, source, dest, data+3,
+	struct hpsb_packet *packet;
+	int length, rcode, extcode;
+	quadlet_t buffer;
+	nodeid_t source = data[1] >> 16;
+	nodeid_t dest = data[0] >> 16;
+	u16 flags = (u16) data[0];
+	u64 addr;
+
+	/* big FIXME - no error checking is done for an out of bounds length */
+
+	switch (tcode) {
+	case TCODE_WRITEQ:
+		addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
+		rcode = highlevel_write(host, source, dest, data+3,
 					addr, 4, flags);
 
-                if (!write_acked
-                    && (NODEID_TO_NODE(data[0] >> 16) != NODE_MASK)
-                    && (rcode >= 0)) {
-                        /* not a broadcast write, reply */
-                        PREP_REPLY_PACKET(0);
-                        fill_async_write_resp(packet, rcode);
-                        send_packet_nocare(packet);
-                }
-                break;
-
-        case TCODE_WRITEB:
-                addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
-                rcode = highlevel_write(host, source, dest, data+4,
+		if (!write_acked
+		    && (NODEID_TO_NODE(data[0] >> 16) != NODE_MASK)
+		    && (rcode >= 0)) {
+			/* not a broadcast write, reply */
+			PREP_REPLY_PACKET(0);
+			fill_async_write_resp(packet, rcode);
+			send_packet_nocare(packet);
+		}
+		break;
+
+	case TCODE_WRITEB:
+		addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
+		rcode = highlevel_write(host, source, dest, data+4,
 					addr, data[3]>>16, flags);
 
-                if (!write_acked
-                    && (NODEID_TO_NODE(data[0] >> 16) != NODE_MASK)
-                    && (rcode >= 0)) {
-                        /* not a broadcast write, reply */
-                        PREP_REPLY_PACKET(0);
-                        fill_async_write_resp(packet, rcode);
-                        send_packet_nocare(packet);
-                }
-                break;
-
-        case TCODE_READQ:
-                addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
-                rcode = highlevel_read(host, source, &buffer, addr, 4, flags);
-
-                if (rcode >= 0) {
-                        PREP_REPLY_PACKET(0);
-                        fill_async_readquad_resp(packet, rcode, buffer);
-                        send_packet_nocare(packet);
-                }
-                break;
-
-        case TCODE_READB:
-                length = data[3] >> 16;
-                PREP_REPLY_PACKET(length);
-
-                addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
-                rcode = highlevel_read(host, source, packet->data, addr,
-                                       length, flags);
-
-                if (rcode >= 0) {
-                        fill_async_readblock_resp(packet, rcode, length);
-                        send_packet_nocare(packet);
-                } else {
-                        hpsb_free_packet(packet);
-                }
-                break;
-
-        case TCODE_LOCK_REQUEST:
-                length = data[3] >> 16;
-                extcode = data[3] & 0xffff;
-                addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
-
-                PREP_REPLY_PACKET(8);
-
-                if ((extcode == 0) || (extcode >= 7)) {
-                        /* let switch default handle error */
-                        length = 0;
-                }
-
-                switch (length) {
-                case 4:
-                        rcode = highlevel_lock(host, source, packet->data, addr,
-                                               data[4], 0, extcode,flags);
-                        fill_async_lock_resp(packet, rcode, extcode, 4);
-                        break;
-                case 8:
-                        if ((extcode != EXTCODE_FETCH_ADD)
-                            && (extcode != EXTCODE_LITTLE_ADD)) {
-                                rcode = highlevel_lock(host, source,
-                                                       packet->data, addr,
-                                                       data[5], data[4],
-                                                       extcode, flags);
-                                fill_async_lock_resp(packet, rcode, extcode, 4);
-                        } else {
-                                rcode = highlevel_lock64(host, source,
-                                             (octlet_t *)packet->data, addr,
-                                             *(octlet_t *)(data + 4), 0ULL,
-                                             extcode, flags);
-                                fill_async_lock_resp(packet, rcode, extcode, 8);
-                        }
-                        break;
-                case 16:
-                        rcode = highlevel_lock64(host, source,
-                                                 (octlet_t *)packet->data, addr,
-                                                 *(octlet_t *)(data + 6),
-                                                 *(octlet_t *)(data + 4),
-                                                 extcode, flags);
-                        fill_async_lock_resp(packet, rcode, extcode, 8);
-                        break;
-                default:
-                        rcode = RCODE_TYPE_ERROR;
-                        fill_async_lock_resp(packet, rcode,
-                                             extcode, 0);
-                }
-
-                if (rcode >= 0) {
-                        send_packet_nocare(packet);
-                } else {
-                        hpsb_free_packet(packet);
-                }
-                break;
-        }
+		if (!write_acked
+		    && (NODEID_TO_NODE(data[0] >> 16) != NODE_MASK)
+		    && (rcode >= 0)) {
+			/* not a broadcast write, reply */
+			PREP_REPLY_PACKET(0);
+			fill_async_write_resp(packet, rcode);
+			send_packet_nocare(packet);
+		}
+		break;
+
+	case TCODE_READQ:
+		addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
+		rcode = highlevel_read(host, source, &buffer, addr, 4, flags);
+
+		if (rcode >= 0) {
+			PREP_REPLY_PACKET(0);
+			fill_async_readquad_resp(packet, rcode, buffer);
+			send_packet_nocare(packet);
+		}
+		break;
+
+	case TCODE_READB:
+		length = data[3] >> 16;
+		PREP_REPLY_PACKET(length);
+
+		addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
+		rcode = highlevel_read(host, source, packet->data, addr,
+				       length, flags);
+
+		if (rcode >= 0) {
+			fill_async_readblock_resp(packet, rcode, length);
+			send_packet_nocare(packet);
+		} else {
+			hpsb_free_packet(packet);
+		}
+		break;
+
+	case TCODE_LOCK_REQUEST:
+		length = data[3] >> 16;
+		extcode = data[3] & 0xffff;
+		addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
+
+		PREP_REPLY_PACKET(8);
+
+		if ((extcode == 0) || (extcode >= 7)) {
+			/* let switch default handle error */
+			length = 0;
+		}
+
+		switch (length) {
+		case 4:
+			rcode = highlevel_lock(host, source, packet->data, addr,
+					       data[4], 0, extcode,flags);
+			fill_async_lock_resp(packet, rcode, extcode, 4);
+			break;
+		case 8:
+			if ((extcode != EXTCODE_FETCH_ADD)
+			    && (extcode != EXTCODE_LITTLE_ADD)) {
+				rcode = highlevel_lock(host, source,
+						       packet->data, addr,
+						       data[5], data[4],
+						       extcode, flags);
+				fill_async_lock_resp(packet, rcode, extcode, 4);
+			} else {
+				rcode = highlevel_lock64(host, source,
+					     (octlet_t *)packet->data, addr,
+					     *(octlet_t *)(data + 4), 0ULL,
+					     extcode, flags);
+				fill_async_lock_resp(packet, rcode, extcode, 8);
+			}
+			break;
+		case 16:
+			rcode = highlevel_lock64(host, source,
+						 (octlet_t *)packet->data, addr,
+						 *(octlet_t *)(data + 6),
+						 *(octlet_t *)(data + 4),
+						 extcode, flags);
+			fill_async_lock_resp(packet, rcode, extcode, 8);
+			break;
+		default:
+			rcode = RCODE_TYPE_ERROR;
+			fill_async_lock_resp(packet, rcode,
+					     extcode, 0);
+		}
+
+		if (rcode >= 0) {
+			send_packet_nocare(packet);
+		} else {
+			hpsb_free_packet(packet);
+		}
+		break;
+	}
 
 }
 #undef PREP_REPLY_PACKET
 
 
 void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size,
-                          int write_acked)
+			  int write_acked)
 {
-        int tcode;
-
-        if (host->in_bus_reset) {
-                HPSB_INFO("received packet during reset; ignoring");
-                return;
-        }
-
-        dump_packet("received packet", data, size, -1);
-
-        tcode = (data[0] >> 4) & 0xf;
-
-        switch (tcode) {
-        case TCODE_WRITE_RESPONSE:
-        case TCODE_READQ_RESPONSE:
-        case TCODE_READB_RESPONSE:
-        case TCODE_LOCK_RESPONSE:
-                handle_packet_response(host, tcode, data, size);
-                break;
-
-        case TCODE_WRITEQ:
-        case TCODE_WRITEB:
-        case TCODE_READQ:
-        case TCODE_READB:
-        case TCODE_LOCK_REQUEST:
-                handle_incoming_packet(host, tcode, data, size, write_acked);
-                break;
-
-
-        case TCODE_ISO_DATA:
-                highlevel_iso_receive(host, data, size);
-                break;
-
-        case TCODE_CYCLE_START:
-                /* simply ignore this packet if it is passed on */
-                break;
-
-        default:
-                HPSB_NOTICE("received packet with bogus transaction code %d",
-                            tcode);
-                break;
-        }
+	int tcode;
+
+	if (host->in_bus_reset) {
+		HPSB_INFO("received packet during reset; ignoring");
+		return;
+	}
+
+	dump_packet("received packet", data, size, -1);
+
+	tcode = (data[0] >> 4) & 0xf;
+
+	switch (tcode) {
+	case TCODE_WRITE_RESPONSE:
+	case TCODE_READQ_RESPONSE:
+	case TCODE_READB_RESPONSE:
+	case TCODE_LOCK_RESPONSE:
+		handle_packet_response(host, tcode, data, size);
+		break;
+
+	case TCODE_WRITEQ:
+	case TCODE_WRITEB:
+	case TCODE_READQ:
+	case TCODE_READB:
+	case TCODE_LOCK_REQUEST:
+		handle_incoming_packet(host, tcode, data, size, write_acked);
+		break;
+
+
+	case TCODE_ISO_DATA:
+		highlevel_iso_receive(host, data, size);
+		break;
+
+	case TCODE_CYCLE_START:
+		/* simply ignore this packet if it is passed on */
+		break;
+
+	default:
+		HPSB_NOTICE("received packet with bogus transaction code %d",
+			    tcode);
+		break;
+	}
 }
 
 
@@ -1030,10 +1027,10 @@ static int hpsbpkt_thread(void *__hi)
 
 	daemonize("khpsbpkt");
 
+	current->flags |= PF_NOFREEZE;
+
 	while (1) {
 		if (down_interruptible(&khpsbpkt_sig)) {
-			if (try_to_freeze())
-				continue;
 			printk("khpsbpkt: received unexpected signal?!\n" );
 			break;
 		}
@@ -1129,7 +1126,7 @@ static int __init ieee1394_init(void)
 		   nodemgr implements functionality required of ieee1394a-2000
 		   IRMs */
 		hpsb_disable_irm = 1;
-                      
+
 		return 0;
 	}
 
diff --git a/drivers/ieee1394/ieee1394_core.h b/drivers/ieee1394/ieee1394_core.h
index 0b31429d0a68..b35466023f00 100644
--- a/drivers/ieee1394/ieee1394_core.h
+++ b/drivers/ieee1394/ieee1394_core.h
@@ -10,8 +10,8 @@
 
 
 struct hpsb_packet {
-        /* This struct is basically read-only for hosts with the exception of
-         * the data buffer contents and xnext - see below. */
+	/* This struct is basically read-only for hosts with the exception of
+	 * the data buffer contents and xnext - see below. */
 
 	/* This can be used for host driver internal linking.
 	 *
@@ -21,47 +21,47 @@ struct hpsb_packet {
 	 * driver_list when free'ing it. */
 	struct list_head driver_list;
 
-        nodeid_t node_id;
+	nodeid_t node_id;
 
-        /* Async and Iso types should be clear, raw means send-as-is, do not
-         * CRC!  Byte swapping shall still be done in this case. */
-        enum { hpsb_async, hpsb_iso, hpsb_raw } __attribute__((packed)) type;
+	/* Async and Iso types should be clear, raw means send-as-is, do not
+	 * CRC!  Byte swapping shall still be done in this case. */
+	enum { hpsb_async, hpsb_iso, hpsb_raw } __attribute__((packed)) type;
 
-        /* Okay, this is core internal and a no care for hosts.
-         * queued   = queued for sending
-         * pending  = sent, waiting for response
-         * complete = processing completed, successful or not
-         */
-        enum {
-                hpsb_unused, hpsb_queued, hpsb_pending, hpsb_complete
-        } __attribute__((packed)) state;
+	/* Okay, this is core internal and a no care for hosts.
+	 * queued   = queued for sending
+	 * pending  = sent, waiting for response
+	 * complete = processing completed, successful or not
+	 */
+	enum {
+		hpsb_unused, hpsb_queued, hpsb_pending, hpsb_complete
+	} __attribute__((packed)) state;
 
-        /* These are core internal. */
-        signed char tlabel;
+	/* These are core internal. */
+	signed char tlabel;
 	signed char ack_code;
 	unsigned char tcode;
 
-        unsigned expect_response:1;
-        unsigned no_waiter:1;
+	unsigned expect_response:1;
+	unsigned no_waiter:1;
 
-        /* Speed to transmit with: 0 = 100Mbps, 1 = 200Mbps, 2 = 400Mbps */
-        unsigned speed_code:2;
+	/* Speed to transmit with: 0 = 100Mbps, 1 = 200Mbps, 2 = 400Mbps */
+	unsigned speed_code:2;
 
-        /*
-         * *header and *data are guaranteed to be 32-bit DMAable and may be
-         * overwritten to allow in-place byte swapping.  Neither of these is
-         * CRCed (the sizes also don't include CRC), but contain space for at
-         * least one additional quadlet to allow in-place CRCing.  The memory is
-         * also guaranteed to be DMA mappable.
-         */
-        quadlet_t *header;
-        quadlet_t *data;
-        size_t header_size;
-        size_t data_size;
+	/*
+	 * *header and *data are guaranteed to be 32-bit DMAable and may be
+	 * overwritten to allow in-place byte swapping.  Neither of these is
+	 * CRCed (the sizes also don't include CRC), but contain space for at
+	 * least one additional quadlet to allow in-place CRCing.  The memory is
+	 * also guaranteed to be DMA mappable.
+	 */
+	quadlet_t *header;
+	quadlet_t *data;
+	size_t header_size;
+	size_t data_size;
 
 
-        struct hpsb_host *host;
-        unsigned int generation;
+	struct hpsb_host *host;
+	unsigned int generation;
 
 	atomic_t refcnt;
 
@@ -73,10 +73,10 @@ struct hpsb_packet {
 	/* XXX This is just a hack at the moment */
 	struct sk_buff *skb;
 
-        /* Store jiffies for implementing bus timeouts. */
-        unsigned long sendtime;
+	/* Store jiffies for implementing bus timeouts. */
+	unsigned long sendtime;
 
-        quadlet_t embedded_header[5];
+	quadlet_t embedded_header[5];
 };
 
 /* Set a task for when a packet completes */
@@ -102,7 +102,7 @@ void hpsb_free_packet(struct hpsb_packet *packet);
  */
 static inline unsigned int get_hpsb_generation(struct hpsb_host *host)
 {
-        return atomic_read(&host->generation);
+	return atomic_read(&host->generation);
 }
 
 /*
@@ -157,7 +157,7 @@ void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot);
  * from within a transmit packet routine.
  */
 void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet,
-                      int ackcode);
+		      int ackcode);
 
 /*
  * Hand over received packet to the core.  The contents of data are expected to
@@ -171,7 +171,7 @@ void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet,
  * packet type.
  */
 void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size,
-                          int write_acked);
+			  int write_acked);
 
 
 /*
@@ -197,20 +197,20 @@ void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size,
  * Block 15 (240-255)  reserved for drivers under development, etc.
  */
 
-#define IEEE1394_MAJOR               171
+#define IEEE1394_MAJOR			 171
 
-#define IEEE1394_MINOR_BLOCK_RAW1394       0
-#define IEEE1394_MINOR_BLOCK_VIDEO1394     1
-#define IEEE1394_MINOR_BLOCK_DV1394        2
-#define IEEE1394_MINOR_BLOCK_AMDTP         3
+#define IEEE1394_MINOR_BLOCK_RAW1394	   0
+#define IEEE1394_MINOR_BLOCK_VIDEO1394	   1
+#define IEEE1394_MINOR_BLOCK_DV1394	   2
+#define IEEE1394_MINOR_BLOCK_AMDTP	   3
 #define IEEE1394_MINOR_BLOCK_EXPERIMENTAL 15
 
-#define IEEE1394_CORE_DEV		MKDEV(IEEE1394_MAJOR, 0)
-#define IEEE1394_RAW1394_DEV		MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16)
-#define IEEE1394_VIDEO1394_DEV		MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_VIDEO1394 * 16)
-#define IEEE1394_DV1394_DEV		MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16)
-#define IEEE1394_AMDTP_DEV		MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_AMDTP * 16)
-#define IEEE1394_EXPERIMENTAL_DEV	MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_EXPERIMENTAL * 16)
+#define IEEE1394_CORE_DEV	  MKDEV(IEEE1394_MAJOR, 0)
+#define IEEE1394_RAW1394_DEV	  MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16)
+#define IEEE1394_VIDEO1394_DEV	  MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_VIDEO1394 * 16)
+#define IEEE1394_DV1394_DEV	  MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16)
+#define IEEE1394_AMDTP_DEV	  MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_AMDTP * 16)
+#define IEEE1394_EXPERIMENTAL_DEV MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_EXPERIMENTAL * 16)
 
 /* return the index (within a minor number block) of a file */
 static inline unsigned char ieee1394_file_to_instance(struct file *file)
diff --git a/drivers/ieee1394/ieee1394_transactions.c b/drivers/ieee1394/ieee1394_transactions.c
index 0aa876360f9b..3fe2f6c4a253 100644
--- a/drivers/ieee1394/ieee1394_transactions.c
+++ b/drivers/ieee1394/ieee1394_transactions.c
@@ -22,7 +22,7 @@
 #include "ieee1394_core.h"
 #include "highlevel.h"
 #include "nodemgr.h"
-
+#include "ieee1394_transactions.h"
 
 #define PREP_ASYNC_HEAD_ADDRESS(tc) \
         packet->tcode = tc; \
@@ -31,80 +31,82 @@
         packet->header[1] = (packet->host->node_id << 16) | (addr >> 32); \
         packet->header[2] = addr & 0xffffffff
 
-
 static void fill_async_readquad(struct hpsb_packet *packet, u64 addr)
 {
-        PREP_ASYNC_HEAD_ADDRESS(TCODE_READQ);
-        packet->header_size = 12;
-        packet->data_size = 0;
-        packet->expect_response = 1;
+	PREP_ASYNC_HEAD_ADDRESS(TCODE_READQ);
+	packet->header_size = 12;
+	packet->data_size = 0;
+	packet->expect_response = 1;
 }
 
-static void fill_async_readblock(struct hpsb_packet *packet, u64 addr, int length)
+static void fill_async_readblock(struct hpsb_packet *packet, u64 addr,
+				 int length)
 {
-        PREP_ASYNC_HEAD_ADDRESS(TCODE_READB);
-        packet->header[3] = length << 16;
-        packet->header_size = 16;
-        packet->data_size = 0;
-        packet->expect_response = 1;
+	PREP_ASYNC_HEAD_ADDRESS(TCODE_READB);
+	packet->header[3] = length << 16;
+	packet->header_size = 16;
+	packet->data_size = 0;
+	packet->expect_response = 1;
 }
 
-static void fill_async_writequad(struct hpsb_packet *packet, u64 addr, quadlet_t data)
+static void fill_async_writequad(struct hpsb_packet *packet, u64 addr,
+				 quadlet_t data)
 {
-        PREP_ASYNC_HEAD_ADDRESS(TCODE_WRITEQ);
-        packet->header[3] = data;
-        packet->header_size = 16;
-        packet->data_size = 0;
-        packet->expect_response = 1;
+	PREP_ASYNC_HEAD_ADDRESS(TCODE_WRITEQ);
+	packet->header[3] = data;
+	packet->header_size = 16;
+	packet->data_size = 0;
+	packet->expect_response = 1;
 }
 
-static void fill_async_writeblock(struct hpsb_packet *packet, u64 addr, int length)
+static void fill_async_writeblock(struct hpsb_packet *packet, u64 addr,
+				  int length)
 {
-        PREP_ASYNC_HEAD_ADDRESS(TCODE_WRITEB);
-        packet->header[3] = length << 16;
-        packet->header_size = 16;
-        packet->expect_response = 1;
-        packet->data_size = length + (length % 4 ? 4 - (length % 4) : 0);
+	PREP_ASYNC_HEAD_ADDRESS(TCODE_WRITEB);
+	packet->header[3] = length << 16;
+	packet->header_size = 16;
+	packet->expect_response = 1;
+	packet->data_size = length + (length % 4 ? 4 - (length % 4) : 0);
 }
 
 static void fill_async_lock(struct hpsb_packet *packet, u64 addr, int extcode,
-                     int length)
+			    int length)
 {
-        PREP_ASYNC_HEAD_ADDRESS(TCODE_LOCK_REQUEST);
-        packet->header[3] = (length << 16) | extcode;
-        packet->header_size = 16;
-        packet->data_size = length;
-        packet->expect_response = 1;
+	PREP_ASYNC_HEAD_ADDRESS(TCODE_LOCK_REQUEST);
+	packet->header[3] = (length << 16) | extcode;
+	packet->header_size = 16;
+	packet->data_size = length;
+	packet->expect_response = 1;
 }
 
 static void fill_iso_packet(struct hpsb_packet *packet, int length, int channel,
-                     int tag, int sync)
+			    int tag, int sync)
 {
-        packet->header[0] = (length << 16) | (tag << 14) | (channel << 8)
-                | (TCODE_ISO_DATA << 4) | sync;
+	packet->header[0] = (length << 16) | (tag << 14) | (channel << 8)
+	    | (TCODE_ISO_DATA << 4) | sync;
 
-        packet->header_size = 4;
-        packet->data_size = length;
-        packet->type = hpsb_iso;
-        packet->tcode = TCODE_ISO_DATA;
+	packet->header_size = 4;
+	packet->data_size = length;
+	packet->type = hpsb_iso;
+	packet->tcode = TCODE_ISO_DATA;
 }
 
 static void fill_phy_packet(struct hpsb_packet *packet, quadlet_t data)
 {
-        packet->header[0] = data;
-        packet->header[1] = ~data;
-        packet->header_size = 8;
-        packet->data_size = 0;
-        packet->expect_response = 0;
-        packet->type = hpsb_raw;             /* No CRC added */
-        packet->speed_code = IEEE1394_SPEED_100; /* Force speed to be 100Mbps */
+	packet->header[0] = data;
+	packet->header[1] = ~data;
+	packet->header_size = 8;
+	packet->data_size = 0;
+	packet->expect_response = 0;
+	packet->type = hpsb_raw;	/* No CRC added */
+	packet->speed_code = IEEE1394_SPEED_100;	/* Force speed to be 100Mbps */
 }
 
 static void fill_async_stream_packet(struct hpsb_packet *packet, int length,
 				     int channel, int tag, int sync)
 {
 	packet->header[0] = (length << 16) | (tag << 14) | (channel << 8)
-	                  | (TCODE_STREAM_DATA << 4) | sync;
+	    | (TCODE_STREAM_DATA << 4) | sync;
 
 	packet->header_size = 4;
 	packet->data_size = length;
@@ -171,99 +173,96 @@ int hpsb_get_tlabel(struct hpsb_packet *packet)
  */
 void hpsb_free_tlabel(struct hpsb_packet *packet)
 {
-        unsigned long flags;
+	unsigned long flags;
 	struct hpsb_tlabel_pool *tp;
 
 	tp = &packet->host->tpool[packet->node_id & NODE_MASK];
 
 	BUG_ON(packet->tlabel > 63 || packet->tlabel < 0);
 
-        spin_lock_irqsave(&tp->lock, flags);
+	spin_lock_irqsave(&tp->lock, flags);
 	BUG_ON(!test_and_clear_bit(packet->tlabel, tp->pool));
-        spin_unlock_irqrestore(&tp->lock, flags);
+	spin_unlock_irqrestore(&tp->lock, flags);
 
 	up(&tp->count);
 }
 
-
-
 int hpsb_packet_success(struct hpsb_packet *packet)
 {
-        switch (packet->ack_code) {
-        case ACK_PENDING:
-                switch ((packet->header[1] >> 12) & 0xf) {
-                case RCODE_COMPLETE:
-                        return 0;
-                case RCODE_CONFLICT_ERROR:
-                        return -EAGAIN;
-                case RCODE_DATA_ERROR:
-                        return -EREMOTEIO;
-                case RCODE_TYPE_ERROR:
-                        return -EACCES;
-                case RCODE_ADDRESS_ERROR:
-                        return -EINVAL;
-                default:
-                        HPSB_ERR("received reserved rcode %d from node %d",
-                                 (packet->header[1] >> 12) & 0xf,
-                                 packet->node_id);
-                        return -EAGAIN;
-                }
-                HPSB_PANIC("reached unreachable code 1 in %s", __FUNCTION__);
-
-        case ACK_BUSY_X:
-        case ACK_BUSY_A:
-        case ACK_BUSY_B:
-                return -EBUSY;
-
-        case ACK_TYPE_ERROR:
-                return -EACCES;
-
-        case ACK_COMPLETE:
-                if (packet->tcode == TCODE_WRITEQ
-                    || packet->tcode == TCODE_WRITEB) {
-                        return 0;
-                } else {
-                        HPSB_ERR("impossible ack_complete from node %d "
-                                 "(tcode %d)", packet->node_id, packet->tcode);
-                        return -EAGAIN;
-                }
-
-
-        case ACK_DATA_ERROR:
-                if (packet->tcode == TCODE_WRITEB
-                    || packet->tcode == TCODE_LOCK_REQUEST) {
-                        return -EAGAIN;
-                } else {
-                        HPSB_ERR("impossible ack_data_error from node %d "
-                                 "(tcode %d)", packet->node_id, packet->tcode);
-                        return -EAGAIN;
-                }
-
-        case ACK_ADDRESS_ERROR:
-                return -EINVAL;
-
-        case ACK_TARDY:
-        case ACK_CONFLICT_ERROR:
-        case ACKX_NONE:
-        case ACKX_SEND_ERROR:
-        case ACKX_ABORTED:
-        case ACKX_TIMEOUT:
-                /* error while sending */
-                return -EAGAIN;
-
-        default:
-                HPSB_ERR("got invalid ack %d from node %d (tcode %d)",
-                         packet->ack_code, packet->node_id, packet->tcode);
-                return -EAGAIN;
-        }
-
-        HPSB_PANIC("reached unreachable code 2 in %s", __FUNCTION__);
+	switch (packet->ack_code) {
+	case ACK_PENDING:
+		switch ((packet->header[1] >> 12) & 0xf) {
+		case RCODE_COMPLETE:
+			return 0;
+		case RCODE_CONFLICT_ERROR:
+			return -EAGAIN;
+		case RCODE_DATA_ERROR:
+			return -EREMOTEIO;
+		case RCODE_TYPE_ERROR:
+			return -EACCES;
+		case RCODE_ADDRESS_ERROR:
+			return -EINVAL;
+		default:
+			HPSB_ERR("received reserved rcode %d from node %d",
+				 (packet->header[1] >> 12) & 0xf,
+				 packet->node_id);
+			return -EAGAIN;
+		}
+		HPSB_PANIC("reached unreachable code 1 in %s", __FUNCTION__);
+
+	case ACK_BUSY_X:
+	case ACK_BUSY_A:
+	case ACK_BUSY_B:
+		return -EBUSY;
+
+	case ACK_TYPE_ERROR:
+		return -EACCES;
+
+	case ACK_COMPLETE:
+		if (packet->tcode == TCODE_WRITEQ
+		    || packet->tcode == TCODE_WRITEB) {
+			return 0;
+		} else {
+			HPSB_ERR("impossible ack_complete from node %d "
+				 "(tcode %d)", packet->node_id, packet->tcode);
+			return -EAGAIN;
+		}
+
+	case ACK_DATA_ERROR:
+		if (packet->tcode == TCODE_WRITEB
+		    || packet->tcode == TCODE_LOCK_REQUEST) {
+			return -EAGAIN;
+		} else {
+			HPSB_ERR("impossible ack_data_error from node %d "
+				 "(tcode %d)", packet->node_id, packet->tcode);
+			return -EAGAIN;
+		}
+
+	case ACK_ADDRESS_ERROR:
+		return -EINVAL;
+
+	case ACK_TARDY:
+	case ACK_CONFLICT_ERROR:
+	case ACKX_NONE:
+	case ACKX_SEND_ERROR:
+	case ACKX_ABORTED:
+	case ACKX_TIMEOUT:
+		/* error while sending */
+		return -EAGAIN;
+
+	default:
+		HPSB_ERR("got invalid ack %d from node %d (tcode %d)",
+			 packet->ack_code, packet->node_id, packet->tcode);
+		return -EAGAIN;
+	}
+
+	HPSB_PANIC("reached unreachable code 2 in %s", __FUNCTION__);
 }
 
 struct hpsb_packet *hpsb_make_readpacket(struct hpsb_host *host, nodeid_t node,
 					 u64 addr, size_t length)
 {
-        struct hpsb_packet *packet;
+	struct hpsb_packet *packet;
 
 	if (length == 0)
 		return NULL;
@@ -288,8 +287,9 @@ struct hpsb_packet *hpsb_make_readpacket(struct hpsb_host *host, nodeid_t node,
 	return packet;
 }
 
-struct hpsb_packet *hpsb_make_writepacket (struct hpsb_host *host, nodeid_t node,
-					   u64 addr, quadlet_t *buffer, size_t length)
+struct hpsb_packet *hpsb_make_writepacket(struct hpsb_host *host, nodeid_t node,
+					  u64 addr, quadlet_t * buffer,
+					  size_t length)
 {
 	struct hpsb_packet *packet;
 
@@ -300,7 +300,7 @@ struct hpsb_packet *hpsb_make_writepacket (struct hpsb_host *host, nodeid_t node
 	if (!packet)
 		return NULL;
 
-	if (length % 4) { /* zero padding bytes */
+	if (length % 4) {	/* zero padding bytes */
 		packet->data[length >> 2] = 0;
 	}
 	packet->host = host;
@@ -322,8 +322,9 @@ struct hpsb_packet *hpsb_make_writepacket (struct hpsb_host *host, nodeid_t node
 	return packet;
 }
 
-struct hpsb_packet *hpsb_make_streampacket(struct hpsb_host *host, u8 *buffer, int length,
-                                           int channel, int tag, int sync)
+struct hpsb_packet *hpsb_make_streampacket(struct hpsb_host *host, u8 * buffer,
+					   int length, int channel, int tag,
+					   int sync)
 {
 	struct hpsb_packet *packet;
 
@@ -334,7 +335,7 @@ struct hpsb_packet *hpsb_make_streampacket(struct hpsb_host *host, u8 *buffer, i
 	if (!packet)
 		return NULL;
 
-	if (length % 4) { /* zero padding bytes */
+	if (length % 4) {	/* zero padding bytes */
 		packet->data[length >> 2] = 0;
 	}
 	packet->host = host;
@@ -352,14 +353,15 @@ struct hpsb_packet *hpsb_make_streampacket(struct hpsb_host *host, u8 *buffer, i
 }
 
 struct hpsb_packet *hpsb_make_lockpacket(struct hpsb_host *host, nodeid_t node,
-                                         u64 addr, int extcode, quadlet_t *data,
-					 quadlet_t arg)
+					 u64 addr, int extcode,
+					 quadlet_t * data, quadlet_t arg)
 {
 	struct hpsb_packet *p;
 	u32 length;
 
 	p = hpsb_alloc_packet(8);
-	if (!p) return NULL;
+	if (!p)
+		return NULL;
 
 	p->host = host;
 	p->node_id = node;
@@ -388,15 +390,16 @@ struct hpsb_packet *hpsb_make_lockpacket(struct hpsb_host *host, nodeid_t node,
 	return p;
 }
 
-struct hpsb_packet *hpsb_make_lock64packet(struct hpsb_host *host, nodeid_t node,
-                                           u64 addr, int extcode, octlet_t *data,
-					   octlet_t arg)
+struct hpsb_packet *hpsb_make_lock64packet(struct hpsb_host *host,
+					   nodeid_t node, u64 addr, int extcode,
+					   octlet_t * data, octlet_t arg)
 {
 	struct hpsb_packet *p;
 	u32 length;
 
 	p = hpsb_alloc_packet(16);
-	if (!p) return NULL;
+	if (!p)
+		return NULL;
 
 	p->host = host;
 	p->node_id = node;
@@ -429,18 +432,18 @@ struct hpsb_packet *hpsb_make_lock64packet(struct hpsb_host *host, nodeid_t node
 	return p;
 }
 
-struct hpsb_packet *hpsb_make_phypacket(struct hpsb_host *host,
-                                        quadlet_t data)
+struct hpsb_packet *hpsb_make_phypacket(struct hpsb_host *host, quadlet_t data)
 {
-        struct hpsb_packet *p;
+	struct hpsb_packet *p;
 
-        p = hpsb_alloc_packet(0);
-        if (!p) return NULL;
+	p = hpsb_alloc_packet(0);
+	if (!p)
+		return NULL;
 
-        p->host = host;
-        fill_phy_packet(p, data);
+	p->host = host;
+	fill_phy_packet(p, data);
 
-        return p;
+	return p;
 }
 
 struct hpsb_packet *hpsb_make_isopacket(struct hpsb_host *host,
@@ -450,7 +453,8 @@ struct hpsb_packet *hpsb_make_isopacket(struct hpsb_host *host,
 	struct hpsb_packet *p;
 
 	p = hpsb_alloc_packet(length);
-	if (!p) return NULL;
+	if (!p)
+		return NULL;
 
 	p->host = host;
 	fill_iso_packet(p, length, channel, tag, sync);
@@ -466,47 +470,46 @@ struct hpsb_packet *hpsb_make_isopacket(struct hpsb_host *host,
  */
 
 int hpsb_read(struct hpsb_host *host, nodeid_t node, unsigned int generation,
-	      u64 addr, quadlet_t *buffer, size_t length)
+	      u64 addr, quadlet_t * buffer, size_t length)
 {
-        struct hpsb_packet *packet;
-        int retval = 0;
+	struct hpsb_packet *packet;
+	int retval = 0;
 
-        if (length == 0)
-                return -EINVAL;
+	if (length == 0)
+		return -EINVAL;
 
-	BUG_ON(in_interrupt()); // We can't be called in an interrupt, yet
+	BUG_ON(in_interrupt());	// We can't be called in an interrupt, yet
 
 	packet = hpsb_make_readpacket(host, node, addr, length);
 
-        if (!packet) {
-                return -ENOMEM;
-        }
+	if (!packet) {
+		return -ENOMEM;
+	}
 
 	packet->generation = generation;
-        retval = hpsb_send_packet_and_wait(packet);
+	retval = hpsb_send_packet_and_wait(packet);
 	if (retval < 0)
 		goto hpsb_read_fail;
 
-        retval = hpsb_packet_success(packet);
+	retval = hpsb_packet_success(packet);
 
-        if (retval == 0) {
-                if (length == 4) {
-                        *buffer = packet->header[3];
-                } else {
-                        memcpy(buffer, packet->data, length);
-                }
-        }
+	if (retval == 0) {
+		if (length == 4) {
+			*buffer = packet->header[3];
+		} else {
+			memcpy(buffer, packet->data, length);
+		}
+	}
 
-hpsb_read_fail:
-        hpsb_free_tlabel(packet);
-        hpsb_free_packet(packet);
+      hpsb_read_fail:
+	hpsb_free_tlabel(packet);
+	hpsb_free_packet(packet);
 
-        return retval;
+	return retval;
 }
 
-
 int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation,
-	       u64 addr, quadlet_t *buffer, size_t length)
+	       u64 addr, quadlet_t * buffer, size_t length)
 {
 	struct hpsb_packet *packet;
 	int retval;
@@ -514,62 +517,61 @@ int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation,
 	if (length == 0)
 		return -EINVAL;
 
-	BUG_ON(in_interrupt()); // We can't be called in an interrupt, yet
+	BUG_ON(in_interrupt());	// We can't be called in an interrupt, yet
 
-	packet = hpsb_make_writepacket (host, node, addr, buffer, length);
+	packet = hpsb_make_writepacket(host, node, addr, buffer, length);
 
 	if (!packet)
 		return -ENOMEM;
 
 	packet->generation = generation;
-        retval = hpsb_send_packet_and_wait(packet);
+	retval = hpsb_send_packet_and_wait(packet);
 	if (retval < 0)
 		goto hpsb_write_fail;
 
-        retval = hpsb_packet_success(packet);
+	retval = hpsb_packet_success(packet);
 
-hpsb_write_fail:
-        hpsb_free_tlabel(packet);
-        hpsb_free_packet(packet);
+      hpsb_write_fail:
+	hpsb_free_tlabel(packet);
+	hpsb_free_packet(packet);
 
-        return retval;
+	return retval;
 }
 
 #if 0
 
 int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation,
-	      u64 addr, int extcode, quadlet_t *data, quadlet_t arg)
+	      u64 addr, int extcode, quadlet_t * data, quadlet_t arg)
 {
-        struct hpsb_packet *packet;
-        int retval = 0;
+	struct hpsb_packet *packet;
+	int retval = 0;
 
-	BUG_ON(in_interrupt()); // We can't be called in an interrupt, yet
+	BUG_ON(in_interrupt());	// We can't be called in an interrupt, yet
 
 	packet = hpsb_make_lockpacket(host, node, addr, extcode, data, arg);
-        if (!packet)
-                return -ENOMEM;
+	if (!packet)
+		return -ENOMEM;
 
 	packet->generation = generation;
-        retval = hpsb_send_packet_and_wait(packet);
+	retval = hpsb_send_packet_and_wait(packet);
 	if (retval < 0)
 		goto hpsb_lock_fail;
 
-        retval = hpsb_packet_success(packet);
+	retval = hpsb_packet_success(packet);
 
-        if (retval == 0) {
-                *data = packet->data[0];
-        }
+	if (retval == 0) {
+		*data = packet->data[0];
+	}
 
-hpsb_lock_fail:
-        hpsb_free_tlabel(packet);
-        hpsb_free_packet(packet);
+      hpsb_lock_fail:
+	hpsb_free_tlabel(packet);
+	hpsb_free_packet(packet);
 
-        return retval;
+	return retval;
 }
 
-
 int hpsb_send_gasp(struct hpsb_host *host, int channel, unsigned int generation,
-		   quadlet_t *buffer, size_t length, u32 specifier_id,
+		   quadlet_t * buffer, size_t length, u32 specifier_id,
 		   unsigned int version)
 {
 	struct hpsb_packet *packet;
@@ -586,7 +588,8 @@ int hpsb_send_gasp(struct hpsb_host *host, int channel, unsigned int generation,
 		return -ENOMEM;
 
 	packet->data[0] = cpu_to_be32((host->node_id << 16) | specifier_id_hi);
-	packet->data[1] = cpu_to_be32((specifier_id_lo << 24) | (version & 0x00ffffff));
+	packet->data[1] =
+	    cpu_to_be32((specifier_id_lo << 24) | (version & 0x00ffffff));
 
 	memcpy(&(packet->data[2]), buffer, length - 8);
 
@@ -601,4 +604,4 @@ int hpsb_send_gasp(struct hpsb_host *host, int channel, unsigned int generation,
 	return retval;
 }
 
-#endif  /*  0  */
+#endif				/*  0  */
diff --git a/drivers/ieee1394/iso.c b/drivers/ieee1394/iso.c
index 615541b8b90f..f26680ebef7c 100644
--- a/drivers/ieee1394/iso.c
+++ b/drivers/ieee1394/iso.c
@@ -36,20 +36,22 @@ void hpsb_iso_shutdown(struct hpsb_iso *iso)
 	kfree(iso);
 }
 
-static struct hpsb_iso* hpsb_iso_common_init(struct hpsb_host *host, enum hpsb_iso_type type,
+static struct hpsb_iso *hpsb_iso_common_init(struct hpsb_host *host,
+					     enum hpsb_iso_type type,
 					     unsigned int data_buf_size,
 					     unsigned int buf_packets,
-					     int channel,
-					     int dma_mode,
+					     int channel, int dma_mode,
 					     int irq_interval,
-					     void (*callback)(struct hpsb_iso*))
+					     void (*callback) (struct hpsb_iso
+							       *))
 {
 	struct hpsb_iso *iso;
 	int dma_direction;
 
 	/* make sure driver supports the ISO API */
 	if (!host->driver->isoctl) {
-		printk(KERN_INFO "ieee1394: host driver '%s' does not support the rawiso API\n",
+		printk(KERN_INFO
+		       "ieee1394: host driver '%s' does not support the rawiso API\n",
 		       host->driver->name);
 		return NULL;
 	}
@@ -59,12 +61,13 @@ static struct hpsb_iso* hpsb_iso_common_init(struct hpsb_host *host, enum hpsb_i
 	if (buf_packets < 2)
 		buf_packets = 2;
 
-	if ((dma_mode < HPSB_ISO_DMA_DEFAULT) || (dma_mode > HPSB_ISO_DMA_PACKET_PER_BUFFER))
-		dma_mode=HPSB_ISO_DMA_DEFAULT;
+	if ((dma_mode < HPSB_ISO_DMA_DEFAULT)
+	    || (dma_mode > HPSB_ISO_DMA_PACKET_PER_BUFFER))
+		dma_mode = HPSB_ISO_DMA_DEFAULT;
 
 	if ((irq_interval < 0) || (irq_interval > buf_packets / 4))
- 		irq_interval = buf_packets / 4;
-	if (irq_interval == 0)     /* really interrupt for each packet*/
+		irq_interval = buf_packets / 4;
+	if (irq_interval == 0)	/* really interrupt for each packet */
 		irq_interval = 1;
 
 	if (channel < -1 || channel >= 64)
@@ -76,7 +79,10 @@ static struct hpsb_iso* hpsb_iso_common_init(struct hpsb_host *host, enum hpsb_i
 
 	/* allocate and write the struct hpsb_iso */
 
-	iso = kmalloc(sizeof(*iso) + buf_packets * sizeof(struct hpsb_iso_packet_info), GFP_KERNEL);
+	iso =
+	    kmalloc(sizeof(*iso) +
+		    buf_packets * sizeof(struct hpsb_iso_packet_info),
+		    GFP_KERNEL);
 	if (!iso)
 		return NULL;
 
@@ -111,17 +117,18 @@ static struct hpsb_iso* hpsb_iso_common_init(struct hpsb_host *host, enum hpsb_i
 	iso->prebuffer = 0;
 
 	/* allocate the packet buffer */
-	if (dma_region_alloc(&iso->data_buf, iso->buf_size, host->pdev, dma_direction))
+	if (dma_region_alloc
+	    (&iso->data_buf, iso->buf_size, host->pdev, dma_direction))
 		goto err;
 
 	return iso;
 
-err:
+      err:
 	hpsb_iso_shutdown(iso);
 	return NULL;
 }
 
-int hpsb_iso_n_ready(struct hpsb_iso* iso)
+int hpsb_iso_n_ready(struct hpsb_iso *iso)
 {
 	unsigned long flags;
 	int val;
@@ -133,18 +140,19 @@ int hpsb_iso_n_ready(struct hpsb_iso* iso)
 	return val;
 }
 
-
-struct hpsb_iso* hpsb_iso_xmit_init(struct hpsb_host *host,
+struct hpsb_iso *hpsb_iso_xmit_init(struct hpsb_host *host,
 				    unsigned int data_buf_size,
 				    unsigned int buf_packets,
 				    int channel,
 				    int speed,
 				    int irq_interval,
-				    void (*callback)(struct hpsb_iso*))
+				    void (*callback) (struct hpsb_iso *))
 {
 	struct hpsb_iso *iso = hpsb_iso_common_init(host, HPSB_ISO_XMIT,
 						    data_buf_size, buf_packets,
-						    channel, HPSB_ISO_DMA_DEFAULT, irq_interval, callback);
+						    channel,
+						    HPSB_ISO_DMA_DEFAULT,
+						    irq_interval, callback);
 	if (!iso)
 		return NULL;
 
@@ -157,22 +165,23 @@ struct hpsb_iso* hpsb_iso_xmit_init(struct hpsb_host *host,
 	iso->flags |= HPSB_ISO_DRIVER_INIT;
 	return iso;
 
-err:
+      err:
 	hpsb_iso_shutdown(iso);
 	return NULL;
 }
 
-struct hpsb_iso* hpsb_iso_recv_init(struct hpsb_host *host,
+struct hpsb_iso *hpsb_iso_recv_init(struct hpsb_host *host,
 				    unsigned int data_buf_size,
 				    unsigned int buf_packets,
 				    int channel,
 				    int dma_mode,
 				    int irq_interval,
-				    void (*callback)(struct hpsb_iso*))
+				    void (*callback) (struct hpsb_iso *))
 {
 	struct hpsb_iso *iso = hpsb_iso_common_init(host, HPSB_ISO_RECV,
 						    data_buf_size, buf_packets,
-						    channel, dma_mode, irq_interval, callback);
+						    channel, dma_mode,
+						    irq_interval, callback);
 	if (!iso)
 		return NULL;
 
@@ -183,7 +192,7 @@ struct hpsb_iso* hpsb_iso_recv_init(struct hpsb_host *host,
 	iso->flags |= HPSB_ISO_DRIVER_INIT;
 	return iso;
 
-err:
+      err:
 	hpsb_iso_shutdown(iso);
 	return NULL;
 }
@@ -197,16 +206,17 @@ int hpsb_iso_recv_listen_channel(struct hpsb_iso *iso, unsigned char channel)
 
 int hpsb_iso_recv_unlisten_channel(struct hpsb_iso *iso, unsigned char channel)
 {
-       if (iso->type != HPSB_ISO_RECV || iso->channel != -1 || channel >= 64)
-               return -EINVAL;
-       return iso->host->driver->isoctl(iso, RECV_UNLISTEN_CHANNEL, channel);
+	if (iso->type != HPSB_ISO_RECV || iso->channel != -1 || channel >= 64)
+		return -EINVAL;
+	return iso->host->driver->isoctl(iso, RECV_UNLISTEN_CHANNEL, channel);
 }
 
 int hpsb_iso_recv_set_channel_mask(struct hpsb_iso *iso, u64 mask)
 {
 	if (iso->type != HPSB_ISO_RECV || iso->channel != -1)
 		return -EINVAL;
-	return iso->host->driver->isoctl(iso, RECV_SET_CHANNEL_MASK, (unsigned long) &mask);
+	return iso->host->driver->isoctl(iso, RECV_SET_CHANNEL_MASK,
+					 (unsigned long)&mask);
 }
 
 int hpsb_iso_recv_flush(struct hpsb_iso *iso)
@@ -283,7 +293,9 @@ int hpsb_iso_recv_start(struct hpsb_iso *iso, int cycle, int tag_mask, int sync)
 
 	isoctl_args[2] = sync;
 
-	retval = iso->host->driver->isoctl(iso, RECV_START, (unsigned long) &isoctl_args[0]);
+	retval =
+	    iso->host->driver->isoctl(iso, RECV_START,
+				      (unsigned long)&isoctl_args[0]);
 	if (retval)
 		return retval;
 
@@ -296,7 +308,8 @@ int hpsb_iso_recv_start(struct hpsb_iso *iso, int cycle, int tag_mask, int sync)
 
 static int hpsb_iso_check_offset_len(struct hpsb_iso *iso,
 				     unsigned int offset, unsigned short len,
-				     unsigned int *out_offset, unsigned short *out_len)
+				     unsigned int *out_offset,
+				     unsigned short *out_len)
 {
 	if (offset >= iso->buf_size)
 		return -EFAULT;
@@ -316,8 +329,8 @@ static int hpsb_iso_check_offset_len(struct hpsb_iso *iso,
 	return 0;
 }
 
-
-int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len, u8 tag, u8 sy)
+int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len,
+			       u8 tag, u8 sy)
 {
 	struct hpsb_iso_packet_info *info;
 	unsigned long flags;
@@ -334,7 +347,8 @@ int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len, u8 tag
 	info = &iso->infos[iso->first_packet];
 
 	/* check for bogus offset/length */
-	if (hpsb_iso_check_offset_len(iso, offset, len, &info->offset, &info->len))
+	if (hpsb_iso_check_offset_len
+	    (iso, offset, len, &info->offset, &info->len))
 		return -EFAULT;
 
 	info->tag = tag;
@@ -342,13 +356,13 @@ int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len, u8 tag
 
 	spin_lock_irqsave(&iso->lock, flags);
 
-	rv = iso->host->driver->isoctl(iso, XMIT_QUEUE, (unsigned long) info);
+	rv = iso->host->driver->isoctl(iso, XMIT_QUEUE, (unsigned long)info);
 	if (rv)
 		goto out;
 
 	/* increment cursors */
-	iso->first_packet = (iso->first_packet+1) % iso->buf_packets;
-	iso->xmit_cycle = (iso->xmit_cycle+1) % 8000;
+	iso->first_packet = (iso->first_packet + 1) % iso->buf_packets;
+	iso->xmit_cycle = (iso->xmit_cycle + 1) % 8000;
 	iso->n_ready_packets--;
 
 	if (iso->prebuffer != 0) {
@@ -359,7 +373,7 @@ int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len, u8 tag
 		}
 	}
 
-out:
+      out:
 	spin_unlock_irqrestore(&iso->lock, flags);
 	return rv;
 }
@@ -369,7 +383,9 @@ int hpsb_iso_xmit_sync(struct hpsb_iso *iso)
 	if (iso->type != HPSB_ISO_XMIT)
 		return -EINVAL;
 
-	return wait_event_interruptible(iso->waitq, hpsb_iso_n_ready(iso) == iso->buf_packets);
+	return wait_event_interruptible(iso->waitq,
+					hpsb_iso_n_ready(iso) ==
+					iso->buf_packets);
 }
 
 void hpsb_iso_packet_sent(struct hpsb_iso *iso, int cycle, int error)
@@ -396,7 +412,8 @@ void hpsb_iso_packet_sent(struct hpsb_iso *iso, int cycle, int error)
 }
 
 void hpsb_iso_packet_received(struct hpsb_iso *iso, u32 offset, u16 len,
-			      u16 total_len, u16 cycle, u8 channel, u8 tag, u8 sy)
+			      u16 total_len, u16 cycle, u8 channel, u8 tag,
+			      u8 sy)
 {
 	unsigned long flags;
 	spin_lock_irqsave(&iso->lock, flags);
@@ -416,7 +433,7 @@ void hpsb_iso_packet_received(struct hpsb_iso *iso, u32 offset, u16 len,
 		info->tag = tag;
 		info->sy = sy;
 
-		iso->pkt_dma = (iso->pkt_dma+1) % iso->buf_packets;
+		iso->pkt_dma = (iso->pkt_dma + 1) % iso->buf_packets;
 		iso->n_ready_packets++;
 	}
 
@@ -435,20 +452,21 @@ int hpsb_iso_recv_release_packets(struct hpsb_iso *iso, unsigned int n_packets)
 	spin_lock_irqsave(&iso->lock, flags);
 	for (i = 0; i < n_packets; i++) {
 		rv = iso->host->driver->isoctl(iso, RECV_RELEASE,
-					       (unsigned long) &iso->infos[iso->first_packet]);
+					       (unsigned long)&iso->infos[iso->
+									  first_packet]);
 		if (rv)
 			break;
 
-		iso->first_packet = (iso->first_packet+1) % iso->buf_packets;
+		iso->first_packet = (iso->first_packet + 1) % iso->buf_packets;
 		iso->n_ready_packets--;
 
 		/* release memory from packets discarded when queue was full  */
-		if (iso->n_ready_packets == 0) { /* Release only after all prior packets handled */
+		if (iso->n_ready_packets == 0) {	/* Release only after all prior packets handled */
 			if (iso->bytes_discarded != 0) {
 				struct hpsb_iso_packet_info inf;
 				inf.total_len = iso->bytes_discarded;
 				iso->host->driver->isoctl(iso, RECV_RELEASE,
-							(unsigned long) &inf);
+							  (unsigned long)&inf);
 				iso->bytes_discarded = 0;
 			}
 		}
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
index 0ea37b1bccb2..082c7fd239f5 100644
--- a/drivers/ieee1394/nodemgr.c
+++ b/drivers/ieee1394/nodemgr.c
@@ -121,8 +121,8 @@ struct host_info {
 };
 
 static int nodemgr_bus_match(struct device * dev, struct device_driver * drv);
-static int nodemgr_hotplug(struct class_device *cdev, char **envp, int num_envp,
-			   char *buffer, int buffer_size);
+static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp,
+			  char *buffer, int buffer_size);
 static void nodemgr_resume_ne(struct node_entry *ne);
 static void nodemgr_remove_ne(struct node_entry *ne);
 static struct node_entry *find_entry_by_guid(u64 guid);
@@ -162,7 +162,7 @@ static void ud_cls_release(struct class_device *class_dev)
 static struct class nodemgr_ud_class = {
 	.name		= "ieee1394",
 	.release	= ud_cls_release,
-	.hotplug	= nodemgr_hotplug,
+	.uevent		= nodemgr_uevent,
 };
 
 static struct hpsb_highlevel nodemgr_highlevel;
@@ -743,21 +743,20 @@ static struct node_entry *nodemgr_create_node(octlet_t guid, struct csr1212_csr
 					      unsigned int generation)
 {
 	struct hpsb_host *host = hi->host;
-        struct node_entry *ne;
-
-	ne = kmalloc(sizeof(struct node_entry), GFP_KERNEL);
-        if (!ne) return NULL;
+	struct node_entry *ne;
 
-	memset(ne, 0, sizeof(struct node_entry));
+	ne = kzalloc(sizeof(*ne), GFP_KERNEL);
+	if (!ne)
+		return NULL;
 
 	ne->tpool = &host->tpool[nodeid & NODE_MASK];
 
-        ne->host = host;
-        ne->nodeid = nodeid;
+	ne->host = host;
+	ne->nodeid = nodeid;
 	ne->generation = generation;
 	ne->needs_probe = 1;
 
-        ne->guid = guid;
+	ne->guid = guid;
 	ne->guid_vendor_id = (guid >> 40) & 0xffffff;
 	ne->guid_vendor_oui = nodemgr_find_oui_name(ne->guid_vendor_id);
 	ne->csr = csr;
@@ -787,7 +786,7 @@ static struct node_entry *nodemgr_create_node(octlet_t guid, struct csr1212_csr
 		   (host->node_id == nodeid) ? "Host" : "Node",
 		   NODE_BUS_ARGS(host, nodeid), (unsigned long long)guid);
 
-        return ne;
+	return ne;
 }
 
 
@@ -872,12 +871,10 @@ static struct unit_directory *nodemgr_process_unit_directory
 	struct csr1212_keyval *kv;
 	u8 last_key_id = 0;
 
-	ud = kmalloc(sizeof(struct unit_directory), GFP_KERNEL);
+	ud = kzalloc(sizeof(*ud), GFP_KERNEL);
 	if (!ud)
 		goto unit_directory_error;
 
-	memset (ud, 0, sizeof(struct unit_directory));
-
 	ud->ne = ne;
 	ud->ignore_driver = ignore_drivers;
 	ud->address = ud_kv->offset + CSR1212_CONFIG_ROM_SPACE_BASE;
@@ -937,10 +934,10 @@ static struct unit_directory *nodemgr_process_unit_directory
 			/* Logical Unit Number */
 			if (kv->key.type == CSR1212_KV_TYPE_IMMEDIATE) {
 				if (ud->flags & UNIT_DIRECTORY_HAS_LUN) {
-					ud_child = kmalloc(sizeof(struct unit_directory), GFP_KERNEL);
+					ud_child = kmalloc(sizeof(*ud_child), GFP_KERNEL);
 					if (!ud_child)
 						goto unit_directory_error;
-					memcpy(ud_child, ud, sizeof(struct unit_directory));
+					memcpy(ud_child, ud, sizeof(*ud_child));
 					nodemgr_register_device(ne, ud_child, &ne->device);
 					ud_child = NULL;
 					
@@ -966,7 +963,7 @@ static struct unit_directory *nodemgr_process_unit_directory
 				if (ud_child == NULL)
 					break;
 				
-				/* inherit unspecified values so hotplug picks it up */
+				/* inherit unspecified values, the driver core picks it up */
 				if ((ud->flags & UNIT_DIRECTORY_MODEL_ID) &&
 				    !(ud_child->flags & UNIT_DIRECTORY_MODEL_ID))
 				{
@@ -1062,8 +1059,8 @@ static void nodemgr_process_root_directory(struct host_info *hi, struct node_ent
 
 #ifdef CONFIG_HOTPLUG
 
-static int nodemgr_hotplug(struct class_device *cdev, char **envp, int num_envp,
-			   char *buffer, int buffer_size)
+static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp,
+			  char *buffer, int buffer_size)
 {
 	struct unit_directory *ud;
 	int i = 0;
@@ -1112,8 +1109,8 @@ do {								\
 
 #else
 
-static int nodemgr_hotplug(struct class_device *cdev, char **envp, int num_envp,
-			   char *buffer, int buffer_size)
+static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp,
+			  char *buffer, int buffer_size)
 {
 	return -ENODEV;
 }
@@ -1200,7 +1197,7 @@ static void nodemgr_node_scan_one(struct host_info *hi,
 	struct csr1212_csr *csr;
 	struct nodemgr_csr_info *ci;
 
-	ci = kmalloc(sizeof(struct nodemgr_csr_info), GFP_KERNEL);
+	ci = kmalloc(sizeof(*ci), GFP_KERNEL);
 	if (!ci)
 		return;
 
@@ -1410,14 +1407,28 @@ static void nodemgr_node_probe(struct host_info *hi, int generation)
 	struct hpsb_host *host = hi->host;
 	struct class *class = &nodemgr_ne_class;
 	struct class_device *cdev;
+	struct node_entry *ne;
 
 	/* Do some processing of the nodes we've probed. This pulls them
 	 * into the sysfs layer if needed, and can result in processing of
 	 * unit-directories, or just updating the node and it's
-	 * unit-directories. */
+	 * unit-directories.
+	 *
+	 * Run updates before probes. Usually, updates are time-critical
+	 * while probes are time-consuming. (Well, those probes need some
+	 * improvement...) */
+
 	down_read(&class->subsys.rwsem);
-	list_for_each_entry(cdev, &class->children, node)
-		nodemgr_probe_ne(hi, container_of(cdev, struct node_entry, class_dev), generation);
+	list_for_each_entry(cdev, &class->children, node) {
+		ne = container_of(cdev, struct node_entry, class_dev);
+		if (!ne->needs_probe)
+			nodemgr_probe_ne(hi, ne, generation);
+	}
+	list_for_each_entry(cdev, &class->children, node) {
+		ne = container_of(cdev, struct node_entry, class_dev);
+		if (ne->needs_probe)
+			nodemgr_probe_ne(hi, ne, generation);
+	}
         up_read(&class->subsys.rwsem);
 
 
@@ -1448,7 +1459,8 @@ static int nodemgr_send_resume_packet(struct hpsb_host *host)
 	int ret = 1;
 
 	packet = hpsb_make_phypacket(host,
-			0x003c0000 | NODEID_TO_NODE(host->node_id) << 24);
+			EXTPHYPACKET_TYPE_RESUME |
+			NODEID_TO_NODE(host->node_id) << PHYPACKET_PORT_SHIFT);
 	if (packet) {
 		packet->no_waiter = 1;
 		packet->generation = get_hpsb_generation(host);
@@ -1618,8 +1630,8 @@ static int nodemgr_host_thread(void *__hi)
 
 		/* Scan our nodes to get the bus options and create node
 		 * entries. This does not do the sysfs stuff, since that
-		 * would trigger hotplug callbacks and such, which is a
-		 * bad idea at this point. */
+		 * would trigger uevents and such, which is a bad idea at
+		 * this point. */
 		nodemgr_node_scan(hi, generation);
 
 		/* This actually does the full probe, with sysfs
diff --git a/drivers/ieee1394/nodemgr.h b/drivers/ieee1394/nodemgr.h
index 3a2f0c02fd08..0b26616e16c3 100644
--- a/drivers/ieee1394/nodemgr.h
+++ b/drivers/ieee1394/nodemgr.h
@@ -151,24 +151,6 @@ static inline int hpsb_node_entry_valid(struct node_entry *ne)
 }
 
 /*
- * Returns a node entry (which has its reference count incremented) or NULL if
- * the GUID in question is not known.  Getting a valid entry does not mean that
- * the node with this GUID is currently accessible (might be powered down).
- */
-struct node_entry *hpsb_guid_get_entry(u64 guid);
-
-/* Same as above, but use the nodeid to get an node entry. This is not
- * fool-proof by itself, since the nodeid can change.  */
-struct node_entry *hpsb_nodeid_get_entry(struct hpsb_host *host, nodeid_t nodeid);
-
-/*
- * If the entry refers to a local host, this function will return the pointer
- * to the hpsb_host structure.  It will return NULL otherwise.  Once you have
- * established it is a local host, you can use that knowledge from then on (the
- * GUID won't wander to an external node).  */
-struct hpsb_host *hpsb_get_host_by_ne(struct node_entry *ne);
-
-/*
  * This will fill in the given, pre-initialised hpsb_packet with the current
  * information from the node entry (host, node ID, generation number).  It will
  * return false if the node owning the GUID is not accessible (and not modify the
diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c
index 4cf9b8f3e336..b6b96fa04d62 100644
--- a/drivers/ieee1394/ohci1394.c
+++ b/drivers/ieee1394/ohci1394.c
@@ -161,9 +161,6 @@ printk(level "%s: " fmt "\n" , OHCI1394_DRIVER_NAME , ## args)
 #define PRINT(level, fmt, args...) \
 printk(level "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, ohci->host->id , ## args)
 
-static char version[] __devinitdata =
-	"$Rev: 1313 $ Ben Collins <bcollins@debian.org>";
-
 /* Module Parameters */
 static int phys_dma = 1;
 module_param(phys_dma, int, 0644);
@@ -587,12 +584,13 @@ static void ohci_initialize(struct ti_ohci *ohci)
 	sprintf (irq_buf, "%s", __irq_itoa(ohci->dev->irq));
 #endif
 	PRINT(KERN_INFO, "OHCI-1394 %d.%d (PCI): IRQ=[%s]  "
-	      "MMIO=[%lx-%lx]  Max Packet=[%d]",
+	      "MMIO=[%lx-%lx]  Max Packet=[%d]  IR/IT contexts=[%d/%d]",
 	      ((((buf) >> 16) & 0xf) + (((buf) >> 20) & 0xf) * 10),
 	      ((((buf) >> 4) & 0xf) + ((buf) & 0xf) * 10), irq_buf,
 	      pci_resource_start(ohci->dev, 0),
 	      pci_resource_start(ohci->dev, 0) + OHCI1394_REGISTER_SIZE - 1,
-	      ohci->max_packet_size);
+	      ohci->max_packet_size,
+	      ohci->nb_iso_rcv_ctx, ohci->nb_iso_xmit_ctx);
 
 	/* Check all of our ports to make sure that if anything is
 	 * connected, we enable that port. */
@@ -2960,28 +2958,23 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d,
 	d->ctrlClear = 0;
 	d->cmdPtr = 0;
 
-	d->buf_cpu = kmalloc(d->num_desc * sizeof(quadlet_t*), GFP_ATOMIC);
-	d->buf_bus = kmalloc(d->num_desc * sizeof(dma_addr_t), GFP_ATOMIC);
+	d->buf_cpu = kzalloc(d->num_desc * sizeof(*d->buf_cpu), GFP_ATOMIC);
+	d->buf_bus = kzalloc(d->num_desc * sizeof(*d->buf_bus), GFP_ATOMIC);
 
 	if (d->buf_cpu == NULL || d->buf_bus == NULL) {
 		PRINT(KERN_ERR, "Failed to allocate dma buffer");
 		free_dma_rcv_ctx(d);
 		return -ENOMEM;
 	}
-	memset(d->buf_cpu, 0, d->num_desc * sizeof(quadlet_t*));
-	memset(d->buf_bus, 0, d->num_desc * sizeof(dma_addr_t));
 
-	d->prg_cpu = kmalloc(d->num_desc * sizeof(struct dma_cmd*),
-				GFP_ATOMIC);
-	d->prg_bus = kmalloc(d->num_desc * sizeof(dma_addr_t), GFP_ATOMIC);
+	d->prg_cpu = kzalloc(d->num_desc * sizeof(*d->prg_cpu), GFP_ATOMIC);
+	d->prg_bus = kzalloc(d->num_desc * sizeof(*d->prg_bus), GFP_ATOMIC);
 
 	if (d->prg_cpu == NULL || d->prg_bus == NULL) {
 		PRINT(KERN_ERR, "Failed to allocate dma prg");
 		free_dma_rcv_ctx(d);
 		return -ENOMEM;
 	}
-	memset(d->prg_cpu, 0, d->num_desc * sizeof(struct dma_cmd*));
-	memset(d->prg_bus, 0, d->num_desc * sizeof(dma_addr_t));
 
 	d->spb = kmalloc(d->split_buf_size, GFP_ATOMIC);
 
@@ -3093,17 +3086,14 @@ alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d,
 	d->ctrlClear = 0;
 	d->cmdPtr = 0;
 
-	d->prg_cpu = kmalloc(d->num_desc * sizeof(struct at_dma_prg*),
-			     GFP_KERNEL);
-	d->prg_bus = kmalloc(d->num_desc * sizeof(dma_addr_t), GFP_KERNEL);
+	d->prg_cpu = kzalloc(d->num_desc * sizeof(*d->prg_cpu), GFP_KERNEL);
+	d->prg_bus = kzalloc(d->num_desc * sizeof(*d->prg_bus), GFP_KERNEL);
 
 	if (d->prg_cpu == NULL || d->prg_bus == NULL) {
 		PRINT(KERN_ERR, "Failed to allocate at dma prg");
 		free_dma_trm_ctx(d);
 		return -ENOMEM;
 	}
-	memset(d->prg_cpu, 0, d->num_desc * sizeof(struct at_dma_prg*));
-	memset(d->prg_bus, 0, d->num_desc * sizeof(dma_addr_t));
 
 	len = sprintf(pool_name, "ohci1394_trm_prg");
 	sprintf(pool_name+len, "%d", num_allocs);
@@ -3201,8 +3191,6 @@ static struct hpsb_host_driver ohci1394_driver = {
 	.hw_csr_reg =		ohci_hw_csr_reg,
 };
 
-
-
 /***********************************
  * PCI Driver Interface functions  *
  ***********************************/
@@ -3217,15 +3205,10 @@ do {						\
 static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
 					const struct pci_device_id *ent)
 {
-	static int version_printed = 0;
-
 	struct hpsb_host *host;
 	struct ti_ohci *ohci;	/* shortcut to currently handled device */
 	unsigned long ohci_base;
 
-	if (version_printed++ == 0)
-		PRINT_G(KERN_INFO, "%s", version);
-
         if (pci_enable_device(dev))
 		FAIL(-ENXIO, "Failed to enable OHCI hardware");
         pci_set_master(dev);
@@ -3369,13 +3352,8 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
 	/* Determine the number of available IR and IT contexts. */
 	ohci->nb_iso_rcv_ctx =
 		get_nb_iso_ctx(ohci, OHCI1394_IsoRecvIntMaskSet);
-	DBGMSG("%d iso receive contexts available",
-	       ohci->nb_iso_rcv_ctx);
-
 	ohci->nb_iso_xmit_ctx =
 		get_nb_iso_ctx(ohci, OHCI1394_IsoXmitIntMaskSet);
-	DBGMSG("%d iso transmit contexts available",
-	       ohci->nb_iso_xmit_ctx);
 
 	/* Set the usage bits for non-existent contexts so they can't
 	 * be allocated */
@@ -3606,8 +3584,6 @@ static struct pci_driver ohci1394_pci_driver = {
 	.suspend =	ohci1394_pci_suspend,
 };
 
-
-
 /***********************************
  * OHCI1394 Video Interface        *
  ***********************************/
@@ -3714,7 +3690,6 @@ EXPORT_SYMBOL(ohci1394_init_iso_tasklet);
 EXPORT_SYMBOL(ohci1394_register_iso_tasklet);
 EXPORT_SYMBOL(ohci1394_unregister_iso_tasklet);
 
-
 /***********************************
  * General module initialization   *
  ***********************************/
diff --git a/drivers/ieee1394/ohci1394.h b/drivers/ieee1394/ohci1394.h
index cc66c1cae250..7df0962144e3 100644
--- a/drivers/ieee1394/ohci1394.h
+++ b/drivers/ieee1394/ohci1394.h
@@ -219,8 +219,8 @@ struct ti_ohci {
 
 	int self_id_errors;
 
-	/* Tasklets for iso receive and transmit, used by video1394,
-	 * amdtp and dv1394 */
+	/* Tasklets for iso receive and transmit, used by video1394
+	 * and dv1394 */
 
 	struct list_head iso_tasklet_list;
 	spinlock_t iso_tasklet_list_lock;
diff --git a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c
index 6b1ab875333b..e2edc41e1b6f 100644
--- a/drivers/ieee1394/pcilynx.c
+++ b/drivers/ieee1394/pcilynx.c
@@ -1435,7 +1435,7 @@ static int __devinit add_card(struct pci_dev *dev,
         	struct i2c_algo_bit_data i2c_adapter_data;
 
         	error = -ENOMEM;
-		i2c_ad = kmalloc(sizeof(struct i2c_adapter), SLAB_KERNEL);
+		i2c_ad = kmalloc(sizeof(*i2c_ad), SLAB_KERNEL);
         	if (!i2c_ad) FAIL("failed to allocate I2C adapter memory");
 
 		memcpy(i2c_ad, &bit_ops, sizeof(struct i2c_adapter));
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
index 24411e666b21..b05235639918 100644
--- a/drivers/ieee1394/raw1394.c
+++ b/drivers/ieee1394/raw1394.c
@@ -102,12 +102,9 @@ static struct pending_request *__alloc_pending_request(gfp_t flags)
 {
 	struct pending_request *req;
 
-	req = (struct pending_request *)kmalloc(sizeof(struct pending_request),
-						flags);
-	if (req != NULL) {
-		memset(req, 0, sizeof(struct pending_request));
+	req = kzalloc(sizeof(*req), flags);
+	if (req)
 		INIT_LIST_HEAD(&req->list);
-	}
 
 	return req;
 }
@@ -192,9 +189,9 @@ static void add_host(struct hpsb_host *host)
 	struct host_info *hi;
 	unsigned long flags;
 
-	hi = (struct host_info *)kmalloc(sizeof(struct host_info), GFP_KERNEL);
+	hi = kmalloc(sizeof(*hi), GFP_KERNEL);
 
-	if (hi != NULL) {
+	if (hi) {
 		INIT_LIST_HEAD(&hi->list);
 		hi->host = host;
 		INIT_LIST_HEAD(&hi->file_info_list);
@@ -315,8 +312,8 @@ static void iso_receive(struct hpsb_host *host, int channel, quadlet_t * data,
 				break;
 
 			if (!ibs) {
-				ibs = kmalloc(sizeof(struct iso_block_store)
-					      + length, SLAB_ATOMIC);
+				ibs = kmalloc(sizeof(*ibs) + length,
+					      SLAB_ATOMIC);
 				if (!ibs) {
 					kfree(req);
 					break;
@@ -376,8 +373,8 @@ static void fcp_request(struct hpsb_host *host, int nodeid, int direction,
 				break;
 
 			if (!ibs) {
-				ibs = kmalloc(sizeof(struct iso_block_store)
-					      + length, SLAB_ATOMIC);
+				ibs = kmalloc(sizeof(*ibs) + length,
+					      SLAB_ATOMIC);
 				if (!ibs) {
 					kfree(req);
 					break;
@@ -502,10 +499,9 @@ static int state_initialized(struct file_info *fi, struct pending_request *req)
 	switch (req->req.type) {
 	case RAW1394_REQ_LIST_CARDS:
 		spin_lock_irqsave(&host_info_lock, flags);
-		khl = kmalloc(sizeof(struct raw1394_khost_list) * host_count,
-			      SLAB_ATOMIC);
+		khl = kmalloc(sizeof(*khl) * host_count, SLAB_ATOMIC);
 
-		if (khl != NULL) {
+		if (khl) {
 			req->req.misc = host_count;
 			req->data = (quadlet_t *) khl;
 
@@ -517,7 +513,7 @@ static int state_initialized(struct file_info *fi, struct pending_request *req)
 		}
 		spin_unlock_irqrestore(&host_info_lock, flags);
 
-		if (khl != NULL) {
+		if (khl) {
 			req->req.error = RAW1394_ERROR_NONE;
 			req->req.length = min(req->req.length,
 					      (u32) (sizeof
@@ -1647,13 +1643,13 @@ static int arm_register(struct file_info *fi, struct pending_request *req)
 		return (-EINVAL);
 	}
 	/* addr-list-entry for fileinfo */
-	addr = (struct arm_addr *)kmalloc(sizeof(struct arm_addr), SLAB_KERNEL);
+	addr = kmalloc(sizeof(*addr), SLAB_KERNEL);
 	if (!addr) {
 		req->req.length = 0;
 		return (-ENOMEM);
 	}
 	/* allocation of addr_space_buffer */
-	addr->addr_space_buffer = (u8 *) vmalloc(req->req.length);
+	addr->addr_space_buffer = vmalloc(req->req.length);
 	if (!(addr->addr_space_buffer)) {
 		kfree(addr);
 		req->req.length = 0;
@@ -2122,8 +2118,7 @@ static int modify_config_rom(struct file_info *fi, struct pending_request *req)
 		return -ENOMEM;
 	}
 
-	cache->filled_head =
-	    kmalloc(sizeof(struct csr1212_cache_region), GFP_KERNEL);
+	cache->filled_head = kmalloc(sizeof(*cache->filled_head), GFP_KERNEL);
 	if (!cache->filled_head) {
 		csr1212_release_keyval(fi->csr1212_dirs[dr]);
 		fi->csr1212_dirs[dr] = NULL;
@@ -2136,7 +2131,6 @@ static int modify_config_rom(struct file_info *fi, struct pending_request *req)
 			   req->req.length)) {
 		csr1212_release_keyval(fi->csr1212_dirs[dr]);
 		fi->csr1212_dirs[dr] = NULL;
-		CSR1212_FREE(cache);
 		ret = -EFAULT;
 	} else {
 		cache->len = req->req.length;
@@ -2172,7 +2166,7 @@ static int modify_config_rom(struct file_info *fi, struct pending_request *req)
 		}
 	}
 	kfree(cache->filled_head);
-	kfree(cache);
+	CSR1212_FREE(cache);
 
 	if (ret >= 0) {
 		/* we have to free the request, because we queue no response,
@@ -2488,8 +2482,8 @@ static int raw1394_iso_recv_packets(struct file_info *fi, void __user * uaddr)
 
 	/* ensure user-supplied buffer is accessible and big enough */
 	if (!access_ok(VERIFY_WRITE, upackets.infos,
-			upackets.n_packets *
-			sizeof(struct raw1394_iso_packet_info)))
+		       upackets.n_packets *
+		       sizeof(struct raw1394_iso_packet_info)))
 		return -EFAULT;
 
 	/* copy the packet_infos out */
@@ -2522,8 +2516,8 @@ static int raw1394_iso_send_packets(struct file_info *fi, void __user * uaddr)
 
 	/* ensure user-supplied buffer is accessible and big enough */
 	if (!access_ok(VERIFY_READ, upackets.infos,
-			upackets.n_packets *
-			sizeof(struct raw1394_iso_packet_info)))
+		       upackets.n_packets *
+		       sizeof(struct raw1394_iso_packet_info)))
 		return -EFAULT;
 
 	/* copy the infos structs in and queue the packets */
@@ -2684,11 +2678,10 @@ static int raw1394_open(struct inode *inode, struct file *file)
 {
 	struct file_info *fi;
 
-	fi = kmalloc(sizeof(struct file_info), SLAB_KERNEL);
-	if (fi == NULL)
+	fi = kzalloc(sizeof(*fi), SLAB_KERNEL);
+	if (!fi)
 		return -ENOMEM;
 
-	memset(fi, 0, sizeof(struct file_info));
 	fi->notification = (u8) RAW1394_NOTIFY_ON;	/* busreset notification */
 
 	INIT_LIST_HEAD(&fi->list);
@@ -2748,8 +2741,7 @@ static int raw1394_release(struct inode *inode, struct file *file)
 						    list) {
 					entry = fi_hlp->addr_list.next;
 					while (entry != &(fi_hlp->addr_list)) {
-						arm_addr = list_entry(entry,
-								      struct
+						arm_addr = list_entry(entry, struct
 								      arm_addr,
 								      addr_list);
 						if (arm_addr->start ==
@@ -2912,16 +2904,17 @@ static int __init init_raw1394(void)
 
 	hpsb_register_highlevel(&raw1394_highlevel);
 
-	if (IS_ERR(class_device_create(hpsb_protocol_class, NULL, MKDEV(
-		IEEE1394_MAJOR,	IEEE1394_MINOR_BLOCK_RAW1394 * 16), 
-		NULL, RAW1394_DEVICE_NAME))) {
+	if (IS_ERR
+	    (class_device_create
+	     (hpsb_protocol_class, NULL,
+	      MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16), NULL,
+	      RAW1394_DEVICE_NAME))) {
 		ret = -EFAULT;
 		goto out_unreg;
 	}
-	
-	devfs_mk_cdev(MKDEV(
-		IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16),
-		S_IFCHR | S_IRUSR | S_IWUSR, RAW1394_DEVICE_NAME);
+
+	devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16),
+		      S_IFCHR | S_IRUSR | S_IWUSR, RAW1394_DEVICE_NAME);
 
 	cdev_init(&raw1394_cdev, &raw1394_fops);
 	raw1394_cdev.owner = THIS_MODULE;
@@ -2943,20 +2936,22 @@ static int __init init_raw1394(void)
 
 	goto out;
 
-out_dev:
+      out_dev:
 	devfs_remove(RAW1394_DEVICE_NAME);
 	class_device_destroy(hpsb_protocol_class,
-		MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16));
-out_unreg:
+			     MKDEV(IEEE1394_MAJOR,
+				   IEEE1394_MINOR_BLOCK_RAW1394 * 16));
+      out_unreg:
 	hpsb_unregister_highlevel(&raw1394_highlevel);
-out:
+      out:
 	return ret;
 }
 
 static void __exit cleanup_raw1394(void)
 {
 	class_device_destroy(hpsb_protocol_class,
-		MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16));
+			     MKDEV(IEEE1394_MAJOR,
+				   IEEE1394_MINOR_BLOCK_RAW1394 * 16));
 	cdev_del(&raw1394_cdev);
 	devfs_remove(RAW1394_DEVICE_NAME);
 	hpsb_unregister_highlevel(&raw1394_highlevel);
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index f7e18ccc5c0a..18d7eda38851 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -80,9 +80,6 @@
 #include "ieee1394_transactions.h"
 #include "sbp2.h"
 
-static char version[] __devinitdata =
-	"$Rev: 1306 $ Ben Collins <bcollins@debian.org>";
-
 /*
  * Module load parameter definitions
  */
@@ -151,18 +148,15 @@ static int force_inquiry_hack;
 module_param(force_inquiry_hack, int, 0444);
 MODULE_PARM_DESC(force_inquiry_hack, "Force SCSI inquiry hack (default = 0)");
 
-
 /*
  * Export information about protocols/devices supported by this driver.
  */
 static struct ieee1394_device_id sbp2_id_table[] = {
 	{
-		.match_flags =IEEE1394_MATCH_SPECIFIER_ID |
-		              IEEE1394_MATCH_VERSION,
-		.specifier_id = SBP2_UNIT_SPEC_ID_ENTRY & 0xffffff,
-		.version =    SBP2_SW_VERSION_ENTRY & 0xffffff
-	},
-	{ }
+	 .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
+	 .specifier_id = SBP2_UNIT_SPEC_ID_ENTRY & 0xffffff,
+	 .version = SBP2_SW_VERSION_ENTRY & 0xffffff},
+	{}
 };
 
 MODULE_DEVICE_TABLE(ieee1394, sbp2_id_table);
@@ -221,7 +215,6 @@ static u32 global_outstanding_dmas = 0;
 
 #define SBP2_ERR(fmt, args...)		HPSB_ERR("sbp2: "fmt, ## args)
 
-
 /*
  * Globals
  */
@@ -254,8 +247,8 @@ static struct hpsb_address_ops sbp2_ops = {
 
 #ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA
 static struct hpsb_address_ops sbp2_physdma_ops = {
-        .read = sbp2_handle_physdma_read,
-        .write = sbp2_handle_physdma_write,
+	.read = sbp2_handle_physdma_read,
+	.write = sbp2_handle_physdma_write,
 };
 #endif
 
@@ -287,7 +280,6 @@ static u32 sbp2_broken_inquiry_list[] = {
  * General utility functions
  **************************************/
 
-
 #ifndef __BIG_ENDIAN
 /*
  * Converts a buffer from be32 to cpu byte ordering. Length is in bytes.
@@ -324,7 +316,8 @@ static __inline__ void sbp2util_cpu_to_be32_buffer(void *buffer, int length)
 /*
  * Debug packet dump routine. Length is in bytes.
  */
-static void sbp2util_packet_dump(void *buffer, int length, char *dump_name, u32 dump_phys_addr)
+static void sbp2util_packet_dump(void *buffer, int length, char *dump_name,
+				 u32 dump_phys_addr)
 {
 	int i;
 	unsigned char *dump = buffer;
@@ -345,7 +338,7 @@ static void sbp2util_packet_dump(void *buffer, int length, char *dump_name, u32
 			printk("  ");
 		if ((i & 0xf) == 0)
 			printk("\n   ");
-		printk("%02x ", (int) dump[i]);
+		printk("%02x ", (int)dump[i]);
 	}
 	printk("\n");
 
@@ -364,9 +357,9 @@ static int sbp2util_down_timeout(atomic_t *done, int timeout)
 
 	for (i = timeout; (i > 0 && atomic_read(done) == 0); i-= HZ/10) {
 		if (msleep_interruptible(100))	/* 100ms */
-			return(1);
+			return 1;
 	}
-	return ((i > 0) ? 0:1);
+	return (i > 0) ? 0 : 1;
 }
 
 /* Free's an allocated packet */
@@ -380,21 +373,22 @@ static void sbp2_free_packet(struct hpsb_packet *packet)
  * subaction and returns immediately. Can be used from interrupts.
  */
 static int sbp2util_node_write_no_wait(struct node_entry *ne, u64 addr,
-				quadlet_t *buffer, size_t length)
+				       quadlet_t *buffer, size_t length)
 {
 	struct hpsb_packet *packet;
 
 	packet = hpsb_make_writepacket(ne->host, ne->nodeid,
 				       addr, buffer, length);
-        if (!packet)
-                return -ENOMEM;
+	if (!packet)
+		return -ENOMEM;
 
-	hpsb_set_packet_complete_task(packet, (void (*)(void*))sbp2_free_packet,
+	hpsb_set_packet_complete_task(packet,
+				      (void (*)(void *))sbp2_free_packet,
 				      packet);
 
 	hpsb_node_fill_packet(ne, packet);
 
-        if (hpsb_send_packet(packet) < 0) {
+	if (hpsb_send_packet(packet) < 0) {
 		sbp2_free_packet(packet);
 		return -EIO;
 	}
@@ -417,22 +411,22 @@ static int sbp2util_create_command_orb_pool(struct scsi_id_instance_data *scsi_i
 
 	spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
 	for (i = 0; i < orbs; i++) {
-		command = (struct sbp2_command_info *)
-		    kmalloc(sizeof(struct sbp2_command_info), GFP_ATOMIC);
+		command = kzalloc(sizeof(*command), GFP_ATOMIC);
 		if (!command) {
-			spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
-			return(-ENOMEM);
+			spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock,
+					       flags);
+			return -ENOMEM;
 		}
-		memset(command, '\0', sizeof(struct sbp2_command_info));
 		command->command_orb_dma =
-			pci_map_single (hi->host->pdev, &command->command_orb,
-					sizeof(struct sbp2_command_orb),
-					PCI_DMA_BIDIRECTIONAL);
+		    pci_map_single(hi->host->pdev, &command->command_orb,
+				   sizeof(struct sbp2_command_orb),
+				   PCI_DMA_BIDIRECTIONAL);
 		SBP2_DMA_ALLOC("single command orb DMA");
 		command->sge_dma =
-			pci_map_single (hi->host->pdev, &command->scatter_gather_element,
-					sizeof(command->scatter_gather_element),
-					PCI_DMA_BIDIRECTIONAL);
+		    pci_map_single(hi->host->pdev,
+				   &command->scatter_gather_element,
+				   sizeof(command->scatter_gather_element),
+				   PCI_DMA_BIDIRECTIONAL);
 		SBP2_DMA_ALLOC("scatter_gather_element");
 		INIT_LIST_HEAD(&command->list);
 		list_add_tail(&command->list, &scsi_id->sbp2_command_orb_completed);
@@ -488,7 +482,7 @@ static struct sbp2_command_info *sbp2util_find_command_for_orb(
 		list_for_each_entry(command, &scsi_id->sbp2_command_orb_inuse, list) {
 			if (command->command_orb_dma == orb) {
 				spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
-				return (command);
+				return command;
 			}
 		}
 	}
@@ -496,7 +490,7 @@ static struct sbp2_command_info *sbp2util_find_command_for_orb(
 
 	SBP2_ORB_DEBUG("could not match command orb %x", (unsigned int)orb);
 
-	return(NULL);
+	return NULL;
 }
 
 /*
@@ -513,12 +507,12 @@ static struct sbp2_command_info *sbp2util_find_command_for_SCpnt(struct scsi_id_
 		list_for_each_entry(command, &scsi_id->sbp2_command_orb_inuse, list) {
 			if (command->Current_SCpnt == SCpnt) {
 				spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
-				return (command);
+				return command;
 			}
 		}
 	}
 	spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
-	return(NULL);
+	return NULL;
 }
 
 /*
@@ -545,7 +539,7 @@ static struct sbp2_command_info *sbp2util_allocate_command_orb(
 		SBP2_ERR("sbp2util_allocate_command_orb - No orbs available!");
 	}
 	spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
-	return (command);
+	return command;
 }
 
 /* Free our DMA's */
@@ -587,7 +581,8 @@ static void sbp2util_free_command_dma(struct sbp2_command_info *command)
 /*
  * This function moves a command to the completed orb list.
  */
-static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_id, struct sbp2_command_info *command)
+static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_id,
+					    struct sbp2_command_info *command)
 {
 	unsigned long flags;
 
@@ -606,8 +601,6 @@ static inline int sbp2util_node_is_available(struct scsi_id_instance_data *scsi_
 	return scsi_id && scsi_id->ne && !scsi_id->ne->in_limbo;
 }
 
-
-
 /*********************************************
  * IEEE-1394 core driver stack related section
  *********************************************/
@@ -627,14 +620,14 @@ static int sbp2_probe(struct device *dev)
 	if (ud->flags & UNIT_DIRECTORY_HAS_LUN_DIRECTORY)
 		return -ENODEV;
 
-        scsi_id = sbp2_alloc_device(ud);
+	scsi_id = sbp2_alloc_device(ud);
 
-        if (!scsi_id)
-                return -ENOMEM;
+	if (!scsi_id)
+		return -ENOMEM;
 
-        sbp2_parse_unit_directory(scsi_id, ud);
+	sbp2_parse_unit_directory(scsi_id, ud);
 
-        return sbp2_start_device(scsi_id);
+	return sbp2_start_device(scsi_id);
 }
 
 static int sbp2_remove(struct device *dev)
@@ -719,12 +712,11 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud
 
 	SBP2_DEBUG("sbp2_alloc_device");
 
-	scsi_id = kmalloc(sizeof(*scsi_id), GFP_KERNEL);
+	scsi_id = kzalloc(sizeof(*scsi_id), GFP_KERNEL);
 	if (!scsi_id) {
 		SBP2_ERR("failed to create scsi_id");
 		goto failed_alloc;
 	}
-	memset(scsi_id, 0, sizeof(*scsi_id));
 
 	scsi_id->ne = ud->ne;
 	scsi_id->ud = ud;
@@ -735,7 +727,7 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud
 	INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_completed);
 	INIT_LIST_HEAD(&scsi_id->scsi_list);
 	spin_lock_init(&scsi_id->sbp2_command_orb_lock);
-	scsi_id->sbp2_device_type_and_lun = SBP2_DEVICE_TYPE_LUN_UNINITIALIZED;
+	scsi_id->sbp2_lun = 0;
 
 	ud->device.driver_data = scsi_id;
 
@@ -769,7 +761,7 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud
 
 	/* Register our host with the SCSI stack. */
 	scsi_host = scsi_host_alloc(&scsi_driver_template,
-				    sizeof (unsigned long));
+				    sizeof(unsigned long));
 	if (!scsi_host) {
 		SBP2_ERR("failed to register scsi host");
 		goto failed_alloc;
@@ -790,7 +782,6 @@ failed_alloc:
 	return NULL;
 }
 
-
 static void sbp2_host_reset(struct hpsb_host *host)
 {
 	struct sbp2scsi_host_info *hi;
@@ -804,7 +795,6 @@ static void sbp2_host_reset(struct hpsb_host *host)
 	}
 }
 
-
 /*
  * This function is where we first pull the node unique ids, and then
  * allocate memory and register a SBP-2 device.
@@ -818,7 +808,8 @@ static int sbp2_start_device(struct scsi_id_instance_data *scsi_id)
 
 	/* Login FIFO DMA */
 	scsi_id->login_response =
-		pci_alloc_consistent(hi->host->pdev, sizeof(struct sbp2_login_response),
+		pci_alloc_consistent(hi->host->pdev,
+				     sizeof(struct sbp2_login_response),
 				     &scsi_id->login_response_dma);
 	if (!scsi_id->login_response)
 		goto alloc_fail;
@@ -826,7 +817,8 @@ static int sbp2_start_device(struct scsi_id_instance_data *scsi_id)
 
 	/* Query logins ORB DMA */
 	scsi_id->query_logins_orb =
-		pci_alloc_consistent(hi->host->pdev, sizeof(struct sbp2_query_logins_orb),
+		pci_alloc_consistent(hi->host->pdev,
+				     sizeof(struct sbp2_query_logins_orb),
 				     &scsi_id->query_logins_orb_dma);
 	if (!scsi_id->query_logins_orb)
 		goto alloc_fail;
@@ -834,7 +826,8 @@ static int sbp2_start_device(struct scsi_id_instance_data *scsi_id)
 
 	/* Query logins response DMA */
 	scsi_id->query_logins_response =
-		pci_alloc_consistent(hi->host->pdev, sizeof(struct sbp2_query_logins_response),
+		pci_alloc_consistent(hi->host->pdev,
+				     sizeof(struct sbp2_query_logins_response),
 				     &scsi_id->query_logins_response_dma);
 	if (!scsi_id->query_logins_response)
 		goto alloc_fail;
@@ -842,7 +835,8 @@ static int sbp2_start_device(struct scsi_id_instance_data *scsi_id)
 
 	/* Reconnect ORB DMA */
 	scsi_id->reconnect_orb =
-		pci_alloc_consistent(hi->host->pdev, sizeof(struct sbp2_reconnect_orb),
+		pci_alloc_consistent(hi->host->pdev,
+				     sizeof(struct sbp2_reconnect_orb),
 				     &scsi_id->reconnect_orb_dma);
 	if (!scsi_id->reconnect_orb)
 		goto alloc_fail;
@@ -850,7 +844,8 @@ static int sbp2_start_device(struct scsi_id_instance_data *scsi_id)
 
 	/* Logout ORB DMA */
 	scsi_id->logout_orb =
-		pci_alloc_consistent(hi->host->pdev, sizeof(struct sbp2_logout_orb),
+		pci_alloc_consistent(hi->host->pdev,
+				     sizeof(struct sbp2_logout_orb),
 				     &scsi_id->logout_orb_dma);
 	if (!scsi_id->logout_orb)
 		goto alloc_fail;
@@ -858,58 +853,11 @@ static int sbp2_start_device(struct scsi_id_instance_data *scsi_id)
 
 	/* Login ORB DMA */
 	scsi_id->login_orb =
-		pci_alloc_consistent(hi->host->pdev, sizeof(struct sbp2_login_orb),
+		pci_alloc_consistent(hi->host->pdev,
+				     sizeof(struct sbp2_login_orb),
 				     &scsi_id->login_orb_dma);
-	if (!scsi_id->login_orb) {
-alloc_fail:
-		if (scsi_id->query_logins_response) {
-			pci_free_consistent(hi->host->pdev,
-					    sizeof(struct sbp2_query_logins_response),
-					    scsi_id->query_logins_response,
-					    scsi_id->query_logins_response_dma);
-			SBP2_DMA_FREE("query logins response DMA");
-		}
-
-		if (scsi_id->query_logins_orb) {
-			pci_free_consistent(hi->host->pdev,
-					    sizeof(struct sbp2_query_logins_orb),
-					    scsi_id->query_logins_orb,
-					    scsi_id->query_logins_orb_dma);
-			SBP2_DMA_FREE("query logins ORB DMA");
-		}
-
-		if (scsi_id->logout_orb) {
-			pci_free_consistent(hi->host->pdev,
-					sizeof(struct sbp2_logout_orb),
-					scsi_id->logout_orb,
-					scsi_id->logout_orb_dma);
-			SBP2_DMA_FREE("logout ORB DMA");
-		}
-
-		if (scsi_id->reconnect_orb) {
-			pci_free_consistent(hi->host->pdev,
-					sizeof(struct sbp2_reconnect_orb),
-					scsi_id->reconnect_orb,
-					scsi_id->reconnect_orb_dma);
-			SBP2_DMA_FREE("reconnect ORB DMA");
-		}
-
-		if (scsi_id->login_response) {
-			pci_free_consistent(hi->host->pdev,
-					sizeof(struct sbp2_login_response),
-					scsi_id->login_response,
-					scsi_id->login_response_dma);
-			SBP2_DMA_FREE("login FIFO DMA");
-		}
-
-		list_del(&scsi_id->scsi_list);
-
-		kfree(scsi_id);
-
-		SBP2_ERR ("Could not allocate memory for scsi_id");
-
-		return -ENOMEM;
-	}
+	if (!scsi_id->login_orb)
+		goto alloc_fail;
 	SBP2_DMA_ALLOC("consistent DMA region for login ORB");
 
 	SBP2_DEBUG("New SBP-2 device inserted, SCSI ID = %x", scsi_id->ud->id);
@@ -935,7 +883,7 @@ alloc_fail:
 		sbp2_remove_device(scsi_id);
 		return -EINTR;
 	}
-	
+
 	/*
 	 * Login to the sbp-2 device
 	 */
@@ -964,10 +912,17 @@ alloc_fail:
 	error = scsi_add_device(scsi_id->scsi_host, 0, scsi_id->ud->id, 0);
 	if (error) {
 		SBP2_ERR("scsi_add_device failed");
+		sbp2_logout_device(scsi_id);
+		sbp2_remove_device(scsi_id);
 		return error;
 	}
 
 	return 0;
+
+alloc_fail:
+	SBP2_ERR("Could not allocate memory for scsi_id");
+	sbp2_remove_device(scsi_id);
+	return -ENOMEM;
 }
 
 /*
@@ -1054,51 +1009,44 @@ static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id)
  * This function deals with physical dma write requests (for adapters that do not support
  * physical dma in hardware). Mostly just here for debugging...
  */
-static int sbp2_handle_physdma_write(struct hpsb_host *host, int nodeid, int destid, quadlet_t *data,
-                                     u64 addr, size_t length, u16 flags)
+static int sbp2_handle_physdma_write(struct hpsb_host *host, int nodeid,
+				     int destid, quadlet_t *data, u64 addr,
+				     size_t length, u16 flags)
 {
 
-        /*
-         * Manually put the data in the right place.
-         */
-        memcpy(bus_to_virt((u32)addr), data, length);
-	sbp2util_packet_dump(data, length, "sbp2 phys dma write by device", (u32)addr);
-        return(RCODE_COMPLETE);
+	/*
+	 * Manually put the data in the right place.
+	 */
+	memcpy(bus_to_virt((u32) addr), data, length);
+	sbp2util_packet_dump(data, length, "sbp2 phys dma write by device",
+			     (u32) addr);
+	return RCODE_COMPLETE;
 }
 
 /*
  * This function deals with physical dma read requests (for adapters that do not support
  * physical dma in hardware). Mostly just here for debugging...
  */
-static int sbp2_handle_physdma_read(struct hpsb_host *host, int nodeid, quadlet_t *data,
-                                    u64 addr, size_t length, u16 flags)
+static int sbp2_handle_physdma_read(struct hpsb_host *host, int nodeid,
+				    quadlet_t *data, u64 addr, size_t length,
+				    u16 flags)
 {
 
-        /*
-         * Grab data from memory and send a read response.
-         */
-        memcpy(data, bus_to_virt((u32)addr), length);
-	sbp2util_packet_dump(data, length, "sbp2 phys dma read by device", (u32)addr);
-        return(RCODE_COMPLETE);
+	/*
+	 * Grab data from memory and send a read response.
+	 */
+	memcpy(data, bus_to_virt((u32) addr), length);
+	sbp2util_packet_dump(data, length, "sbp2 phys dma read by device",
+			     (u32) addr);
+	return RCODE_COMPLETE;
 }
 #endif
 
-
 /**************************************
  * SBP-2 protocol related section
  **************************************/
 
 /*
- * This function determines if we should convert scsi commands for a particular sbp2 device type
- */
-static __inline__ int sbp2_command_conversion_device_type(u8 device_type)
-{
-	return (((device_type == TYPE_DISK) ||
-		 (device_type == TYPE_RBC) ||
-		 (device_type == TYPE_ROM)) ? 1:0);
-}
-
-/*
  * This function queries the device for the maximum concurrent logins it
  * supports.
  */
@@ -1120,11 +1068,7 @@ static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id)
 
 	scsi_id->query_logins_orb->lun_misc = ORB_SET_FUNCTION(SBP2_QUERY_LOGINS_REQUEST);
 	scsi_id->query_logins_orb->lun_misc |= ORB_SET_NOTIFY(1);
-	if (scsi_id->sbp2_device_type_and_lun != SBP2_DEVICE_TYPE_LUN_UNINITIALIZED) {
-		scsi_id->query_logins_orb->lun_misc |= ORB_SET_LUN(scsi_id->sbp2_device_type_and_lun);
-		SBP2_DEBUG("sbp2_query_logins: set lun to %d",
-			   ORB_SET_LUN(scsi_id->sbp2_device_type_and_lun));
-	}
+	scsi_id->query_logins_orb->lun_misc |= ORB_SET_LUN(scsi_id->sbp2_lun);
 	SBP2_DEBUG("sbp2_query_logins: lun_misc initialized");
 
 	scsi_id->query_logins_orb->reserved_resp_length =
@@ -1161,12 +1105,12 @@ static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id)
 
 	if (sbp2util_down_timeout(&scsi_id->sbp2_login_complete, 2*HZ)) {
 		SBP2_INFO("Error querying logins to SBP-2 device - timed out");
-		return(-EIO);
+		return -EIO;
 	}
 
 	if (scsi_id->status_block.ORB_offset_lo != scsi_id->query_logins_orb_dma) {
 		SBP2_INFO("Error querying logins to SBP-2 device - timed out");
-		return(-EIO);
+		return -EIO;
 	}
 
 	if (STATUS_GET_RESP(scsi_id->status_block.ORB_offset_hi_misc) ||
@@ -1174,7 +1118,7 @@ static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id)
 	    STATUS_GET_SBP_STATUS(scsi_id->status_block.ORB_offset_hi_misc)) {
 
 		SBP2_INFO("Error querying logins to SBP-2 device - timed out");
-		return(-EIO);
+		return -EIO;
 	}
 
 	sbp2util_cpu_to_be32_buffer(scsi_id->query_logins_response, sizeof(struct sbp2_query_logins_response));
@@ -1191,7 +1135,7 @@ static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id)
 	SBP2_DEBUG("Number of active logins: %d", active_logins);
 
 	if (active_logins >= max_logins) {
-		return(-EIO);
+		return -EIO;
 	}
 
 	return 0;
@@ -1210,13 +1154,13 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id)
 
 	if (!scsi_id->login_orb) {
 		SBP2_DEBUG("sbp2_login_device: login_orb not alloc'd!");
-		return(-EIO);
+		return -EIO;
 	}
 
 	if (!exclusive_login) {
 		if (sbp2_query_logins(scsi_id)) {
 			SBP2_INFO("Device does not support any more concurrent logins");
-			return(-EIO);
+			return -EIO;
 		}
 	}
 
@@ -1233,12 +1177,7 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id)
 	scsi_id->login_orb->lun_misc |= ORB_SET_RECONNECT(0);	/* One second reconnect time */
 	scsi_id->login_orb->lun_misc |= ORB_SET_EXCLUSIVE(exclusive_login);	/* Exclusive access to device */
 	scsi_id->login_orb->lun_misc |= ORB_SET_NOTIFY(1);	/* Notify us of login complete */
-	/* Set the lun if we were able to pull it from the device's unit directory */
-	if (scsi_id->sbp2_device_type_and_lun != SBP2_DEVICE_TYPE_LUN_UNINITIALIZED) {
-		scsi_id->login_orb->lun_misc |= ORB_SET_LUN(scsi_id->sbp2_device_type_and_lun);
-		SBP2_DEBUG("sbp2_query_logins: set lun to %d",
-			   ORB_SET_LUN(scsi_id->sbp2_device_type_and_lun));
-	}
+	scsi_id->login_orb->lun_misc |= ORB_SET_LUN(scsi_id->sbp2_lun);
 	SBP2_DEBUG("sbp2_login_device: lun_misc initialized");
 
 	scsi_id->login_orb->passwd_resp_lengths =
@@ -1288,7 +1227,7 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id)
 	 */
 	if (sbp2util_down_timeout(&scsi_id->sbp2_login_complete, 20*HZ)) {
 		SBP2_ERR("Error logging into SBP-2 device - login timed-out");
-		return(-EIO);
+		return -EIO;
 	}
 
 	/*
@@ -1296,7 +1235,7 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id)
 	 */
 	if (scsi_id->status_block.ORB_offset_lo != scsi_id->login_orb_dma) {
 		SBP2_ERR("Error logging into SBP-2 device - login timed-out");
-		return(-EIO);
+		return -EIO;
 	}
 
 	/*
@@ -1307,7 +1246,7 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id)
 	    STATUS_GET_SBP_STATUS(scsi_id->status_block.ORB_offset_hi_misc)) {
 
 		SBP2_ERR("Error logging into SBP-2 device - login failed");
-		return(-EIO);
+		return -EIO;
 	}
 
 	/*
@@ -1331,7 +1270,7 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id)
 
 	SBP2_INFO("Logged into SBP-2 device");
 
-	return(0);
+	return 0;
 
 }
 
@@ -1385,8 +1324,7 @@ static int sbp2_logout_device(struct scsi_id_instance_data *scsi_id)
 	atomic_set(&scsi_id->sbp2_login_complete, 0);
 
 	error = hpsb_node_write(scsi_id->ne,
-	                            scsi_id->sbp2_management_agent_addr,
-	                            data, 8);
+				scsi_id->sbp2_management_agent_addr, data, 8);
 	if (error)
 		return error;
 
@@ -1396,7 +1334,7 @@ static int sbp2_logout_device(struct scsi_id_instance_data *scsi_id)
 
 	SBP2_INFO("Logged out of SBP-2 device");
 
-	return(0);
+	return 0;
 
 }
 
@@ -1456,8 +1394,7 @@ static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id)
 	atomic_set(&scsi_id->sbp2_login_complete, 0);
 
 	error = hpsb_node_write(scsi_id->ne,
-	                            scsi_id->sbp2_management_agent_addr,
-	                            data, 8);
+				scsi_id->sbp2_management_agent_addr, data, 8);
 	if (error)
 		return error;
 
@@ -1466,7 +1403,7 @@ static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id)
 	 */
 	if (sbp2util_down_timeout(&scsi_id->sbp2_login_complete, HZ)) {
 		SBP2_ERR("Error reconnecting to SBP-2 device - reconnect timed-out");
-		return(-EIO);
+		return -EIO;
 	}
 
 	/*
@@ -1474,7 +1411,7 @@ static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id)
 	 */
 	if (scsi_id->status_block.ORB_offset_lo != scsi_id->reconnect_orb_dma) {
 		SBP2_ERR("Error reconnecting to SBP-2 device - reconnect timed-out");
-		return(-EIO);
+		return -EIO;
 	}
 
 	/*
@@ -1485,12 +1422,12 @@ static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id)
 	    STATUS_GET_SBP_STATUS(scsi_id->status_block.ORB_offset_hi_misc)) {
 
 		SBP2_ERR("Error reconnecting to SBP-2 device - reconnect failed");
-		return(-EIO);
+		return -EIO;
 	}
 
 	HPSB_DEBUG("Reconnected to SBP-2 device");
 
-	return(0);
+	return 0;
 
 }
 
@@ -1513,10 +1450,9 @@ static int sbp2_set_busy_timeout(struct scsi_id_instance_data *scsi_id)
 		SBP2_ERR("sbp2_set_busy_timeout error");
 	}
 
-	return(0);
+	return 0;
 }
 
-
 /*
  * This function is called to parse sbp2 device's config rom unit
  * directory. Used to determine things like sbp2 management agent offset,
@@ -1529,7 +1465,7 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
 	struct csr1212_dentry *dentry;
 	u64 management_agent_addr;
 	u32 command_set_spec_id, command_set, unit_characteristics,
-		firmware_revision, workarounds;
+	    firmware_revision, workarounds;
 	int i;
 
 	SBP2_DEBUG("sbp2_parse_unit_directory");
@@ -1547,13 +1483,14 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
 			if (kv->key.type == CSR1212_KV_TYPE_CSR_OFFSET) {
 				/* Save off the management agent address */
 				management_agent_addr =
-					CSR1212_REGISTER_SPACE_BASE +
-					(kv->value.csr_offset << 2);
+				    CSR1212_REGISTER_SPACE_BASE +
+				    (kv->value.csr_offset << 2);
 
 				SBP2_DEBUG("sbp2_management_agent_addr = %x",
-					   (unsigned int) management_agent_addr);
+					   (unsigned int)management_agent_addr);
 			} else if (kv->key.type == CSR1212_KV_TYPE_IMMEDIATE) {
-				scsi_id->sbp2_device_type_and_lun = kv->value.immediate;
+				scsi_id->sbp2_lun =
+				    ORB_SET_LUN(kv->value.immediate);
 			}
 			break;
 
@@ -1561,14 +1498,14 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
 			/* Command spec organization */
 			command_set_spec_id = kv->value.immediate;
 			SBP2_DEBUG("sbp2_command_set_spec_id = %x",
-				   (unsigned int) command_set_spec_id);
+				   (unsigned int)command_set_spec_id);
 			break;
 
 		case SBP2_COMMAND_SET_KEY:
 			/* Command set used by sbp2 device */
 			command_set = kv->value.immediate;
 			SBP2_DEBUG("sbp2_command_set = %x",
-				   (unsigned int) command_set);
+				   (unsigned int)command_set);
 			break;
 
 		case SBP2_UNIT_CHARACTERISTICS_KEY:
@@ -1578,7 +1515,7 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
 			 */
 			unit_characteristics = kv->value.immediate;
 			SBP2_DEBUG("sbp2_unit_characteristics = %x",
-				   (unsigned int) unit_characteristics);
+				   (unsigned int)unit_characteristics);
 			break;
 
 		case SBP2_FIRMWARE_REVISION_KEY:
@@ -1586,9 +1523,10 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
 			firmware_revision = kv->value.immediate;
 			if (force_inquiry_hack)
 				SBP2_INFO("sbp2_firmware_revision = %x",
-				   (unsigned int) firmware_revision);
-			else	SBP2_DEBUG("sbp2_firmware_revision = %x",
-				   (unsigned int) firmware_revision);
+					  (unsigned int)firmware_revision);
+			else
+				SBP2_DEBUG("sbp2_firmware_revision = %x",
+					   (unsigned int)firmware_revision);
 			break;
 
 		default:
@@ -1646,7 +1584,7 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
 		scsi_id->sbp2_firmware_revision = firmware_revision;
 		scsi_id->workarounds = workarounds;
 		if (ud->flags & UNIT_DIRECTORY_HAS_LUN)
-			scsi_id->sbp2_device_type_and_lun = ud->lun;
+			scsi_id->sbp2_lun = ORB_SET_LUN(ud->lun);
 	}
 }
 
@@ -1666,8 +1604,9 @@ static int sbp2_max_speed_and_size(struct scsi_id_instance_data *scsi_id)
 	SBP2_DEBUG("sbp2_max_speed_and_size");
 
 	/* Initial setting comes from the hosts speed map */
-	scsi_id->speed_code = hi->host->speed_map[NODEID_TO_NODE(hi->host->node_id) * 64
-						  + NODEID_TO_NODE(scsi_id->ne->nodeid)];
+	scsi_id->speed_code =
+	    hi->host->speed_map[NODEID_TO_NODE(hi->host->node_id) * 64 +
+				NODEID_TO_NODE(scsi_id->ne->nodeid)];
 
 	/* Bump down our speed if the user requested it */
 	if (scsi_id->speed_code > max_speed) {
@@ -1678,15 +1617,16 @@ static int sbp2_max_speed_and_size(struct scsi_id_instance_data *scsi_id)
 
 	/* Payload size is the lesser of what our speed supports and what
 	 * our host supports.  */
-	scsi_id->max_payload_size = min(sbp2_speedto_max_payload[scsi_id->speed_code],
-					(u8)(hi->host->csr.max_rec - 1));
+	scsi_id->max_payload_size =
+	    min(sbp2_speedto_max_payload[scsi_id->speed_code],
+		(u8) (hi->host->csr.max_rec - 1));
 
 	HPSB_DEBUG("Node " NODE_BUS_FMT ": Max speed [%s] - Max payload [%u]",
 		   NODE_BUS_ARGS(hi->host, scsi_id->ne->nodeid),
 		   hpsb_speedto_str[scsi_id->speed_code],
-		   1 << ((u32)scsi_id->max_payload_size + 2));
+		   1 << ((u32) scsi_id->max_payload_size + 2));
 
-	return(0);
+	return 0;
 }
 
 /*
@@ -1721,30 +1661,187 @@ static int sbp2_agent_reset(struct scsi_id_instance_data *scsi_id, int wait)
 	 */
 	scsi_id->last_orb = NULL;
 
-	return(0);
+	return 0;
+}
+
+static void sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb,
+				     struct sbp2scsi_host_info *hi,
+				     struct sbp2_command_info *command,
+				     unsigned int scsi_use_sg,
+				     struct scatterlist *sgpnt,
+				     u32 orb_direction,
+				     enum dma_data_direction dma_dir)
+{
+	command->dma_dir = dma_dir;
+	orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
+	orb->misc |= ORB_SET_DIRECTION(orb_direction);
+
+	/* Special case if only one element (and less than 64KB in size) */
+	if ((scsi_use_sg == 1) &&
+	    (sgpnt[0].length <= SBP2_MAX_SG_ELEMENT_LENGTH)) {
+
+		SBP2_DEBUG("Only one s/g element");
+		command->dma_size = sgpnt[0].length;
+		command->dma_type = CMD_DMA_PAGE;
+		command->cmd_dma = pci_map_page(hi->host->pdev,
+						sgpnt[0].page,
+						sgpnt[0].offset,
+						command->dma_size,
+						command->dma_dir);
+		SBP2_DMA_ALLOC("single page scatter element");
+
+		orb->data_descriptor_lo = command->cmd_dma;
+		orb->misc |= ORB_SET_DATA_SIZE(command->dma_size);
+
+	} else {
+		struct sbp2_unrestricted_page_table *sg_element =
+					&command->scatter_gather_element[0];
+		u32 sg_count, sg_len;
+		dma_addr_t sg_addr;
+		int i, count = pci_map_sg(hi->host->pdev, sgpnt, scsi_use_sg,
+					  dma_dir);
+
+		SBP2_DMA_ALLOC("scatter list");
+
+		command->dma_size = scsi_use_sg;
+		command->sge_buffer = sgpnt;
+
+		/* use page tables (s/g) */
+		orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1);
+		orb->data_descriptor_lo = command->sge_dma;
+
+		/*
+		 * Loop through and fill out our sbp-2 page tables
+		 * (and split up anything too large)
+		 */
+		for (i = 0, sg_count = 0 ; i < count; i++, sgpnt++) {
+			sg_len = sg_dma_len(sgpnt);
+			sg_addr = sg_dma_address(sgpnt);
+			while (sg_len) {
+				sg_element[sg_count].segment_base_lo = sg_addr;
+				if (sg_len > SBP2_MAX_SG_ELEMENT_LENGTH) {
+					sg_element[sg_count].length_segment_base_hi =
+						PAGE_TABLE_SET_SEGMENT_LENGTH(SBP2_MAX_SG_ELEMENT_LENGTH);
+					sg_addr += SBP2_MAX_SG_ELEMENT_LENGTH;
+					sg_len -= SBP2_MAX_SG_ELEMENT_LENGTH;
+				} else {
+					sg_element[sg_count].length_segment_base_hi =
+						PAGE_TABLE_SET_SEGMENT_LENGTH(sg_len);
+					sg_len = 0;
+				}
+				sg_count++;
+			}
+		}
+
+		/* Number of page table (s/g) elements */
+		orb->misc |= ORB_SET_DATA_SIZE(sg_count);
+
+		sbp2util_packet_dump(sg_element,
+				     (sizeof(struct sbp2_unrestricted_page_table)) * sg_count,
+				     "sbp2 s/g list", command->sge_dma);
+
+		/* Byte swap page tables if necessary */
+		sbp2util_cpu_to_be32_buffer(sg_element,
+					    (sizeof(struct sbp2_unrestricted_page_table)) *
+					    sg_count);
+	}
+}
+
+static void sbp2_prep_command_orb_no_sg(struct sbp2_command_orb *orb,
+					struct sbp2scsi_host_info *hi,
+					struct sbp2_command_info *command,
+					struct scatterlist *sgpnt,
+					u32 orb_direction,
+					unsigned int scsi_request_bufflen,
+					void *scsi_request_buffer,
+					enum dma_data_direction dma_dir)
+{
+	command->dma_dir = dma_dir;
+	command->dma_size = scsi_request_bufflen;
+	command->dma_type = CMD_DMA_SINGLE;
+	command->cmd_dma = pci_map_single(hi->host->pdev, scsi_request_buffer,
+					  command->dma_size, command->dma_dir);
+	orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
+	orb->misc |= ORB_SET_DIRECTION(orb_direction);
+
+	SBP2_DMA_ALLOC("single bulk");
+
+	/*
+	 * Handle case where we get a command w/o s/g enabled (but
+	 * check for transfers larger than 64K)
+	 */
+	if (scsi_request_bufflen <= SBP2_MAX_SG_ELEMENT_LENGTH) {
+
+		orb->data_descriptor_lo = command->cmd_dma;
+		orb->misc |= ORB_SET_DATA_SIZE(scsi_request_bufflen);
+
+	} else {
+		struct sbp2_unrestricted_page_table *sg_element =
+			&command->scatter_gather_element[0];
+		u32 sg_count, sg_len;
+		dma_addr_t sg_addr;
+
+		/*
+		 * Need to turn this into page tables, since the
+		 * buffer is too large.
+		 */
+		orb->data_descriptor_lo = command->sge_dma;
+
+		/* Use page tables (s/g) */
+		orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1);
+
+		/*
+		 * fill out our sbp-2 page tables (and split up
+		 * the large buffer)
+		 */
+		sg_count = 0;
+		sg_len = scsi_request_bufflen;
+		sg_addr = command->cmd_dma;
+		while (sg_len) {
+			sg_element[sg_count].segment_base_lo = sg_addr;
+			if (sg_len > SBP2_MAX_SG_ELEMENT_LENGTH) {
+				sg_element[sg_count].length_segment_base_hi =
+					PAGE_TABLE_SET_SEGMENT_LENGTH(SBP2_MAX_SG_ELEMENT_LENGTH);
+				sg_addr += SBP2_MAX_SG_ELEMENT_LENGTH;
+				sg_len -= SBP2_MAX_SG_ELEMENT_LENGTH;
+			} else {
+				sg_element[sg_count].length_segment_base_hi =
+					PAGE_TABLE_SET_SEGMENT_LENGTH(sg_len);
+				sg_len = 0;
+			}
+			sg_count++;
+		}
+
+		/* Number of page table (s/g) elements */
+		orb->misc |= ORB_SET_DATA_SIZE(sg_count);
+
+		sbp2util_packet_dump(sg_element,
+				     (sizeof(struct sbp2_unrestricted_page_table)) * sg_count,
+				     "sbp2 s/g list", command->sge_dma);
+
+		/* Byte swap page tables if necessary */
+		sbp2util_cpu_to_be32_buffer(sg_element,
+					    (sizeof(struct sbp2_unrestricted_page_table)) *
+					     sg_count);
+	}
 }
 
 /*
  * This function is called to create the actual command orb and s/g list
  * out of the scsi command itself.
  */
-static int sbp2_create_command_orb(struct scsi_id_instance_data *scsi_id,
-				   struct sbp2_command_info *command,
-				   unchar *scsi_cmd,
-				   unsigned int scsi_use_sg,
-				   unsigned int scsi_request_bufflen,
-				   void *scsi_request_buffer,
-				   enum dma_data_direction dma_dir)
-
+static void sbp2_create_command_orb(struct scsi_id_instance_data *scsi_id,
+				    struct sbp2_command_info *command,
+				    unchar *scsi_cmd,
+				    unsigned int scsi_use_sg,
+				    unsigned int scsi_request_bufflen,
+				    void *scsi_request_buffer,
+				    enum dma_data_direction dma_dir)
 {
 	struct sbp2scsi_host_info *hi = scsi_id->hi;
-	struct scatterlist *sgpnt = (struct scatterlist *) scsi_request_buffer;
+	struct scatterlist *sgpnt = (struct scatterlist *)scsi_request_buffer;
 	struct sbp2_command_orb *command_orb = &command->command_orb;
-	struct sbp2_unrestricted_page_table *scatter_gather_element =
-		&command->scatter_gather_element[0];
-	u32 sg_count, sg_len, orb_direction;
-	dma_addr_t sg_addr;
-	int i;
+	u32 orb_direction;
 
 	/*
 	 * Set-up our command ORB..
@@ -1758,222 +1855,42 @@ static int sbp2_create_command_orb(struct scsi_id_instance_data *scsi_id,
 	command_orb->next_ORB_lo = 0x0;
 	command_orb->misc = ORB_SET_MAX_PAYLOAD(scsi_id->max_payload_size);
 	command_orb->misc |= ORB_SET_SPEED(scsi_id->speed_code);
-	command_orb->misc |= ORB_SET_NOTIFY(1);		/* Notify us when complete */
+	command_orb->misc |= ORB_SET_NOTIFY(1);	/* Notify us when complete */
 
-	/*
-	 * Get the direction of the transfer. If the direction is unknown, then use our
-	 * goofy table as a back-up.
-	 */
-	switch (dma_dir) {
-		case DMA_NONE:
-			orb_direction = ORB_DIRECTION_NO_DATA_TRANSFER;
-			break;
-		case DMA_TO_DEVICE:
-			orb_direction = ORB_DIRECTION_WRITE_TO_MEDIA;
-			break;
-		case DMA_FROM_DEVICE:
-			orb_direction = ORB_DIRECTION_READ_FROM_MEDIA;
-			break;
-		case DMA_BIDIRECTIONAL:
-		default:
-			SBP2_ERR("SCSI data transfer direction not specified. "
-				 "Update the SBP2 direction table in sbp2.h if "
-				 "necessary for your application");
-			__scsi_print_command(scsi_cmd);
-			orb_direction = sbp2scsi_direction_table[*scsi_cmd];
-			break;
+	if (dma_dir == DMA_NONE)
+		orb_direction = ORB_DIRECTION_NO_DATA_TRANSFER;
+	else if (dma_dir == DMA_TO_DEVICE && scsi_request_bufflen)
+		orb_direction = ORB_DIRECTION_WRITE_TO_MEDIA;
+	else if (dma_dir == DMA_FROM_DEVICE && scsi_request_bufflen)
+		orb_direction = ORB_DIRECTION_READ_FROM_MEDIA;
+	else {
+		SBP2_WARN("Falling back to DMA_NONE");
+		orb_direction = ORB_DIRECTION_NO_DATA_TRANSFER;
 	}
 
-	/*
-	 * Set-up our pagetable stuff... unfortunately, this has become
-	 * messier than I'd like. Need to clean this up a bit.   ;-)
-	 */
+	/* Set-up our pagetable stuff */
 	if (orb_direction == ORB_DIRECTION_NO_DATA_TRANSFER) {
-
 		SBP2_DEBUG("No data transfer");
-
-		/*
-		 * Handle no data transfer
-		 */
 		command_orb->data_descriptor_hi = 0x0;
 		command_orb->data_descriptor_lo = 0x0;
 		command_orb->misc |= ORB_SET_DIRECTION(1);
-
 	} else if (scsi_use_sg) {
-
 		SBP2_DEBUG("Use scatter/gather");
-
-		/*
-		 * Special case if only one element (and less than 64KB in size)
-		 */
-		if ((scsi_use_sg == 1) && (sgpnt[0].length <= SBP2_MAX_SG_ELEMENT_LENGTH)) {
-
-			SBP2_DEBUG("Only one s/g element");
-			command->dma_dir = dma_dir;
-			command->dma_size = sgpnt[0].length;
-			command->dma_type = CMD_DMA_PAGE;
-			command->cmd_dma = pci_map_page(hi->host->pdev,
-							sgpnt[0].page,
-							sgpnt[0].offset,
-							command->dma_size,
-							command->dma_dir);
-			SBP2_DMA_ALLOC("single page scatter element");
-
-			command_orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
-			command_orb->data_descriptor_lo = command->cmd_dma;
-			command_orb->misc |= ORB_SET_DATA_SIZE(command->dma_size);
-			command_orb->misc |= ORB_SET_DIRECTION(orb_direction);
-
-		} else {
-			int count = pci_map_sg(hi->host->pdev, sgpnt, scsi_use_sg, dma_dir);
-			SBP2_DMA_ALLOC("scatter list");
-
-			command->dma_size = scsi_use_sg;
-			command->dma_dir = dma_dir;
-			command->sge_buffer = sgpnt;
-
-			/* use page tables (s/g) */
-			command_orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1);
-			command_orb->misc |= ORB_SET_DIRECTION(orb_direction);
-			command_orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
-			command_orb->data_descriptor_lo = command->sge_dma;
-
-			/*
-			 * Loop through and fill out our sbp-2 page tables
-			 * (and split up anything too large)
-			 */
-			for (i = 0, sg_count = 0 ; i < count; i++, sgpnt++) {
-				sg_len = sg_dma_len(sgpnt);
-				sg_addr = sg_dma_address(sgpnt);
-				while (sg_len) {
-					scatter_gather_element[sg_count].segment_base_lo = sg_addr;
-					if (sg_len > SBP2_MAX_SG_ELEMENT_LENGTH) {
-						scatter_gather_element[sg_count].length_segment_base_hi =
-							PAGE_TABLE_SET_SEGMENT_LENGTH(SBP2_MAX_SG_ELEMENT_LENGTH);
-						sg_addr += SBP2_MAX_SG_ELEMENT_LENGTH;
-						sg_len -= SBP2_MAX_SG_ELEMENT_LENGTH;
-					} else {
-						scatter_gather_element[sg_count].length_segment_base_hi =
-							PAGE_TABLE_SET_SEGMENT_LENGTH(sg_len);
-						sg_len = 0;
-					}
-					sg_count++;
-				}
-			}
-
-			/* Number of page table (s/g) elements */
-			command_orb->misc |= ORB_SET_DATA_SIZE(sg_count);
-
-			sbp2util_packet_dump(scatter_gather_element,
-					     (sizeof(struct sbp2_unrestricted_page_table)) * sg_count,
-					     "sbp2 s/g list", command->sge_dma);
-
-			/*
-			 * Byte swap page tables if necessary
-			 */
-			sbp2util_cpu_to_be32_buffer(scatter_gather_element,
-						    (sizeof(struct sbp2_unrestricted_page_table)) *
-						    sg_count);
-
-		}
-
+		sbp2_prep_command_orb_sg(command_orb, hi, command, scsi_use_sg,
+					 sgpnt, orb_direction, dma_dir);
 	} else {
-
 		SBP2_DEBUG("No scatter/gather");
-
-		command->dma_dir = dma_dir;
-		command->dma_size = scsi_request_bufflen;
-		command->dma_type = CMD_DMA_SINGLE;
-		command->cmd_dma = pci_map_single (hi->host->pdev, scsi_request_buffer,
-						   command->dma_size,
-						   command->dma_dir);
-		SBP2_DMA_ALLOC("single bulk");
-
-		/*
-		 * Handle case where we get a command w/o s/g enabled (but
-		 * check for transfers larger than 64K)
-		 */
-		if (scsi_request_bufflen <= SBP2_MAX_SG_ELEMENT_LENGTH) {
-
-			command_orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
-			command_orb->data_descriptor_lo = command->cmd_dma;
-			command_orb->misc |= ORB_SET_DATA_SIZE(scsi_request_bufflen);
-			command_orb->misc |= ORB_SET_DIRECTION(orb_direction);
-
-			/*
-			 * Sanity, in case our direction table is not
-			 * up-to-date
-			 */
-			if (!scsi_request_bufflen) {
-				command_orb->data_descriptor_hi = 0x0;
-				command_orb->data_descriptor_lo = 0x0;
-				command_orb->misc |= ORB_SET_DIRECTION(1);
-			}
-
-		} else {
-			/*
-			 * Need to turn this into page tables, since the
-			 * buffer is too large.
-			 */
-			command_orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
-			command_orb->data_descriptor_lo = command->sge_dma;
-
-			/* Use page tables (s/g) */
-			command_orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1);
-			command_orb->misc |= ORB_SET_DIRECTION(orb_direction);
-
-			/*
-			 * fill out our sbp-2 page tables (and split up
-			 * the large buffer)
-			 */
-			sg_count = 0;
-			sg_len = scsi_request_bufflen;
-			sg_addr = command->cmd_dma;
-			while (sg_len) {
-				scatter_gather_element[sg_count].segment_base_lo = sg_addr;
-				if (sg_len > SBP2_MAX_SG_ELEMENT_LENGTH) {
-					scatter_gather_element[sg_count].length_segment_base_hi =
-						PAGE_TABLE_SET_SEGMENT_LENGTH(SBP2_MAX_SG_ELEMENT_LENGTH);
-					sg_addr += SBP2_MAX_SG_ELEMENT_LENGTH;
-					sg_len -= SBP2_MAX_SG_ELEMENT_LENGTH;
-				} else {
-					scatter_gather_element[sg_count].length_segment_base_hi =
-						PAGE_TABLE_SET_SEGMENT_LENGTH(sg_len);
-					sg_len = 0;
-				}
-				sg_count++;
-			}
-
-			/* Number of page table (s/g) elements */
-			command_orb->misc |= ORB_SET_DATA_SIZE(sg_count);
-
-			sbp2util_packet_dump(scatter_gather_element,
-					     (sizeof(struct sbp2_unrestricted_page_table)) * sg_count,
-					     "sbp2 s/g list", command->sge_dma);
-
-			/*
-			 * Byte swap page tables if necessary
-			 */
-			sbp2util_cpu_to_be32_buffer(scatter_gather_element,
-						    (sizeof(struct sbp2_unrestricted_page_table)) *
-						     sg_count);
-
-		}
-
+		sbp2_prep_command_orb_no_sg(command_orb, hi, command, sgpnt,
+					    orb_direction, scsi_request_bufflen,
+					    scsi_request_buffer, dma_dir);
 	}
 
-	/*
-	 * Byte swap command ORB if necessary
-	 */
+	/* Byte swap command ORB if necessary */
 	sbp2util_cpu_to_be32_buffer(command_orb, sizeof(struct sbp2_command_orb));
 
-	/*
-	 * Put our scsi command in the command ORB
-	 */
+	/* Put our scsi command in the command ORB */
 	memset(command_orb->cdb, 0, 12);
 	memcpy(command_orb->cdb, scsi_cmd, COMMAND_SIZE(*scsi_cmd));
-
-	return(0);
 }
 
 /*
@@ -1989,7 +1906,7 @@ static int sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id,
 
 	outstanding_orb_incr;
 	SBP2_ORB_DEBUG("sending command orb %p, total orbs = %x",
-			command_orb, global_outstanding_command_orbs);
+		       command_orb, global_outstanding_command_orbs);
 
 	pci_dma_sync_single_for_device(hi->host->pdev, command->command_orb_dma,
 				       sizeof(struct sbp2_command_orb),
@@ -2034,10 +1951,11 @@ static int sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id,
 		 * both by the sbp2 device and us.
 		 */
 		scsi_id->last_orb->next_ORB_lo =
-			cpu_to_be32(command->command_orb_dma);
+		    cpu_to_be32(command->command_orb_dma);
 		/* Tells hardware that this pointer is valid */
 		scsi_id->last_orb->next_ORB_hi = 0x0;
-		pci_dma_sync_single_for_device(hi->host->pdev, scsi_id->last_orb_dma,
+		pci_dma_sync_single_for_device(hi->host->pdev,
+					       scsi_id->last_orb_dma,
 					       sizeof(struct sbp2_command_orb),
 					       PCI_DMA_BIDIRECTIONAL);
 
@@ -2051,14 +1969,14 @@ static int sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id,
 
 		if (sbp2util_node_write_no_wait(ne, addr, &data, 4) < 0) {
 			SBP2_ERR("sbp2util_node_write_no_wait failed");
-			return(-EIO);
+			return -EIO;
 		}
 
 		scsi_id->last_orb = command_orb;
 		scsi_id->last_orb_dma = command->command_orb_dma;
 
 	}
-       	return(0);
+	return 0;
 }
 
 /*
@@ -2085,7 +2003,7 @@ static int sbp2_send_command(struct scsi_id_instance_data *scsi_id,
 	 */
 	command = sbp2util_allocate_command_orb(scsi_id, SCpnt, done);
 	if (!command) {
-		return(-EIO);
+		return -EIO;
 	}
 
 	/*
@@ -2106,11 +2024,6 @@ static int sbp2_send_command(struct scsi_id_instance_data *scsi_id,
 	sbp2_create_command_orb(scsi_id, command, cmd, SCpnt->use_sg,
 				request_bufflen, SCpnt->request_buffer,
 				SCpnt->sc_data_direction);
-	/*
-	 * Update our cdb if necessary (to handle sbp2 RBC command set
-	 * differences). This is where the command set hacks go!   =)
-	 */
-	sbp2_check_sbp2_command(scsi_id, command->command_orb.cdb);
 
 	sbp2util_packet_dump(&command->command_orb, sizeof(struct sbp2_command_orb),
 			     "sbp2 command orb", command->command_orb_dma);
@@ -2125,112 +2038,7 @@ static int sbp2_send_command(struct scsi_id_instance_data *scsi_id,
 	 */
 	sbp2_link_orb_command(scsi_id, command);
 
-	return(0);
-}
-
-
-/*
- * This function deals with command set differences between Linux scsi
- * command set and sbp2 RBC command set.
- */
-static void sbp2_check_sbp2_command(struct scsi_id_instance_data *scsi_id, unchar *cmd)
-{
-	unchar new_cmd[16];
-	u8 device_type = SBP2_DEVICE_TYPE (scsi_id->sbp2_device_type_and_lun);
-
-	SBP2_DEBUG("sbp2_check_sbp2_command");
-
-	switch (*cmd) {
-
-		case READ_6:
-
-			if (sbp2_command_conversion_device_type(device_type)) {
-
-				SBP2_DEBUG("Convert READ_6 to READ_10");
-
-				/*
-				 * Need to turn read_6 into read_10
-				 */
-				new_cmd[0] = 0x28;
-				new_cmd[1] = (cmd[1] & 0xe0);
-				new_cmd[2] = 0x0;
-				new_cmd[3] = (cmd[1] & 0x1f);
-				new_cmd[4] = cmd[2];
-				new_cmd[5] = cmd[3];
-				new_cmd[6] = 0x0;
-				new_cmd[7] = 0x0;
-				new_cmd[8] = cmd[4];
-				new_cmd[9] = cmd[5];
-
-				memcpy(cmd, new_cmd, 10);
-
-			}
-
-			break;
-
-		case WRITE_6:
-
-			if (sbp2_command_conversion_device_type(device_type)) {
-
-				SBP2_DEBUG("Convert WRITE_6 to WRITE_10");
-
-				/*
-				 * Need to turn write_6 into write_10
-				 */
-				new_cmd[0] = 0x2a;
-				new_cmd[1] = (cmd[1] & 0xe0);
-				new_cmd[2] = 0x0;
-				new_cmd[3] = (cmd[1] & 0x1f);
-				new_cmd[4] = cmd[2];
-				new_cmd[5] = cmd[3];
-				new_cmd[6] = 0x0;
-				new_cmd[7] = 0x0;
-				new_cmd[8] = cmd[4];
-				new_cmd[9] = cmd[5];
-
-				memcpy(cmd, new_cmd, 10);
-
-			}
-
-			break;
-
-		case MODE_SENSE:
-
-			if (sbp2_command_conversion_device_type(device_type)) {
-
-				SBP2_DEBUG("Convert MODE_SENSE_6 to MODE_SENSE_10");
-
-				/*
-				 * Need to turn mode_sense_6 into mode_sense_10
-				 */
-				new_cmd[0] = 0x5a;
-				new_cmd[1] = cmd[1];
-				new_cmd[2] = cmd[2];
-				new_cmd[3] = 0x0;
-				new_cmd[4] = 0x0;
-				new_cmd[5] = 0x0;
-				new_cmd[6] = 0x0;
-				new_cmd[7] = 0x0;
-				new_cmd[8] = cmd[4];
-				new_cmd[9] = cmd[5];
-
-				memcpy(cmd, new_cmd, 10);
-
-			}
-
-			break;
-
-		case MODE_SELECT:
-
-			/*
-			 * TODO. Probably need to change mode select to 10 byte version
-			 */
-
-		default:
-			break;
-	}
-
-	return;
+	return 0;
 }
 
 /*
@@ -2260,80 +2068,40 @@ static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, unchar *sense
 	sense_data[14] = sbp2_status[20];
 	sense_data[15] = sbp2_status[21];
 
-	return(sbp2_status[8] & 0x3f);	/* return scsi status */
+	return sbp2_status[8] & 0x3f;	/* return scsi status */
 }
 
 /*
  * This function is called after a command is completed, in order to do any necessary SBP-2
  * response data translations for the SCSI stack
  */
-static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id, 
+static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id,
 				     struct scsi_cmnd *SCpnt)
 {
 	u8 *scsi_buf = SCpnt->request_buffer;
-	u8 device_type = SBP2_DEVICE_TYPE (scsi_id->sbp2_device_type_and_lun);
 
 	SBP2_DEBUG("sbp2_check_sbp2_response");
 
 	switch (SCpnt->cmnd[0]) {
 
-		case INQUIRY:
-
-			/*
-			 * If scsi_id->sbp2_device_type_and_lun is uninitialized, then fill 
-			 * this information in from the inquiry response data. Lun is set to zero.
-			 */
-			if (scsi_id->sbp2_device_type_and_lun == SBP2_DEVICE_TYPE_LUN_UNINITIALIZED) {
-				SBP2_DEBUG("Creating sbp2_device_type_and_lun from scsi inquiry data");
-				scsi_id->sbp2_device_type_and_lun = (scsi_buf[0] & 0x1f) << 16;
-			}
-
-			/*
-			 * Make sure data length is ok. Minimum length is 36 bytes
-			 */
-			if (scsi_buf[4] == 0) {
-				scsi_buf[4] = 36 - 5;
-			}
-
-			/*
-			 * Check for Simple Direct Access Device and change it to TYPE_DISK
-			 */
-			if ((scsi_buf[0] & 0x1f) == TYPE_RBC) {
-				SBP2_DEBUG("Changing TYPE_RBC to TYPE_DISK");
-				scsi_buf[0] &= 0xe0;
-			}
-
-			/*
-			 * Fix ansi revision and response data format
-			 */
-			scsi_buf[2] |= 2;
-			scsi_buf[3] = (scsi_buf[3] & 0xf0) | 2;
-
-			break;
-
-		case MODE_SENSE:
-
-			if (sbp2_command_conversion_device_type(device_type)) {
-
-				SBP2_DEBUG("Modify mode sense response (10 byte version)");
-
-				scsi_buf[0] = scsi_buf[1];	/* Mode data length */
-				scsi_buf[1] = scsi_buf[2];	/* Medium type */
-				scsi_buf[2] = scsi_buf[3];	/* Device specific parameter */
-				scsi_buf[3] = scsi_buf[7];	/* Block descriptor length */
-				memcpy(scsi_buf + 4, scsi_buf + 8, scsi_buf[0]);
-			}
-
-			break;
+	case INQUIRY:
+		/*
+		 * Make sure data length is ok. Minimum length is 36 bytes
+		 */
+		if (scsi_buf[4] == 0) {
+			scsi_buf[4] = 36 - 5;
+		}
 
-		case MODE_SELECT:
+		/*
+		 * Fix ansi revision and response data format
+		 */
+		scsi_buf[2] |= 2;
+		scsi_buf[3] = (scsi_buf[3] & 0xf0) | 2;
 
-			/*
-			 * TODO. Probably need to change mode select to 10 byte version
-			 */
+		break;
 
-		default:
-			break;
+	default:
+		break;
 	}
 	return;
 }
@@ -2358,14 +2126,14 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest
 
 	if (!host) {
 		SBP2_ERR("host is NULL - this is bad!");
-		return(RCODE_ADDRESS_ERROR);
+		return RCODE_ADDRESS_ERROR;
 	}
 
 	hi = hpsb_get_hostinfo(&sbp2_highlevel, host);
 
 	if (!hi) {
 		SBP2_ERR("host info is NULL - this is bad!");
-		return(RCODE_ADDRESS_ERROR);
+		return RCODE_ADDRESS_ERROR;
 	}
 
 	/*
@@ -2382,7 +2150,7 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest
 
 	if (!scsi_id) {
 		SBP2_ERR("scsi_id is NULL - device is gone?");
-		return(RCODE_ADDRESS_ERROR);
+		return RCODE_ADDRESS_ERROR;
 	}
 
 	/*
@@ -2480,10 +2248,9 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest
 		SBP2_ORB_DEBUG("command orb completed");
 	}
 
-	return(RCODE_COMPLETE);
+	return RCODE_COMPLETE;
 }
 
-
 /**************************************
  * SCSI interface related section
  **************************************/
@@ -2541,6 +2308,16 @@ static int sbp2scsi_queuecommand(struct scsi_cmnd *SCpnt,
 	}
 
 	/*
+	 * Bidirectional commands are not yet implemented,
+	 * and unknown transfer direction not handled.
+	 */
+	if (SCpnt->sc_data_direction == DMA_BIDIRECTIONAL) {
+		SBP2_ERR("Cannot handle DMA_BIDIRECTIONAL - rejecting command");
+		result = DID_ERROR << 16;
+		goto done;
+	}
+
+	/*
 	 * Try and send our SCSI command
 	 */
 	if (sbp2_send_command(scsi_id, SCpnt, done)) {
@@ -2616,55 +2393,56 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
 	 * complete the command, just let it get retried at the end of the
 	 * bus reset.
 	 */
-	if (!hpsb_node_entry_valid(scsi_id->ne) && (scsi_status != SBP2_SCSI_STATUS_GOOD)) {
+	if (!hpsb_node_entry_valid(scsi_id->ne)
+	    && (scsi_status != SBP2_SCSI_STATUS_GOOD)) {
 		SBP2_ERR("Bus reset in progress - retry command later");
 		return;
 	}
- 
+
 	/*
 	 * Switch on scsi status
 	 */
 	switch (scsi_status) {
-		case SBP2_SCSI_STATUS_GOOD:
-			SCpnt->result = DID_OK;
-			break;
+	case SBP2_SCSI_STATUS_GOOD:
+		SCpnt->result = DID_OK;
+		break;
 
-		case SBP2_SCSI_STATUS_BUSY:
-			SBP2_ERR("SBP2_SCSI_STATUS_BUSY");
-			SCpnt->result = DID_BUS_BUSY << 16;
-			break;
+	case SBP2_SCSI_STATUS_BUSY:
+		SBP2_ERR("SBP2_SCSI_STATUS_BUSY");
+		SCpnt->result = DID_BUS_BUSY << 16;
+		break;
 
-		case SBP2_SCSI_STATUS_CHECK_CONDITION:
-			SBP2_DEBUG("SBP2_SCSI_STATUS_CHECK_CONDITION");
-			SCpnt->result = CHECK_CONDITION << 1;
+	case SBP2_SCSI_STATUS_CHECK_CONDITION:
+		SBP2_DEBUG("SBP2_SCSI_STATUS_CHECK_CONDITION");
+		SCpnt->result = CHECK_CONDITION << 1;
 
-			/*
-			 * Debug stuff
-			 */
+		/*
+		 * Debug stuff
+		 */
 #if CONFIG_IEEE1394_SBP2_DEBUG >= 1
-			scsi_print_command(SCpnt);
-			scsi_print_sense("bh", SCpnt);
+		scsi_print_command(SCpnt);
+		scsi_print_sense("bh", SCpnt);
 #endif
 
-			break;
+		break;
 
-		case SBP2_SCSI_STATUS_SELECTION_TIMEOUT:
-			SBP2_ERR("SBP2_SCSI_STATUS_SELECTION_TIMEOUT");
-			SCpnt->result = DID_NO_CONNECT << 16;
-			scsi_print_command(SCpnt);
-			break;
+	case SBP2_SCSI_STATUS_SELECTION_TIMEOUT:
+		SBP2_ERR("SBP2_SCSI_STATUS_SELECTION_TIMEOUT");
+		SCpnt->result = DID_NO_CONNECT << 16;
+		scsi_print_command(SCpnt);
+		break;
 
-		case SBP2_SCSI_STATUS_CONDITION_MET:
-		case SBP2_SCSI_STATUS_RESERVATION_CONFLICT:
-		case SBP2_SCSI_STATUS_COMMAND_TERMINATED:
-			SBP2_ERR("Bad SCSI status = %x", scsi_status);
-			SCpnt->result = DID_ERROR << 16;
-			scsi_print_command(SCpnt);
-			break;
+	case SBP2_SCSI_STATUS_CONDITION_MET:
+	case SBP2_SCSI_STATUS_RESERVATION_CONFLICT:
+	case SBP2_SCSI_STATUS_COMMAND_TERMINATED:
+		SBP2_ERR("Bad SCSI status = %x", scsi_status);
+		SCpnt->result = DID_ERROR << 16;
+		scsi_print_command(SCpnt);
+		break;
 
-		default:
-			SBP2_ERR("Unsupported SCSI status = %x", scsi_status);
-			SCpnt->result = DID_ERROR << 16;
+	default:
+		SBP2_ERR("Unsupported SCSI status = %x", scsi_status);
+		SCpnt->result = DID_ERROR << 16;
 	}
 
 	/*
@@ -2678,7 +2456,8 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
 	 * If a bus reset is in progress and there was an error, complete
 	 * the command as busy so that it will get retried.
 	 */
-	if (!hpsb_node_entry_valid(scsi_id->ne) && (scsi_status != SBP2_SCSI_STATUS_GOOD)) {
+	if (!hpsb_node_entry_valid(scsi_id->ne)
+	    && (scsi_status != SBP2_SCSI_STATUS_GOOD)) {
 		SBP2_ERR("Completing command with busy (bus reset)");
 		SCpnt->result = DID_BUS_BUSY << 16;
 	}
@@ -2699,31 +2478,29 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
 	/*
 	 * Tell scsi stack that we're done with this command
 	 */
-	done (SCpnt);
+	done(SCpnt);
 }
 
-
 static int sbp2scsi_slave_alloc(struct scsi_device *sdev)
 {
 	((struct scsi_id_instance_data *)sdev->host->hostdata[0])->sdev = sdev;
 	return 0;
 }
 
-
 static int sbp2scsi_slave_configure(struct scsi_device *sdev)
 {
 	blk_queue_dma_alignment(sdev->request_queue, (512 - 1));
+	sdev->use_10_for_rw = 1;
+	sdev->use_10_for_ms = 1;
 	return 0;
 }
 
-
 static void sbp2scsi_slave_destroy(struct scsi_device *sdev)
 {
 	((struct scsi_id_instance_data *)sdev->host->hostdata[0])->sdev = NULL;
 	return;
 }
 
-
 /*
  * Called by scsi stack when something has really gone wrong.  Usually
  * called when a command has timed-out for some reason.
@@ -2769,7 +2546,7 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt)
 		sbp2scsi_complete_all_commands(scsi_id, DID_BUS_BUSY);
 	}
 
-	return(SUCCESS);
+	return SUCCESS;
 }
 
 /*
@@ -2779,28 +2556,20 @@ static int sbp2scsi_reset(struct scsi_cmnd *SCpnt)
 {
 	struct scsi_id_instance_data *scsi_id =
 		(struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0];
-	unsigned long flags;
 
 	SBP2_ERR("reset requested");
 
-	spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
-
 	if (sbp2util_node_is_available(scsi_id)) {
 		SBP2_ERR("Generating sbp2 fetch agent reset");
 		sbp2_agent_reset(scsi_id, 0);
 	}
 
-	spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
-
 	return SUCCESS;
 }
 
-static const char *sbp2scsi_info (struct Scsi_Host *host)
-{
-        return "SCSI emulation for IEEE-1394 SBP-2 Devices";
-}
-
-static ssize_t sbp2_sysfs_ieee1394_id_show(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t sbp2_sysfs_ieee1394_id_show(struct device *dev,
+					   struct device_attribute *attr,
+					   char *buf)
 {
 	struct scsi_device *sdev;
 	struct scsi_id_instance_data *scsi_id;
@@ -2812,10 +2581,7 @@ static ssize_t sbp2_sysfs_ieee1394_id_show(struct device *dev, struct device_att
 	if (!(scsi_id = (struct scsi_id_instance_data *)sdev->host->hostdata[0]))
 		return 0;
 
-	if (scsi_id->sbp2_device_type_and_lun == SBP2_DEVICE_TYPE_LUN_UNINITIALIZED)
-		lun = 0;
-	else
-		lun = ORB_SET_LUN(scsi_id->sbp2_device_type_and_lun);
+	lun = ORB_SET_LUN(scsi_id->sbp2_lun);
 
 	return sprintf(buf, "%016Lx:%d:%d\n", (unsigned long long)scsi_id->ne->guid,
 		       scsi_id->ud->id, lun);
@@ -2837,12 +2603,9 @@ static struct scsi_host_template scsi_driver_template = {
 	.module =			THIS_MODULE,
 	.name =				"SBP-2 IEEE-1394",
 	.proc_name =			SBP2_DEVICE_NAME,
-	.info =				sbp2scsi_info,
 	.queuecommand =			sbp2scsi_queuecommand,
 	.eh_abort_handler =		sbp2scsi_abort,
 	.eh_device_reset_handler =	sbp2scsi_reset,
-	.eh_bus_reset_handler =		sbp2scsi_reset,
-	.eh_host_reset_handler =	sbp2scsi_reset,
 	.slave_alloc =			sbp2scsi_slave_alloc,
 	.slave_configure =		sbp2scsi_slave_configure,
 	.slave_destroy =		sbp2scsi_slave_destroy,
@@ -2861,8 +2624,6 @@ static int sbp2_module_init(void)
 
 	SBP2_DEBUG("sbp2_module_init");
 
-	printk(KERN_INFO "sbp2: %s\n", version);
-
 	/* Module load debug option to force one command at a time (serializing I/O) */
 	if (serialize_io) {
 		SBP2_INFO("Driver forced to serialize I/O (serialize_io=1)");
@@ -2874,7 +2635,6 @@ static int sbp2_module_init(void)
 	/* Set max sectors (module load option). Default is 255 sectors. */
 	scsi_driver_template.max_sectors = max_sectors;
 
-
 	/* Register our high level driver with 1394 stack */
 	hpsb_register_highlevel(&sbp2_highlevel);
 
diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h
index cd425be74841..900ea1d25e71 100644
--- a/drivers/ieee1394/sbp2.h
+++ b/drivers/ieee1394/sbp2.h
@@ -119,8 +119,8 @@ struct sbp2_query_logins_response {
 struct sbp2_reconnect_orb {
 	u32 reserved1;
 	u32 reserved2;
-        u32 reserved3;
-        u32 reserved4;
+	u32 reserved3;
+	u32 reserved4;
 	u32 login_ID_misc;
 	u32 reserved5;
 	u32 status_FIFO_hi;
@@ -130,8 +130,8 @@ struct sbp2_reconnect_orb {
 struct sbp2_logout_orb {
 	u32 reserved1;
 	u32 reserved2;
-        u32 reserved3;
-        u32 reserved4;
+	u32 reserved3;
+	u32 reserved4;
 	u32 login_ID_misc;
 	u32 reserved5;
 	u32 status_FIFO_hi;
@@ -188,7 +188,7 @@ struct sbp2_unrestricted_page_table {
 struct sbp2_status_block {
 	u32 ORB_offset_hi_misc;
 	u32 ORB_offset_lo;
-        u8 command_set_dependent[24];
+	u8 command_set_dependent[24];
 };
 
 /*
@@ -211,7 +211,7 @@ struct sbp2_status_block {
  * specified for write posting, where the ohci controller will
  * automatically send an ack_complete when the status is written by the
  * sbp2 device... saving a split transaction.   =)
- */ 
+ */
 #define SBP2_STATUS_FIFO_ADDRESS				0xfffe00000000ULL
 #define SBP2_STATUS_FIFO_ADDRESS_HI                             0xfffe
 #define SBP2_STATUS_FIFO_ADDRESS_LO                             0x0
@@ -229,9 +229,6 @@ struct sbp2_status_block {
 #define SBP2_DEVICE_TYPE_AND_LUN_KEY				0x14
 #define SBP2_FIRMWARE_REVISION_KEY				0x3c
 
-#define SBP2_DEVICE_TYPE(q)					(((q) >> 16) & 0x1f)
-#define SBP2_DEVICE_LUN(q)					((q) & 0xffff)
-
 #define SBP2_AGENT_STATE_OFFSET					0x00ULL
 #define SBP2_AGENT_RESET_OFFSET					0x04ULL
 #define SBP2_ORB_POINTER_OFFSET					0x08ULL
@@ -256,8 +253,6 @@ struct sbp2_status_block {
  */
 #define SBP2_128KB_BROKEN_FIRMWARE				0xa0b800
 
-#define SBP2_DEVICE_TYPE_LUN_UNINITIALIZED			0xffffffff
-
 /*
  * SCSI specific stuff
  */
@@ -265,45 +260,7 @@ struct sbp2_status_block {
 #define SBP2_MAX_SG_ELEMENT_LENGTH	0xf000
 #define SBP2_MAX_UDS_PER_NODE		16	/* Maximum scsi devices per node */
 #define SBP2_MAX_SECTORS		255	/* Max sectors supported */
-
-/*
- * SCSI direction table...
- * (now used as a back-up in case the direction passed down from above is "unknown")
- *
- * DIN = IN data direction
- * DOU = OUT data direction
- * DNO = No data transfer
- * DUN = Unknown data direction
- *
- * Opcode 0xec (Teac specific "opc execute") possibly should be DNO,
- * but we'll change it when somebody reports a problem with this.
- */
-#define DIN				ORB_DIRECTION_READ_FROM_MEDIA
-#define DOU				ORB_DIRECTION_WRITE_TO_MEDIA
-#define DNO				ORB_DIRECTION_NO_DATA_TRANSFER
-#define DUN				DIN
-
-static unchar sbp2scsi_direction_table[0x100] = {
-	DNO,DNO,DIN,DIN,DOU,DIN,DIN,DOU,DIN,DUN,DOU,DOU,DUN,DUN,DUN,DIN,
-	DNO,DIN,DIN,DOU,DIN,DOU,DNO,DNO,DOU,DNO,DIN,DNO,DIN,DOU,DNO,DUN,
-	DIN,DUN,DIN,DIN,DOU,DIN,DUN,DUN,DIN,DIN,DOU,DNO,DUN,DIN,DOU,DOU,
-	DOU,DOU,DOU,DNO,DIN,DNO,DNO,DIN,DOU,DOU,DOU,DOU,DIN,DOU,DIN,DOU,
-	DOU,DOU,DIN,DIN,DIN,DNO,DIN,DNO,DNO,DNO,DUN,DNO,DOU,DIN,DNO,DUN,
-	DUN,DIN,DIN,DNO,DNO,DOU,DUN,DUN,DNO,DIN,DIN,DNO,DIN,DOU,DUN,DUN,
-	DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
-	DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
-	DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
-	DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
-	DUN,DNO,DOU,DOU,DIN,DNO,DNO,DNO,DIN,DNO,DOU,DUN,DNO,DIN,DOU,DOU,
-	DOU,DOU,DOU,DNO,DUN,DIN,DOU,DIN,DIN,DIN,DNO,DNO,DNO,DIN,DIN,DUN,
-	DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
-	DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
-	DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DOU,DUN,DUN,DUN,DUN,DUN,
-	DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN
-};
-
-/* This should be safe */
-#define SBP2_MAX_CMDS		8
+#define SBP2_MAX_CMDS			8	/* This should be safe */
 
 /* This is the two dma types we use for cmd_dma below */
 enum cmd_dma_types {
@@ -338,10 +295,8 @@ struct sbp2_command_info {
 #define SBP2_BREAKAGE_128K_MAX_TRANSFER		0x1
 #define SBP2_BREAKAGE_INQUIRY_HACK		0x2
 
-
 struct sbp2scsi_host_info;
 
-
 /*
  * Information needed on a per scsi id basis (one for each sbp2 device)
  */
@@ -379,7 +334,7 @@ struct scsi_id_instance_data {
 	u32 sbp2_command_set_spec_id;
 	u32 sbp2_command_set;
 	u32 sbp2_unit_characteristics;
-	u32 sbp2_device_type_and_lun;
+	u32 sbp2_lun;
 	u32 sbp2_firmware_revision;
 
 	/*
@@ -411,7 +366,6 @@ struct scsi_id_instance_data {
 	u32 workarounds;
 };
 
-
 /* Sbp2 host data structure (one per IEEE1394 host) */
 struct sbp2scsi_host_info {
 	struct hpsb_host *host;		/* IEEE1394 host */
@@ -456,20 +410,12 @@ static int sbp2_logout_device(struct scsi_id_instance_data *scsi_id);
 static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int destid,
 				    quadlet_t *data, u64 addr, size_t length, u16 flags);
 static int sbp2_agent_reset(struct scsi_id_instance_data *scsi_id, int wait);
-static int sbp2_create_command_orb(struct scsi_id_instance_data *scsi_id,
-				   struct sbp2_command_info *command,
-				   unchar *scsi_cmd,
-				   unsigned int scsi_use_sg,
-				   unsigned int scsi_request_bufflen,
-				   void *scsi_request_buffer,
-				   enum dma_data_direction dma_dir);
 static int sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id,
 				 struct sbp2_command_info *command);
 static int sbp2_send_command(struct scsi_id_instance_data *scsi_id,
 			     struct scsi_cmnd *SCpnt,
 			     void (*done)(struct scsi_cmnd *));
 static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, unchar *sense_data);
-static void sbp2_check_sbp2_command(struct scsi_id_instance_data *scsi_id, unchar *cmd);
 static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id,
 				     struct scsi_cmnd *SCpnt);
 static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
index 23911da50154..608479b2df14 100644
--- a/drivers/ieee1394/video1394.c
+++ b/drivers/ieee1394/video1394.c
@@ -19,12 +19,6 @@
  *
  * NOTES:
  *
- * jds -- add private data to file to keep track of iso contexts associated
- * with each open -- so release won't kill all iso transfers.
- * 
- * Damien Douxchamps: Fix failure when the number of DMA pages per frame is
- * one.
- * 
  * ioctl return codes:
  * EFAULT is only for invalid address for the argp
  * EINVAL for out of range values
@@ -34,12 +28,6 @@
  * ENOTTY for unsupported ioctl request
  *
  */
-
-/* Markus Tavenrath <speedygoo@speedygoo.de> :
-   - fixed checks for valid buffer-numbers in video1394_icotl
-   - changed the ways the dma prg's are used, now it's possible to use
-     even a single dma buffer
-*/
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
@@ -77,14 +65,6 @@
 
 #define ISO_CHANNELS 64
 
-#ifndef virt_to_page
-#define virt_to_page(x) MAP_NR(x)
-#endif
-
-#ifndef vmalloc_32
-#define vmalloc_32(x) vmalloc(x)
-#endif
-
 struct it_dma_prg {
 	struct dma_cmd begin;
 	quadlet_t data[4];
@@ -206,14 +186,12 @@ alloc_dma_iso_ctx(struct ti_ohci *ohci, int type, int num_desc,
 	struct dma_iso_ctx *d;
 	int i;
 
-	d = kmalloc(sizeof(struct dma_iso_ctx), GFP_KERNEL);
-	if (d == NULL) {
+	d = kzalloc(sizeof(*d), GFP_KERNEL);
+	if (!d) {
 		PRINT(KERN_ERR, ohci->host->id, "Failed to allocate dma_iso_ctx");
 		return NULL;
 	}
 
-	memset(d, 0, sizeof *d);
-
 	d->ohci = ohci;
 	d->type = type;
 	d->channel = channel;
@@ -251,9 +229,8 @@ alloc_dma_iso_ctx(struct ti_ohci *ohci, int type, int num_desc,
 	}
 	d->ctx = d->iso_tasklet.context;
 
-	d->prg_reg = kmalloc(d->num_desc * sizeof(struct dma_prog_region),
-			GFP_KERNEL);
-	if (d->prg_reg == NULL) {
+	d->prg_reg = kmalloc(d->num_desc * sizeof(*d->prg_reg), GFP_KERNEL);
+	if (!d->prg_reg) {
 		PRINT(KERN_ERR, ohci->host->id, "Failed to allocate ir prg regs");
 		free_dma_iso_ctx(d);
 		return NULL;
@@ -268,15 +245,14 @@ alloc_dma_iso_ctx(struct ti_ohci *ohci, int type, int num_desc,
 		d->cmdPtr = OHCI1394_IsoRcvCommandPtr+32*d->ctx;
 		d->ctxMatch = OHCI1394_IsoRcvContextMatch+32*d->ctx;
 
-		d->ir_prg = kmalloc(d->num_desc * sizeof(struct dma_cmd *),
+		d->ir_prg = kzalloc(d->num_desc * sizeof(*d->ir_prg),
 				    GFP_KERNEL);
 
-		if (d->ir_prg == NULL) {
+		if (!d->ir_prg) {
 			PRINT(KERN_ERR, ohci->host->id, "Failed to allocate dma ir prg");
 			free_dma_iso_ctx(d);
 			return NULL;
 		}
-		memset(d->ir_prg, 0, d->num_desc * sizeof(struct dma_cmd *));
 
 		d->nb_cmd = d->buf_size / PAGE_SIZE + 1;
 		d->left_size = (d->frame_size % PAGE_SIZE) ?
@@ -297,16 +273,15 @@ alloc_dma_iso_ctx(struct ti_ohci *ohci, int type, int num_desc,
 		d->ctrlClear = OHCI1394_IsoXmitContextControlClear+16*d->ctx;
 		d->cmdPtr = OHCI1394_IsoXmitCommandPtr+16*d->ctx;
 
-		d->it_prg = kmalloc(d->num_desc * sizeof(struct it_dma_prg *),
+		d->it_prg = kzalloc(d->num_desc * sizeof(*d->it_prg),
 				    GFP_KERNEL);
 
-		if (d->it_prg == NULL) {
+		if (!d->it_prg) {
 			PRINT(KERN_ERR, ohci->host->id,
 			      "Failed to allocate dma it prg");
 			free_dma_iso_ctx(d);
 			return NULL;
 		}
-		memset(d->it_prg, 0, d->num_desc*sizeof(struct it_dma_prg *));
 
 		d->packet_size = packet_size;
 
@@ -337,47 +312,24 @@ alloc_dma_iso_ctx(struct ti_ohci *ohci, int type, int num_desc,
 		}
 	}
 
-	d->buffer_status = kmalloc(d->num_desc * sizeof(unsigned int),
-				   GFP_KERNEL);
-	d->buffer_prg_assignment = kmalloc(d->num_desc * sizeof(unsigned int),
-				   GFP_KERNEL);
-	d->buffer_time = kmalloc(d->num_desc * sizeof(struct timeval),
-				   GFP_KERNEL);
-	d->last_used_cmd = kmalloc(d->num_desc * sizeof(unsigned int),
-				   GFP_KERNEL);
-	d->next_buffer = kmalloc(d->num_desc * sizeof(int),
-				 GFP_KERNEL);
-
-	if (d->buffer_status == NULL) {
-		PRINT(KERN_ERR, ohci->host->id, "Failed to allocate buffer_status");
-		free_dma_iso_ctx(d);
-		return NULL;
-	}
-	if (d->buffer_prg_assignment == NULL) {
-		PRINT(KERN_ERR, ohci->host->id, "Failed to allocate buffer_prg_assignment");
-		free_dma_iso_ctx(d);
-		return NULL;
-	}
-	if (d->buffer_time == NULL) {
-		PRINT(KERN_ERR, ohci->host->id, "Failed to allocate buffer_time");
-		free_dma_iso_ctx(d);
-		return NULL;
-	}
-	if (d->last_used_cmd == NULL) {
-		PRINT(KERN_ERR, ohci->host->id, "Failed to allocate last_used_cmd");
-		free_dma_iso_ctx(d);
-		return NULL;
-	}
-	if (d->next_buffer == NULL) {
-		PRINT(KERN_ERR, ohci->host->id, "Failed to allocate next_buffer");
+	d->buffer_status =
+	    kzalloc(d->num_desc * sizeof(*d->buffer_status), GFP_KERNEL);
+	d->buffer_prg_assignment =
+	    kzalloc(d->num_desc * sizeof(*d->buffer_prg_assignment), GFP_KERNEL);
+	d->buffer_time =
+	    kzalloc(d->num_desc * sizeof(*d->buffer_time), GFP_KERNEL);
+	d->last_used_cmd =
+	    kzalloc(d->num_desc * sizeof(*d->last_used_cmd), GFP_KERNEL);
+	d->next_buffer =
+	    kzalloc(d->num_desc * sizeof(*d->next_buffer), GFP_KERNEL);
+
+	if (!d->buffer_status || !d->buffer_prg_assignment || !d->buffer_time ||
+	    !d->last_used_cmd || !d->next_buffer) {
+		PRINT(KERN_ERR, ohci->host->id,
+		      "Failed to allocate dma_iso_ctx member");
 		free_dma_iso_ctx(d);
 		return NULL;
 	}
-	memset(d->buffer_status, 0, d->num_desc * sizeof(unsigned int));
-	memset(d->buffer_prg_assignment, 0, d->num_desc * sizeof(unsigned int));
-	memset(d->buffer_time, 0, d->num_desc * sizeof(struct timeval));
-	memset(d->last_used_cmd, 0, d->num_desc * sizeof(unsigned int));
-	memset(d->next_buffer, -1, d->num_desc * sizeof(int));
 
         spin_lock_init(&d->lock);
 
@@ -539,7 +491,7 @@ static void wakeup_dma_ir_ctx(unsigned long l)
 		if (d->ir_prg[i][d->nb_cmd-1].status & cpu_to_le32(0xFFFF0000)) {
 			reset_ir_status(d, i);
 			d->buffer_status[d->buffer_prg_assignment[i]] = VIDEO1394_BUFFER_READY;
-			do_gettimeofday(&d->buffer_time[i]);
+			do_gettimeofday(&d->buffer_time[d->buffer_prg_assignment[i]]);
 		}
 	}
 
@@ -1046,7 +998,6 @@ static int __video1394_ioctl(struct file *file,
 
 		/* set time of buffer */
 		v.filltime = d->buffer_time[v.buffer];
-//		printk("Buffer %d time %d\n", v.buffer, (d->buffer_time[v.buffer]).tv_usec);
 
 		/*
 		 * Look ahead to see how many more buffers have been received
@@ -1085,7 +1036,7 @@ static int __video1394_ioctl(struct file *file,
 		}
 
 		if (d->flags & VIDEO1394_VARIABLE_PACKET_SIZE) {
-			int buf_size = d->nb_cmd * sizeof(unsigned int);
+			int buf_size = d->nb_cmd * sizeof(*psizes);
 			struct video1394_queue_variable __user *p = argp;
 			unsigned int __user *qv;
 
@@ -1104,7 +1055,7 @@ static int __video1394_ioctl(struct file *file,
 
 		spin_lock_irqsave(&d->lock,flags);
 
-		// last_buffer is last_prg
+		/* last_buffer is last_prg */
 		next_prg = (d->last_buffer + 1) % d->num_desc;
 		if (d->buffer_status[v.buffer]!=VIDEO1394_BUFFER_FREE) {
 			PRINT(KERN_ERR, ohci->host->id,
@@ -1251,13 +1202,12 @@ static int video1394_open(struct inode *inode, struct file *file)
         if (ohci == NULL)
                 return -EIO;
 
-	ctx = kmalloc(sizeof(struct file_ctx), GFP_KERNEL);
-	if (ctx == NULL)  {
+	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)  {
 		PRINT(KERN_ERR, ohci->host->id, "Cannot malloc file_ctx");
 		return -ENOMEM;
 	}
 
-	memset(ctx, 0, sizeof(struct file_ctx));
 	ctx->ohci = ohci;
 	INIT_LIST_HEAD(&ctx->context_list);
 	ctx->current_ctx = NULL;
diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c
index 08648b1a387e..1f1743c5c9a3 100644
--- a/drivers/infiniband/core/sysfs.c
+++ b/drivers/infiniband/core/sysfs.c
@@ -434,24 +434,24 @@ static void ib_device_release(struct class_device *cdev)
 	kfree(dev);
 }
 
-static int ib_device_hotplug(struct class_device *cdev, char **envp,
-			     int num_envp, char *buf, int size)
+static int ib_device_uevent(struct class_device *cdev, char **envp,
+			    int num_envp, char *buf, int size)
 {
 	struct ib_device *dev = container_of(cdev, struct ib_device, class_dev);
 	int i = 0, len = 0;
 
-	if (add_hotplug_env_var(envp, num_envp, &i, buf, size, &len,
-				"NAME=%s", dev->name))
+	if (add_uevent_var(envp, num_envp, &i, buf, size, &len,
+			   "NAME=%s", dev->name))
 		return -ENOMEM;
 
 	/*
-	 * It might be nice to pass the node GUID to hotplug, but
+	 * It might be nice to pass the node GUID with the event, but
 	 * right now the only way to get it is to query the device
 	 * provider, and this can crash during device removal because
 	 * we are will be running after driver removal has started.
 	 * We could add a node_guid field to struct ib_device, or we
-	 * could just let the hotplug script read the node GUID from
-	 * sysfs when devices are added.
+	 * could just let userspace read the node GUID from sysfs when
+	 * devices are added.
 	 */
 
 	envp[i] = NULL;
@@ -653,7 +653,7 @@ static struct class_device_attribute *ib_class_attributes[] = {
 static struct class ib_class = {
 	.name    = "infiniband",
 	.release = ib_device_release,
-	.hotplug = ib_device_hotplug,
+	.uevent = ib_device_uevent,
 };
 
 int ib_device_register_sysfs(struct ib_device *device)
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 475d98fa9e26..780009c7eaa6 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -47,6 +47,8 @@
 #include <linux/ip.h>
 #include <linux/in.h>
 
+#include <net/dst.h>
+
 MODULE_AUTHOR("Roland Dreier");
 MODULE_DESCRIPTION("IP-over-InfiniBand net driver");
 MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index ef3ee035bbc8..ed0c2ead8bc1 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -43,6 +43,8 @@
 #include <linux/delay.h>
 #include <linux/completion.h>
 
+#include <net/dst.h>
+
 #include "ipoib.h"
 
 #ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 9f2352bd8348..a1e660e3531d 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -157,7 +157,7 @@ struct input_event_compat {
 #  define COMPAT_TEST test_thread_flag(TIF_IA32)
 #elif defined(CONFIG_IA64)
 #  define COMPAT_TEST IS_IA32_PROCESS(ia64_task_regs(current))
-#elif defined(CONFIG_ARCH_S390)
+#elif defined(CONFIG_S390)
 #  define COMPAT_TEST test_thread_flag(TIF_31BIT)
 #elif defined(CONFIG_MIPS)
 #  define COMPAT_TEST (current->thread.mflags & MF_32BIT_ADDR)
diff --git a/drivers/input/input.c b/drivers/input/input.c
index bdd2a7fc268d..ef5824c8846b 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -18,7 +18,6 @@
 #include <linux/random.h>
 #include <linux/major.h>
 #include <linux/proc_fs.h>
-#include <linux/kobject_uevent.h>
 #include <linux/interrupt.h>
 #include <linux/poll.h>
 #include <linux/device.h>
@@ -529,10 +528,49 @@ INPUT_DEV_STRING_ATTR_SHOW(name);
 INPUT_DEV_STRING_ATTR_SHOW(phys);
 INPUT_DEV_STRING_ATTR_SHOW(uniq);
 
+static int print_modalias_bits(char *buf, char prefix, unsigned long *arr,
+			       unsigned int min, unsigned int max)
+{
+	int len, i;
+
+	len = sprintf(buf, "%c", prefix);
+	for (i = min; i < max; i++)
+		if (arr[LONG(i)] & BIT(i))
+			len += sprintf(buf+len, "%X,", i);
+	return len;
+}
+
+static ssize_t input_dev_show_modalias(struct class_device *dev, char *buf)
+{
+	struct input_dev *id = to_input_dev(dev);
+	ssize_t len = 0;
+
+	len += sprintf(buf+len, "input:b%04Xv%04Xp%04Xe%04X-",
+		       id->id.bustype,
+		       id->id.vendor,
+		       id->id.product,
+		       id->id.version);
+
+	len += print_modalias_bits(buf+len, 'e', id->evbit, 0, EV_MAX);
+	len += print_modalias_bits(buf+len, 'k', id->keybit,
+				   KEY_MIN_INTERESTING, KEY_MAX);
+	len += print_modalias_bits(buf+len, 'r', id->relbit, 0, REL_MAX);
+	len += print_modalias_bits(buf+len, 'a', id->absbit, 0, ABS_MAX);
+	len += print_modalias_bits(buf+len, 'm', id->mscbit, 0, MSC_MAX);
+	len += print_modalias_bits(buf+len, 'l', id->ledbit, 0, LED_MAX);
+	len += print_modalias_bits(buf+len, 's', id->sndbit, 0, SND_MAX);
+	len += print_modalias_bits(buf+len, 'f', id->ffbit, 0, FF_MAX);
+	len += print_modalias_bits(buf+len, 'w', id->swbit, 0, SW_MAX);
+	len += sprintf(buf+len, "\n");
+	return len;
+}
+static CLASS_DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL);
+
 static struct attribute *input_dev_attrs[] = {
 	&class_device_attr_name.attr,
 	&class_device_attr_phys.attr,
 	&class_device_attr_uniq.attr,
+	&class_device_attr_modalias.attr,
 	NULL
 };
 
@@ -611,10 +649,10 @@ static void input_dev_release(struct class_device *class_dev)
 }
 
 /*
- * Input hotplugging interface - loading event handlers based on
+ * Input uevent interface - loading event handlers based on
  * device bitfields.
  */
-static int input_add_hotplug_bm_var(char **envp, int num_envp, int *cur_index,
+static int input_add_uevent_bm_var(char **envp, int num_envp, int *cur_index,
 				    char *buffer, int buffer_size, int *cur_len,
 				    const char *name, unsigned long *bitmap, int max)
 {
@@ -639,7 +677,7 @@ static int input_add_hotplug_bm_var(char **envp, int num_envp, int *cur_index,
 
 #define INPUT_ADD_HOTPLUG_VAR(fmt, val...)				\
 	do {								\
-		int err = add_hotplug_env_var(envp, num_envp, &i,	\
+		int err = add_uevent_var(envp, num_envp, &i,	\
 					buffer, buffer_size, &len,	\
 					fmt, val);			\
 		if (err)						\
@@ -648,15 +686,15 @@ static int input_add_hotplug_bm_var(char **envp, int num_envp, int *cur_index,
 
 #define INPUT_ADD_HOTPLUG_BM_VAR(name, bm, max)				\
 	do {								\
-		int err = input_add_hotplug_bm_var(envp, num_envp, &i,	\
+		int err = input_add_uevent_bm_var(envp, num_envp, &i,	\
 					buffer, buffer_size, &len,	\
 					name, bm, max);			\
 		if (err)						\
 			return err;					\
 	} while (0)
 
-static int input_dev_hotplug(struct class_device *cdev, char **envp,
-			     int num_envp, char *buffer, int buffer_size)
+static int input_dev_uevent(struct class_device *cdev, char **envp,
+			    int num_envp, char *buffer, int buffer_size)
 {
 	struct input_dev *dev = to_input_dev(cdev);
 	int i = 0;
@@ -698,7 +736,7 @@ static int input_dev_hotplug(struct class_device *cdev, char **envp,
 struct class input_class = {
 	.name			= "input",
 	.release		= input_dev_release,
-	.hotplug		= input_dev_hotplug,
+	.uevent			= input_dev_uevent,
 };
 
 struct input_dev *input_allocate_device(void)
diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c
index 64b4a3080985..bc2fce60f9f8 100644
--- a/drivers/input/joystick/iforce/iforce-usb.c
+++ b/drivers/input/joystick/iforce/iforce-usb.c
@@ -235,7 +235,6 @@ static struct usb_device_id iforce_usb_ids [] = {
 MODULE_DEVICE_TABLE (usb, iforce_usb_ids);
 
 struct usb_driver iforce_usb_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"iforce",
 	.probe =	iforce_usb_probe,
 	.disconnect =	iforce_usb_disconnect,
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index fbb69ef6a77b..8e530cc970e1 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -800,16 +800,16 @@ static int serio_bus_match(struct device *dev, struct device_driver *drv)
 
 #ifdef CONFIG_HOTPLUG
 
-#define SERIO_ADD_HOTPLUG_VAR(fmt, val...)				\
+#define SERIO_ADD_UEVENT_VAR(fmt, val...)				\
 	do {								\
-		int err = add_hotplug_env_var(envp, num_envp, &i,	\
+		int err = add_uevent_var(envp, num_envp, &i,	\
 					buffer, buffer_size, &len,	\
 					fmt, val);			\
 		if (err)						\
 			return err;					\
 	} while (0)
 
-static int serio_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
+static int serio_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
 {
 	struct serio *serio;
 	int i = 0;
@@ -820,21 +820,21 @@ static int serio_hotplug(struct device *dev, char **envp, int num_envp, char *bu
 
 	serio = to_serio_port(dev);
 
-	SERIO_ADD_HOTPLUG_VAR("SERIO_TYPE=%02x", serio->id.type);
-	SERIO_ADD_HOTPLUG_VAR("SERIO_PROTO=%02x", serio->id.proto);
-	SERIO_ADD_HOTPLUG_VAR("SERIO_ID=%02x", serio->id.id);
-	SERIO_ADD_HOTPLUG_VAR("SERIO_EXTRA=%02x", serio->id.extra);
-	SERIO_ADD_HOTPLUG_VAR("MODALIAS=serio:ty%02Xpr%02Xid%02Xex%02X",
+	SERIO_ADD_UEVENT_VAR("SERIO_TYPE=%02x", serio->id.type);
+	SERIO_ADD_UEVENT_VAR("SERIO_PROTO=%02x", serio->id.proto);
+	SERIO_ADD_UEVENT_VAR("SERIO_ID=%02x", serio->id.id);
+	SERIO_ADD_UEVENT_VAR("SERIO_EXTRA=%02x", serio->id.extra);
+	SERIO_ADD_UEVENT_VAR("MODALIAS=serio:ty%02Xpr%02Xid%02Xex%02X",
 				serio->id.type, serio->id.proto, serio->id.id, serio->id.extra);
 	envp[i] = NULL;
 
 	return 0;
 }
-#undef SERIO_ADD_HOTPLUG_VAR
+#undef SERIO_ADD_UEVENT_VAR
 
 #else
 
-static int serio_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
+static int serio_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
 {
 	return -ENODEV;
 }
@@ -908,7 +908,7 @@ static int __init serio_init(void)
 	serio_bus.dev_attrs = serio_device_attrs;
 	serio_bus.drv_attrs = serio_driver_attrs;
 	serio_bus.match = serio_bus_match;
-	serio_bus.hotplug = serio_hotplug;
+	serio_bus.uevent = serio_uevent;
 	serio_bus.resume = serio_resume;
 	bus_register(&serio_bus);
 
diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c
index 27391c32f3eb..2a2b03ff096b 100644
--- a/drivers/isdn/hardware/avm/avm_cs.c
+++ b/drivers/isdn/hardware/avm/avm_cs.c
@@ -53,8 +53,6 @@ MODULE_LICENSE("GPL");
 
 static void avmcs_config(dev_link_t *link);
 static void avmcs_release(dev_link_t *link);
-static int avmcs_event(event_t event, int priority,
-			  event_callback_args_t *args);
 
 /*
    The attach() and detach() entry points are used to create and destroy
@@ -62,16 +60,7 @@ static int avmcs_event(event_t event, int priority,
    needed to manage one actual PCMCIA card.
 */
 
-static dev_link_t *avmcs_attach(void);
-static void avmcs_detach(dev_link_t *);
-
-/*
-   The dev_info variable is the "key" that is used to match up this
-   device driver with appropriate cards, through the card configuration
-   database.
-*/
-
-static dev_info_t dev_info = "avm_cs";
+static void avmcs_detach(struct pcmcia_device *p_dev);
 
 /*
    A linked list of "instances" of the skeleton device.  Each actual
@@ -83,15 +72,7 @@ static dev_info_t dev_info = "avm_cs";
    device numbers are used to derive the corresponding array index.
 */
 
-static dev_link_t *dev_list = NULL;
-
 /*
-   A dev_link_t structure has fields for most things that are needed
-   to keep track of a socket, but there will usually be some device
-   specific information that also needs to be kept track of.  The
-   'priv' pointer in a dev_link_t structure can be used to point to
-   a device-specific private data structure, like this.
-
    A driver needs to provide a dev_node_t structure for each device
    on a card.  In some cases, there is only one device per card (for
    example, ethernet cards, modems).  In other cases, there may be
@@ -118,13 +99,11 @@ typedef struct local_info_t {
     
 ======================================================================*/
 
-static dev_link_t *avmcs_attach(void)
+static int avmcs_attach(struct pcmcia_device *p_dev)
 {
-    client_reg_t client_reg;
     dev_link_t *link;
     local_info_t *local;
-    int ret;
-    
+
     /* Initialize the dev_link_t structure */
     link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
     if (!link)
@@ -155,25 +134,19 @@ static dev_link_t *avmcs_attach(void)
         goto err_kfree;
     memset(local, 0, sizeof(local_info_t));
     link->priv = local;
-    
-    /* Register with Card Services */
-    link->next = dev_list;
-    dev_list = link;
-    client_reg.dev_info = &dev_info;
-    client_reg.Version = 0x0210;
-    client_reg.event_callback_args.client_data = link;
-    ret = pcmcia_register_client(&link->handle, &client_reg);
-    if (ret != 0) {
-	cs_error(link->handle, RegisterClient, ret);
-	avmcs_detach(link);
-	goto err;
-    }
-    return link;
+
+    link->handle = p_dev;
+    p_dev->instance = link;
+
+    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+    avmcs_config(link);
+
+    return 0;
 
  err_kfree:
     kfree(link);
  err:
-    return NULL;
+    return -EINVAL;
 } /* avmcs_attach */
 
 /*======================================================================
@@ -185,33 +158,13 @@ static dev_link_t *avmcs_attach(void)
 
 ======================================================================*/
 
-static void avmcs_detach(dev_link_t *link)
+static void avmcs_detach(struct pcmcia_device *p_dev)
 {
-    dev_link_t **linkp;
-
-    /* Locate device structure */
-    for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
-	if (*linkp == link) break;
-    if (*linkp == NULL)
-	return;
+    dev_link_t *link = dev_to_instance(p_dev);
 
-    /*
-       If the device is currently configured and active, we won't
-       actually delete it yet.  Instead, it is marked so that when
-       the release() function is called, that will trigger a proper
-       detach().
-    */
-    if (link->state & DEV_CONFIG) {
-	link->state |= DEV_STALE_LINK;
-	return;
-    }
+    if (link->state & DEV_CONFIG)
+	avmcs_release(link);
 
-    /* Break the link with Card Services */
-    if (link->handle)
-	pcmcia_deregister_client(link->handle);
-    
-    /* Unlink device structure, free pieces */
-    *linkp = link->next;
     kfree(link->priv);
     kfree(link);
 } /* avmcs_detach */
@@ -424,12 +377,30 @@ static void avmcs_release(dev_link_t *link)
     pcmcia_release_io(link->handle, &link->io);
     pcmcia_release_irq(link->handle, &link->irq);
     link->state &= ~DEV_CONFIG;
-    
-    if (link->state & DEV_STALE_LINK)
-	avmcs_detach(link);
-    
 } /* avmcs_release */
 
+static int avmcs_suspend(struct pcmcia_device *dev)
+{
+	dev_link_t *link = dev_to_instance(dev);
+
+	link->state |= DEV_SUSPEND;
+	if (link->state & DEV_CONFIG)
+		pcmcia_release_configuration(link->handle);
+
+	return 0;
+}
+
+static int avmcs_resume(struct pcmcia_device *dev)
+{
+	dev_link_t *link = dev_to_instance(dev);
+
+	link->state &= ~DEV_SUSPEND;
+	if (link->state & DEV_CONFIG)
+		pcmcia_request_configuration(link->handle, &link->conf);
+
+	return 0;
+}
+
 /*======================================================================
 
     The card status event handler.  Mostly, this schedules other
@@ -444,38 +415,6 @@ static void avmcs_release(dev_link_t *link)
     
 ======================================================================*/
 
-static int avmcs_event(event_t event, int priority,
-			  event_callback_args_t *args)
-{
-    dev_link_t *link = args->client_data;
-
-    switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-	link->state &= ~DEV_PRESENT;
-	if (link->state & DEV_CONFIG)
-		avmcs_release(link);
-	break;
-    case CS_EVENT_CARD_INSERTION:
-	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-	avmcs_config(link);
-	break;
-    case CS_EVENT_PM_SUSPEND:
-	link->state |= DEV_SUSPEND;
-	/* Fall through... */
-    case CS_EVENT_RESET_PHYSICAL:
-	if (link->state & DEV_CONFIG)
-	    pcmcia_release_configuration(link->handle);
-	break;
-    case CS_EVENT_PM_RESUME:
-	link->state &= ~DEV_SUSPEND;
-	/* Fall through... */
-    case CS_EVENT_CARD_RESET:
-	if (link->state & DEV_CONFIG)
-	    pcmcia_request_configuration(link->handle, &link->conf);
-	break;
-    }
-    return 0;
-} /* avmcs_event */
 
 static struct pcmcia_device_id avmcs_ids[] = {
 	PCMCIA_DEVICE_PROD_ID12("AVM", "ISDN-Controller B1", 0x95d42008, 0x845dc335),
@@ -490,10 +429,11 @@ static struct pcmcia_driver avmcs_driver = {
 	.drv	= {
 		.name	= "avm_cs",
 	},
-	.attach	= avmcs_attach,
-	.event	= avmcs_event,
-	.detach	= avmcs_detach,
+	.probe = avmcs_attach,
+	.remove	= avmcs_detach,
 	.id_table = avmcs_ids,
+	.suspend= avmcs_suspend,
+	.resume = avmcs_resume,
 };
 
 static int __init avmcs_init(void)
@@ -504,7 +444,6 @@ static int __init avmcs_init(void)
 static void __exit avmcs_exit(void)
 {
 	pcmcia_unregister_driver(&avmcs_driver);
-	BUG_ON(dev_list != NULL);
 }
 
 module_init(avmcs_init);
diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c
index 5f5a5ae740d2..969da40c4248 100644
--- a/drivers/isdn/hisax/avma1_cs.c
+++ b/drivers/isdn/hisax/avma1_cs.c
@@ -69,8 +69,6 @@ module_param(isdnprot, int, 0);
 
 static void avma1cs_config(dev_link_t *link);
 static void avma1cs_release(dev_link_t *link);
-static int avma1cs_event(event_t event, int priority,
-			  event_callback_args_t *args);
 
 /*
    The attach() and detach() entry points are used to create and destroy
@@ -78,16 +76,8 @@ static int avma1cs_event(event_t event, int priority,
    needed to manage one actual PCMCIA card.
 */
 
-static dev_link_t *avma1cs_attach(void);
-static void avma1cs_detach(dev_link_t *);
+static void avma1cs_detach(struct pcmcia_device *p_dev);
 
-/*
-   The dev_info variable is the "key" that is used to match up this
-   device driver with appropriate cards, through the card configuration
-   database.
-*/
-
-static dev_info_t dev_info = "avma1_cs";
 
 /*
    A linked list of "instances" of the skeleton device.  Each actual
@@ -99,15 +89,7 @@ static dev_info_t dev_info = "avma1_cs";
    device numbers are used to derive the corresponding array index.
 */
 
-static dev_link_t *dev_list = NULL;
-
 /*
-   A dev_link_t structure has fields for most things that are needed
-   to keep track of a socket, but there will usually be some device
-   specific information that also needs to be kept track of.  The
-   'priv' pointer in a dev_link_t structure can be used to point to
-   a device-specific private data structure, like this.
-
    A driver needs to provide a dev_node_t structure for each device
    on a card.  In some cases, there is only one device per card (for
    example, ethernet cards, modems).  In other cases, there may be
@@ -134,26 +116,24 @@ typedef struct local_info_t {
     
 ======================================================================*/
 
-static dev_link_t *avma1cs_attach(void)
+static int avma1cs_attach(struct pcmcia_device *p_dev)
 {
-    client_reg_t client_reg;
     dev_link_t *link;
     local_info_t *local;
-    int ret;
-    
+
     DEBUG(0, "avma1cs_attach()\n");
 
     /* Initialize the dev_link_t structure */
     link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
     if (!link)
-	return NULL;
+	return -ENOMEM;
     memset(link, 0, sizeof(struct dev_link_t));
 
     /* Allocate space for private device-specific data */
     local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
     if (!local) {
 	kfree(link);
-	return NULL;
+	return -ENOMEM;
     }
     memset(local, 0, sizeof(local_info_t));
     link->priv = local;
@@ -178,20 +158,13 @@ static dev_link_t *avma1cs_attach(void)
     link->conf.ConfigIndex = 1;
     link->conf.Present = PRESENT_OPTION;
 
-    /* Register with Card Services */
-    link->next = dev_list;
-    dev_list = link;
-    client_reg.dev_info = &dev_info;
-    client_reg.Version = 0x0210;
-    client_reg.event_callback_args.client_data = link;
-    ret = pcmcia_register_client(&link->handle, &client_reg);
-    if (ret != 0) {
-	cs_error(link->handle, RegisterClient, ret);
-	avma1cs_detach(link);
-	return NULL;
-    }
+    link->handle = p_dev;
+    p_dev->instance = link;
 
-    return link;
+    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+    avma1cs_config(link);
+
+    return 0;
 } /* avma1cs_attach */
 
 /*======================================================================
@@ -203,42 +176,17 @@ static dev_link_t *avma1cs_attach(void)
 
 ======================================================================*/
 
-static void avma1cs_detach(dev_link_t *link)
+static void avma1cs_detach(struct pcmcia_device *p_dev)
 {
-    dev_link_t **linkp;
+    dev_link_t *link = dev_to_instance(p_dev);
 
     DEBUG(0, "avma1cs_detach(0x%p)\n", link);
-    
-    /* Locate device structure */
-    for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
-	if (*linkp == link) break;
-    if (*linkp == NULL)
-	return;
 
-    /*
-       If the device is currently configured and active, we won't
-       actually delete it yet.  Instead, it is marked so that when
-       the release() function is called, that will trigger a proper
-       detach().
-    */
-    if (link->state & DEV_CONFIG) {
-#ifdef PCMCIA_DEBUG
-	printk(KERN_DEBUG "avma1_cs: detach postponed, '%s' "
-	       "still locked\n", link->dev->dev_name);
-#endif
-	link->state |= DEV_STALE_LINK;
-	return;
-    }
+    if (link->state & DEV_CONFIG)
+	    avma1cs_release(link);
 
-    /* Break the link with Card Services */
-    if (link->handle)
-    	pcmcia_deregister_client(link->handle);
-    
-    /* Unlink device structure, free pieces */
-    *linkp = link->next;
     kfree(link->priv);
     kfree(link);
-    
 } /* avma1cs_detach */
 
 /*======================================================================
@@ -440,58 +388,30 @@ static void avma1cs_release(dev_link_t *link)
     pcmcia_release_io(link->handle, &link->io);
     pcmcia_release_irq(link->handle, &link->irq);
     link->state &= ~DEV_CONFIG;
-    
-    if (link->state & DEV_STALE_LINK)
-	avma1cs_detach(link);
 } /* avma1cs_release */
 
-/*======================================================================
+static int avma1cs_suspend(struct pcmcia_device *dev)
+{
+	dev_link_t *link = dev_to_instance(dev);
 
-    The card status event handler.  Mostly, this schedules other
-    stuff to run after an event is received.  A CARD_REMOVAL event
-    also sets some flags to discourage the net drivers from trying
-    to talk to the card any more.
+	link->state |= DEV_SUSPEND;
+	if (link->state & DEV_CONFIG)
+		pcmcia_release_configuration(link->handle);
 
-    When a CARD_REMOVAL event is received, we immediately set a flag
-    to block future accesses to this device.  All the functions that
-    actually access the device should check this flag to make sure
-    the card is still present.
-    
-======================================================================*/
+	return 0;
+}
 
-static int avma1cs_event(event_t event, int priority,
-			  event_callback_args_t *args)
+static int avma1cs_resume(struct pcmcia_device *dev)
 {
-    dev_link_t *link = args->client_data;
+	dev_link_t *link = dev_to_instance(dev);
 
-    DEBUG(1, "avma1cs_event(0x%06x)\n", event);
-    
-    switch (event) {
-	case CS_EVENT_CARD_REMOVAL:
-	    if (link->state & DEV_CONFIG)
-		avma1cs_release(link);
-	    break;
-	case CS_EVENT_CARD_INSERTION:
-	    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-	    avma1cs_config(link);
-	    break;
-	case CS_EVENT_PM_SUSPEND:
-	    link->state |= DEV_SUSPEND;
-	    /* Fall through... */
-	case CS_EVENT_RESET_PHYSICAL:
-	    if (link->state & DEV_CONFIG)
-		pcmcia_release_configuration(link->handle);
-	    break;
-	case CS_EVENT_PM_RESUME:
-	    link->state &= ~DEV_SUSPEND;
-	    /* Fall through... */
-	case CS_EVENT_CARD_RESET:
- 	    if (link->state & DEV_CONFIG)
+	link->state &= ~DEV_SUSPEND;
+	if (link->state & DEV_CONFIG)
 		pcmcia_request_configuration(link->handle, &link->conf);
-	    break;
-    }
-    return 0;
-} /* avma1cs_event */
+
+	return 0;
+}
+
 
 static struct pcmcia_device_id avma1cs_ids[] = {
 	PCMCIA_DEVICE_PROD_ID12("AVM", "ISDN A", 0x95d42008, 0xadc9d4bb),
@@ -505,10 +425,11 @@ static struct pcmcia_driver avma1cs_driver = {
 	.drv		= {
 		.name	= "avma1_cs",
 	},
-	.attach		= avma1cs_attach,
-	.event		= avma1cs_event,
-	.detach		= avma1cs_detach,
+	.probe		= avma1cs_attach,
+	.remove		= avma1cs_detach,
 	.id_table	= avma1cs_ids,
+	.suspend	= avma1cs_suspend,
+	.resume		= avma1cs_resume,
 };
  
 /*====================================================================*/
@@ -521,7 +442,6 @@ static int __init init_avma1_cs(void)
 static void __exit exit_avma1_cs(void)
 {
 	pcmcia_unregister_driver(&avma1cs_driver);
-	BUG_ON(dev_list != NULL);
 }
 
 module_init(init_avma1_cs);
diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c
index 6fc6868de0b0..062fb8f0739f 100644
--- a/drivers/isdn/hisax/elsa_cs.c
+++ b/drivers/isdn/hisax/elsa_cs.c
@@ -96,8 +96,6 @@ module_param(protocol, int, 0);
 
 static void elsa_cs_config(dev_link_t *link);
 static void elsa_cs_release(dev_link_t *link);
-static int elsa_cs_event(event_t event, int priority,
-                          event_callback_args_t *args);
 
 /*
    The attach() and detach() entry points are used to create and destroy
@@ -105,39 +103,9 @@ static int elsa_cs_event(event_t event, int priority,
    needed to manage one actual PCMCIA card.
 */
 
-static dev_link_t *elsa_cs_attach(void);
-static void elsa_cs_detach(dev_link_t *);
+static void elsa_cs_detach(struct pcmcia_device *p_dev);
 
 /*
-   The dev_info variable is the "key" that is used to match up this
-   device driver with appropriate cards, through the card configuration
-   database.
-*/
-
-static dev_info_t dev_info = "elsa_cs";
-
-/*
-   A linked list of "instances" of the elsa_cs device.  Each actual
-   PCMCIA card corresponds to one device instance, and is described
-   by one dev_link_t structure (defined in ds.h).
-
-   You may not want to use a linked list for this -- for example, the
-   memory card driver uses an array of dev_link_t pointers, where minor
-   device numbers are used to derive the corresponding array index.
-*/
-
-static dev_link_t *dev_list = NULL;
-
-/*
-   A dev_link_t structure has fields for most things that are needed
-   to keep track of a socket, but there will usually be some device
-   specific information that also needs to be kept track of.  The
-   'priv' pointer in a dev_link_t structure can be used to point to
-   a device-specific private data structure, like this.
-
-   To simplify the data structure handling, we actually include the
-   dev_link_t structure in the device's private data structure.
-
    A driver needs to provide a dev_node_t structure for each device
    on a card.  In some cases, there is only one device per card (for
    example, ethernet cards, modems).  In other cases, there may be
@@ -171,18 +139,16 @@ typedef struct local_info_t {
 
 ======================================================================*/
 
-static dev_link_t *elsa_cs_attach(void)
+static int elsa_cs_attach(struct pcmcia_device *p_dev)
 {
-    client_reg_t client_reg;
     dev_link_t *link;
     local_info_t *local;
-    int ret;
 
     DEBUG(0, "elsa_cs_attach()\n");
 
     /* Allocate space for private device-specific data */
     local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
-    if (!local) return NULL;
+    if (!local) return -ENOMEM;
     memset(local, 0, sizeof(local_info_t));
     local->cardnr = -1;
     link = &local->link; link->priv = local;
@@ -207,20 +173,13 @@ static dev_link_t *elsa_cs_attach(void)
     link->conf.Vcc = 50;
     link->conf.IntType = INT_MEMORY_AND_IO;
 
-    /* Register with Card Services */
-    link->next = dev_list;
-    dev_list = link;
-    client_reg.dev_info = &dev_info;
-    client_reg.Version = 0x0210;
-    client_reg.event_callback_args.client_data = link;
-    ret = pcmcia_register_client(&link->handle, &client_reg);
-    if (ret != CS_SUCCESS) {
-        cs_error(link->handle, RegisterClient, ret);
-        elsa_cs_detach(link);
-        return NULL;
-    }
+    link->handle = p_dev;
+    p_dev->instance = link;
 
-    return link;
+    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+    elsa_cs_config(link);
+
+    return 0;
 } /* elsa_cs_attach */
 
 /*======================================================================
@@ -232,32 +191,18 @@ static dev_link_t *elsa_cs_attach(void)
 
 ======================================================================*/
 
-static void elsa_cs_detach(dev_link_t *link)
+static void elsa_cs_detach(struct pcmcia_device *p_dev)
 {
-    dev_link_t **linkp;
+    dev_link_t *link = dev_to_instance(p_dev);
     local_info_t *info = link->priv;
-    int ret;
 
     DEBUG(0, "elsa_cs_detach(0x%p)\n", link);
 
-    /* Locate device structure */
-    for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
-        if (*linkp == link) break;
-    if (*linkp == NULL)
-        return;
-
-    if (link->state & DEV_CONFIG)
-        elsa_cs_release(link);
-
-    /* Break the link with Card Services */
-    if (link->handle) {
-        ret = pcmcia_deregister_client(link->handle);
-	if (ret != CS_SUCCESS)
-	    cs_error(link->handle, DeregisterClient, ret);
+    if (link->state & DEV_CONFIG) {
+	    info->busy = 1;
+	    elsa_cs_release(link);
     }
 
-    /* Unlink device structure and free it */
-    *linkp = link->next;
     kfree(info);
 
 } /* elsa_cs_detach */
@@ -447,60 +392,31 @@ static void elsa_cs_release(dev_link_t *link)
     link->state &= ~DEV_CONFIG;
 } /* elsa_cs_release */
 
-/*======================================================================
-
-    The card status event handler.  Mostly, this schedules other
-    stuff to run after an event is received.  A CARD_REMOVAL event
-    also sets some flags to discourage the net drivers from trying
-    to talk to the card any more.
+static int elsa_suspend(struct pcmcia_device *p_dev)
+{
+	dev_link_t *link = dev_to_instance(p_dev);
+	local_info_t *dev = link->priv;
 
-    When a CARD_REMOVAL event is received, we immediately set a flag
-    to block future accesses to this device.  All the functions that
-    actually access the device should check this flag to make sure
-    the card is still present.
+	link->state |= DEV_SUSPEND;
+        dev->busy = 1;
+	if (link->state & DEV_CONFIG)
+		pcmcia_release_configuration(link->handle);
 
-======================================================================*/
+	return 0;
+}
 
-static int elsa_cs_event(event_t event, int priority,
-                          event_callback_args_t *args)
+static int elsa_resume(struct pcmcia_device *p_dev)
 {
-    dev_link_t *link = args->client_data;
-    local_info_t *dev = link->priv;
-
-    DEBUG(1, "elsa_cs_event(%d)\n", event);
+	dev_link_t *link = dev_to_instance(p_dev);
+	local_info_t *dev = link->priv;
 
-    switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-        link->state &= ~DEV_PRESENT;
-        if (link->state & DEV_CONFIG) {
-            ((local_info_t*)link->priv)->busy = 1;
-	    elsa_cs_release(link);
-        }
-        break;
-    case CS_EVENT_CARD_INSERTION:
-        link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-        elsa_cs_config(link);
-        break;
-    case CS_EVENT_PM_SUSPEND:
-        link->state |= DEV_SUSPEND;
-        /* Fall through... */
-    case CS_EVENT_RESET_PHYSICAL:
-        /* Mark the device as stopped, to block IO until later */
-        dev->busy = 1;
-        if (link->state & DEV_CONFIG)
-            pcmcia_release_configuration(link->handle);
-        break;
-    case CS_EVENT_PM_RESUME:
-        link->state &= ~DEV_SUSPEND;
-        /* Fall through... */
-    case CS_EVENT_CARD_RESET:
-        if (link->state & DEV_CONFIG)
-            pcmcia_request_configuration(link->handle, &link->conf);
+	link->state &= ~DEV_SUSPEND;
+	if (link->state & DEV_CONFIG)
+		pcmcia_request_configuration(link->handle, &link->conf);
         dev->busy = 0;
-        break;
-    }
-    return 0;
-} /* elsa_cs_event */
+
+	return 0;
+}
 
 static struct pcmcia_device_id elsa_ids[] = {
 	PCMCIA_DEVICE_PROD_ID12("ELSA AG (Aachen, Germany)", "MicroLink ISDN/MC ", 0x983de2c4, 0x333ba257),
@@ -514,10 +430,11 @@ static struct pcmcia_driver elsa_cs_driver = {
 	.drv		= {
 		.name	= "elsa_cs",
 	},
-	.attach		= elsa_cs_attach,
-	.event		= elsa_cs_event,
-	.detach		= elsa_cs_detach,
+	.probe		= elsa_cs_attach,
+	.remove		= elsa_cs_detach,
 	.id_table	= elsa_ids,
+	.suspend	= elsa_suspend,
+	.resume		= elsa_resume,
 };
 
 static int __init init_elsa_cs(void)
@@ -528,7 +445,6 @@ static int __init init_elsa_cs(void)
 static void __exit exit_elsa_cs(void)
 {
 	pcmcia_unregister_driver(&elsa_cs_driver);
-	BUG_ON(dev_list != NULL);
 }
 
 module_init(init_elsa_cs);
diff --git a/drivers/isdn/hisax/hfc_usb.c b/drivers/isdn/hisax/hfc_usb.c
index f8457ef48826..ca5b4a3b683e 100644
--- a/drivers/isdn/hisax/hfc_usb.c
+++ b/drivers/isdn/hisax/hfc_usb.c
@@ -1715,7 +1715,6 @@ hfc_usb_disconnect(struct usb_interface
 /* our driver information structure */
 /************************************/
 static struct usb_driver hfc_drv = {
-	.owner = THIS_MODULE,
 	.name  = "hfc_usb",
 	.id_table = hfcusb_idtab,
 	.probe = hfc_usb_probe,
diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c
index dc334aab433e..6f5213a18a8d 100644
--- a/drivers/isdn/hisax/sedlbauer_cs.c
+++ b/drivers/isdn/hisax/sedlbauer_cs.c
@@ -97,8 +97,6 @@ module_param(protocol, int, 0);
 
 static void sedlbauer_config(dev_link_t *link);
 static void sedlbauer_release(dev_link_t *link);
-static int sedlbauer_event(event_t event, int priority,
-		       event_callback_args_t *args);
 
 /*
    The attach() and detach() entry points are used to create and destroy
@@ -106,8 +104,7 @@ static int sedlbauer_event(event_t event, int priority,
    needed to manage one actual PCMCIA card.
 */
 
-static dev_link_t *sedlbauer_attach(void);
-static void sedlbauer_detach(dev_link_t *);
+static void sedlbauer_detach(struct pcmcia_device *p_dev);
 
 /*
    You'll also need to prototype all the functions that will actually
@@ -117,35 +114,6 @@ static void sedlbauer_detach(dev_link_t *);
 */
 
 /*
-   The dev_info variable is the "key" that is used to match up this
-   device driver with appropriate cards, through the card configuration
-   database.
-*/
-
-static dev_info_t dev_info = "sedlbauer_cs";
-
-/*
-   A linked list of "instances" of the sedlbauer device.  Each actual
-   PCMCIA card corresponds to one device instance, and is described
-   by one dev_link_t structure (defined in ds.h).
-
-   You may not want to use a linked list for this -- for example, the
-   memory card driver uses an array of dev_link_t pointers, where minor
-   device numbers are used to derive the corresponding array index.
-*/
-
-static dev_link_t *dev_list = NULL;
-
-/*
-   A dev_link_t structure has fields for most things that are needed
-   to keep track of a socket, but there will usually be some device
-   specific information that also needs to be kept track of.  The
-   'priv' pointer in a dev_link_t structure can be used to point to
-   a device-specific private data structure, like this.
-
-   To simplify the data structure handling, we actually include the
-   dev_link_t structure in the device's private data structure.
-
    A driver needs to provide a dev_node_t structure for each device
    on a card.  In some cases, there is only one device per card (for
    example, ethernet cards, modems).  In other cases, there may be
@@ -180,18 +148,16 @@ typedef struct local_info_t {
     
 ======================================================================*/
 
-static dev_link_t *sedlbauer_attach(void)
+static int sedlbauer_attach(struct pcmcia_device *p_dev)
 {
     local_info_t *local;
     dev_link_t *link;
-    client_reg_t client_reg;
-    int ret;
     
     DEBUG(0, "sedlbauer_attach()\n");
 
     /* Allocate space for private device-specific data */
     local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
-    if (!local) return NULL;
+    if (!local) return -ENOMEM;
     memset(local, 0, sizeof(local_info_t));
     local->cardnr = -1;
     link = &local->link; link->priv = local;
@@ -221,20 +187,13 @@ static dev_link_t *sedlbauer_attach(void)
     link->conf.Vcc = 50;
     link->conf.IntType = INT_MEMORY_AND_IO;
 
-    /* Register with Card Services */
-    link->next = dev_list;
-    dev_list = link;
-    client_reg.dev_info = &dev_info;
-    client_reg.Version = 0x0210;
-    client_reg.event_callback_args.client_data = link;
-    ret = pcmcia_register_client(&link->handle, &client_reg);
-    if (ret != CS_SUCCESS) {
-	cs_error(link->handle, RegisterClient, ret);
-	sedlbauer_detach(link);
-	return NULL;
-    }
+    link->handle = p_dev;
+    p_dev->instance = link;
+
+    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+    sedlbauer_config(link);
 
-    return link;
+    return 0;
 } /* sedlbauer_attach */
 
 /*======================================================================
@@ -246,39 +205,17 @@ static dev_link_t *sedlbauer_attach(void)
 
 ======================================================================*/
 
-static void sedlbauer_detach(dev_link_t *link)
+static void sedlbauer_detach(struct pcmcia_device *p_dev)
 {
-    dev_link_t **linkp;
+    dev_link_t *link = dev_to_instance(p_dev);
 
     DEBUG(0, "sedlbauer_detach(0x%p)\n", link);
-    
-    /* Locate device structure */
-    for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
-	if (*linkp == link) break;
-    if (*linkp == NULL)
-	return;
 
-    /*
-       If the device is currently configured and active, we won't
-       actually delete it yet.  Instead, it is marked so that when
-       the release() function is called, that will trigger a proper
-       detach().
-    */
     if (link->state & DEV_CONFIG) {
-#ifdef PCMCIA_DEBUG
-	printk(KERN_DEBUG "sedlbauer_cs: detach postponed, '%s' "
-	       "still locked\n", link->dev->dev_name);
-#endif
-	link->state |= DEV_STALE_LINK;
-	return;
+	    ((local_info_t *)link->priv)->stop = 1;
+	    sedlbauer_release(link);
     }
 
-    /* Break the link with Card Services */
-    if (link->handle)
-	pcmcia_deregister_client(link->handle);
-    
-    /* Unlink device structure, and free it */
-    *linkp = link->next;
     /* This points to the parent local_info_t struct */
     kfree(link->priv);
 } /* sedlbauer_detach */
@@ -547,68 +484,34 @@ static void sedlbauer_release(dev_link_t *link)
     if (link->irq.AssignedIRQ)
 	pcmcia_release_irq(link->handle, &link->irq);
     link->state &= ~DEV_CONFIG;
-    
-    if (link->state & DEV_STALE_LINK)
-	sedlbauer_detach(link);
-    
 } /* sedlbauer_release */
 
-/*======================================================================
-
-    The card status event handler.  Mostly, this schedules other
-    stuff to run after an event is received.
-
-    When a CARD_REMOVAL event is received, we immediately set a
-    private flag to block future accesses to this device.  All the
-    functions that actually access the device should check this flag
-    to make sure the card is still present.
-    
-======================================================================*/
-
-static int sedlbauer_event(event_t event, int priority,
-		       event_callback_args_t *args)
+static int sedlbauer_suspend(struct pcmcia_device *p_dev)
 {
-    dev_link_t *link = args->client_data;
-    local_info_t *dev = link->priv;
-    
-    DEBUG(1, "sedlbauer_event(0x%06x)\n", event);
-    
-    switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-	link->state &= ~DEV_PRESENT;
-	if (link->state & DEV_CONFIG) {
-	    ((local_info_t *)link->priv)->stop = 1;
-	    sedlbauer_release(link);
-	}
-	break;
-    case CS_EVENT_CARD_INSERTION:
-	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-	sedlbauer_config(link);
-	break;
-    case CS_EVENT_PM_SUSPEND:
+	dev_link_t *link = dev_to_instance(p_dev);
+	local_info_t *dev = link->priv;
+
 	link->state |= DEV_SUSPEND;
-	/* Fall through... */
-    case CS_EVENT_RESET_PHYSICAL:
-	/* Mark the device as stopped, to block IO until later */
 	dev->stop = 1;
 	if (link->state & DEV_CONFIG)
-	    pcmcia_release_configuration(link->handle);
-	break;
-    case CS_EVENT_PM_RESUME:
+		pcmcia_release_configuration(link->handle);
+
+	return 0;
+}
+
+static int sedlbauer_resume(struct pcmcia_device *p_dev)
+{
+	dev_link_t *link = dev_to_instance(p_dev);
+	local_info_t *dev = link->priv;
+
 	link->state &= ~DEV_SUSPEND;
-	/* Fall through... */
-    case CS_EVENT_CARD_RESET:
 	if (link->state & DEV_CONFIG)
-	    pcmcia_request_configuration(link->handle, &link->conf);
+		pcmcia_request_configuration(link->handle, &link->conf);
 	dev->stop = 0;
-	/*
-	  In a normal driver, additional code may go here to restore
-	  the device state and restart IO. 
-	*/
-	break;
-    }
-    return 0;
-} /* sedlbauer_event */
+
+	return 0;
+}
+
 
 static struct pcmcia_device_id sedlbauer_ids[] = {
 	PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "speed star II", "V 3.1", 0x81fb79f5, 0xf3612e1d, 0x6b95c78a),
@@ -627,10 +530,11 @@ static struct pcmcia_driver sedlbauer_driver = {
 	.drv		= {
 		.name	= "sedlbauer_cs",
 	},
-	.attach		= sedlbauer_attach,
-	.event		= sedlbauer_event,
-	.detach		= sedlbauer_detach,
+	.probe		= sedlbauer_attach,
+	.remove		= sedlbauer_detach,
 	.id_table	= sedlbauer_ids,
+	.suspend	= sedlbauer_suspend,
+	.resume		= sedlbauer_resume,
 };
 
 static int __init init_sedlbauer_cs(void)
@@ -641,7 +545,6 @@ static int __init init_sedlbauer_cs(void)
 static void __exit exit_sedlbauer_cs(void)
 {
 	pcmcia_unregister_driver(&sedlbauer_driver);
-	BUG_ON(dev_list != NULL);
 }
 
 module_init(init_sedlbauer_cs);
diff --git a/drivers/isdn/hisax/st5481_init.c b/drivers/isdn/hisax/st5481_init.c
index 8e192a3a3490..99cb0f3d59a1 100644
--- a/drivers/isdn/hisax/st5481_init.c
+++ b/drivers/isdn/hisax/st5481_init.c
@@ -180,7 +180,6 @@ static struct usb_device_id st5481_ids[] = {
 MODULE_DEVICE_TABLE (usb, st5481_ids);
 
 static struct usb_driver st5481_usb_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"st5481_usb",
 	.probe =	probe_st5481,
 	.disconnect =	disconnect_st5481,
diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c
index 0ddef1bf778b..4e5c14c7240e 100644
--- a/drivers/isdn/hisax/teles_cs.c
+++ b/drivers/isdn/hisax/teles_cs.c
@@ -77,8 +77,6 @@ module_param(protocol, int, 0);
 
 static void teles_cs_config(dev_link_t *link);
 static void teles_cs_release(dev_link_t *link);
-static int teles_cs_event(event_t event, int priority,
-                          event_callback_args_t *args);
 
 /*
    The attach() and detach() entry points are used to create and destroy
@@ -86,16 +84,7 @@ static int teles_cs_event(event_t event, int priority,
    needed to manage one actual PCMCIA card.
 */
 
-static dev_link_t *teles_attach(void);
-static void teles_detach(dev_link_t *);
-
-/*
-   The dev_info variable is the "key" that is used to match up this
-   device driver with appropriate cards, through the card configuration
-   database.
-*/
-
-static dev_info_t dev_info = "teles_cs";
+static void teles_detach(struct pcmcia_device *p_dev);
 
 /*
    A linked list of "instances" of the teles_cs device.  Each actual
@@ -107,18 +96,7 @@ static dev_info_t dev_info = "teles_cs";
    device numbers are used to derive the corresponding array index.
 */
 
-static dev_link_t *dev_list = NULL;
-
 /*
-   A dev_link_t structure has fields for most things that are needed
-   to keep track of a socket, but there will usually be some device
-   specific information that also needs to be kept track of.  The
-   'priv' pointer in a dev_link_t structure can be used to point to
-   a device-specific private data structure, like this.
-
-   To simplify the data structure handling, we actually include the
-   dev_link_t structure in the device's private data structure.
-
    A driver needs to provide a dev_node_t structure for each device
    on a card.  In some cases, there is only one device per card (for
    example, ethernet cards, modems).  In other cases, there may be
@@ -152,18 +130,16 @@ typedef struct local_info_t {
 
 ======================================================================*/
 
-static dev_link_t *teles_attach(void)
+static int teles_attach(struct pcmcia_device *p_dev)
 {
-    client_reg_t client_reg;
     dev_link_t *link;
     local_info_t *local;
-    int ret;
 
     DEBUG(0, "teles_attach()\n");
 
     /* Allocate space for private device-specific data */
     local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
-    if (!local) return NULL;
+    if (!local) return -ENOMEM;
     memset(local, 0, sizeof(local_info_t));
     local->cardnr = -1;
     link = &local->link; link->priv = local;
@@ -188,20 +164,13 @@ static dev_link_t *teles_attach(void)
     link->conf.Vcc = 50;
     link->conf.IntType = INT_MEMORY_AND_IO;
 
-    /* Register with Card Services */
-    link->next = dev_list;
-    dev_list = link;
-    client_reg.dev_info = &dev_info;
-    client_reg.Version = 0x0210;
-    client_reg.event_callback_args.client_data = link;
-    ret = pcmcia_register_client(&link->handle, &client_reg);
-    if (ret != CS_SUCCESS) {
-        cs_error(link->handle, RegisterClient, ret);
-        teles_detach(link);
-        return NULL;
-    }
+    link->handle = p_dev;
+    p_dev->instance = link;
+
+    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+    teles_cs_config(link);
 
-    return link;
+    return 0;
 } /* teles_attach */
 
 /*======================================================================
@@ -213,32 +182,18 @@ static dev_link_t *teles_attach(void)
 
 ======================================================================*/
 
-static void teles_detach(dev_link_t *link)
+static void teles_detach(struct pcmcia_device *p_dev)
 {
-    dev_link_t **linkp;
+    dev_link_t *link = dev_to_instance(p_dev);
     local_info_t *info = link->priv;
-    int ret;
 
     DEBUG(0, "teles_detach(0x%p)\n", link);
 
-    /* Locate device structure */
-    for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
-        if (*linkp == link) break;
-    if (*linkp == NULL)
-        return;
-
-    if (link->state & DEV_CONFIG)
-        teles_cs_release(link);
-
-    /* Break the link with Card Services */
-    if (link->handle) {
-        ret = pcmcia_deregister_client(link->handle);
-	if (ret != CS_SUCCESS)
-	    cs_error(link->handle, DeregisterClient, ret);
+    if (link->state & DEV_CONFIG) {
+	    info->busy = 1;
+	    teles_cs_release(link);
     }
 
-    /* Unlink device structure and free it */
-    *linkp = link->next;
     kfree(info);
 
 } /* teles_detach */
@@ -428,60 +383,32 @@ static void teles_cs_release(dev_link_t *link)
     link->state &= ~DEV_CONFIG;
 } /* teles_cs_release */
 
-/*======================================================================
-
-    The card status event handler.  Mostly, this schedules other
-    stuff to run after an event is received.  A CARD_REMOVAL event
-    also sets some flags to discourage the net drivers from trying
-    to talk to the card any more.
+static int teles_suspend(struct pcmcia_device *p_dev)
+{
+	dev_link_t *link = dev_to_instance(p_dev);
+	local_info_t *dev = link->priv;
 
-    When a CARD_REMOVAL event is received, we immediately set a flag
-    to block future accesses to this device.  All the functions that
-    actually access the device should check this flag to make sure
-    the card is still present.
+	link->state |= DEV_SUSPEND;
+        dev->busy = 1;
+	if (link->state & DEV_CONFIG)
+		pcmcia_release_configuration(link->handle);
 
-======================================================================*/
+	return 0;
+}
 
-static int teles_cs_event(event_t event, int priority,
-                          event_callback_args_t *args)
+static int teles_resume(struct pcmcia_device *p_dev)
 {
-    dev_link_t *link = args->client_data;
-    local_info_t *dev = link->priv;
-
-    DEBUG(1, "teles_cs_event(%d)\n", event);
+	dev_link_t *link = dev_to_instance(p_dev);
+	local_info_t *dev = link->priv;
 
-    switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-        link->state &= ~DEV_PRESENT;
-        if (link->state & DEV_CONFIG) {
-            ((local_info_t*)link->priv)->busy = 1;
-	    teles_cs_release(link);
-        }
-        break;
-    case CS_EVENT_CARD_INSERTION:
-        link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-        teles_cs_config(link);
-        break;
-    case CS_EVENT_PM_SUSPEND:
-        link->state |= DEV_SUSPEND;
-        /* Fall through... */
-    case CS_EVENT_RESET_PHYSICAL:
-        /* Mark the device as stopped, to block IO until later */
-        dev->busy = 1;
-        if (link->state & DEV_CONFIG)
-            pcmcia_release_configuration(link->handle);
-        break;
-    case CS_EVENT_PM_RESUME:
-        link->state &= ~DEV_SUSPEND;
-        /* Fall through... */
-    case CS_EVENT_CARD_RESET:
-        if (link->state & DEV_CONFIG)
-            pcmcia_request_configuration(link->handle, &link->conf);
+	link->state &= ~DEV_SUSPEND;
+	if (link->state & DEV_CONFIG)
+		pcmcia_request_configuration(link->handle, &link->conf);
         dev->busy = 0;
-        break;
-    }
-    return 0;
-} /* teles_cs_event */
+
+	return 0;
+}
+
 
 static struct pcmcia_device_id teles_ids[] = {
 	PCMCIA_DEVICE_PROD_ID12("TELES", "S0/PC", 0x67b50eae, 0xe9e70119),
@@ -494,10 +421,11 @@ static struct pcmcia_driver teles_cs_driver = {
 	.drv		= {
 		.name	= "teles_cs",
 	},
-	.attach		= teles_attach,
-	.event		= teles_cs_event,
-	.detach		= teles_detach,
+	.probe		= teles_attach,
+	.remove		= teles_detach,
 	.id_table       = teles_ids,
+	.suspend	= teles_suspend,
+	.resume		= teles_resume,
 };
 
 static int __init init_teles_cs(void)
@@ -508,7 +436,6 @@ static int __init init_teles_cs(void)
 static void __exit exit_teles_cs(void)
 {
 	pcmcia_unregister_driver(&teles_cs_driver);
-	BUG_ON(dev_list != NULL);
 }
 
 module_init(init_teles_cs);
diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c
index c34c96d18907..228e1852a836 100644
--- a/drivers/macintosh/macio_asic.c
+++ b/drivers/macintosh/macio_asic.c
@@ -128,7 +128,7 @@ static int macio_device_resume(struct device * dev)
 	return 0;
 }
 
-static int macio_hotplug (struct device *dev, char **envp, int num_envp,
+static int macio_uevent(struct device *dev, char **envp, int num_envp,
                           char *buffer, int buffer_size)
 {
 	struct macio_dev * macio_dev;
@@ -203,7 +203,7 @@ extern struct device_attribute macio_dev_attrs[];
 struct bus_type macio_bus_type = {
        .name	= "macio",
        .match	= macio_bus_match,
-       .hotplug = macio_hotplug,
+       .uevent = macio_uevent,
        .suspend	= macio_device_suspend,
        .resume	= macio_device_resume,
        .dev_attrs = macio_dev_attrs,
diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c
index f38696622eb4..5ebfd1d138da 100644
--- a/drivers/macintosh/therm_adt746x.c
+++ b/drivers/macintosh/therm_adt746x.c
@@ -52,6 +52,7 @@ static char *sensor_location[3] = {NULL, NULL, NULL};
 
 static int limit_adjust = 0;
 static int fan_speed = -1;
+static int verbose = 0;
 
 MODULE_AUTHOR("Colin Leroy <colin@colino.net>");
 MODULE_DESCRIPTION("Driver for ADT746x thermostat in iBook G4 and "
@@ -66,6 +67,10 @@ module_param(fan_speed, int, 0644);
 MODULE_PARM_DESC(fan_speed,"Specify starting fan speed (0-255) "
 		 "(default 64)");
 
+module_param(verbose, bool, 0);
+MODULE_PARM_DESC(verbose,"Verbose log operations "
+		 "(default 0)");
+
 struct thermostat {
 	struct i2c_client	clt;
 	u8			temps[3];
@@ -149,13 +154,13 @@ detach_thermostat(struct i2c_adapter *adapter)
 	if (thread_therm != NULL) {
 		kthread_stop(thread_therm);
 	}
-		
+
 	printk(KERN_INFO "adt746x: Putting max temperatures back from "
 			 "%d, %d, %d to %d, %d, %d\n",
 		th->limits[0], th->limits[1], th->limits[2],
 		th->initial_limits[0], th->initial_limits[1],
 		th->initial_limits[2]);
-	
+
 	for (i = 0; i < 3; i++)
 		write_reg(th, LIMIT_REG[i], th->initial_limits[i]);
 
@@ -171,9 +176,9 @@ detach_thermostat(struct i2c_adapter *adapter)
 }
 
 static struct i2c_driver thermostat_driver = {  
-	.owner		= THIS_MODULE,
-	.name		= "therm_adt746x",
-	.flags		= I2C_DF_NOTIFY,
+	.driver = {
+		.name	= "therm_adt746x",
+	},
 	.attach_adapter	= attach_thermostat,
 	.detach_adapter	= detach_thermostat,
 };
@@ -212,12 +217,14 @@ static void write_fan_speed(struct thermostat *th, int speed, int fan)
 		return;
 	
 	if (th->last_speed[fan] != speed) {
-		if (speed == -1)
-			printk(KERN_DEBUG "adt746x: Setting speed to automatic "
-				"for %s fan.\n", sensor_location[fan+1]);
-		else
-			printk(KERN_DEBUG "adt746x: Setting speed to %d "
-				"for %s fan.\n", speed, sensor_location[fan+1]);
+		if (verbose) {
+			if (speed == -1)
+				printk(KERN_DEBUG "adt746x: Setting speed to automatic "
+					"for %s fan.\n", sensor_location[fan+1]);
+			else
+				printk(KERN_DEBUG "adt746x: Setting speed to %d "
+					"for %s fan.\n", speed, sensor_location[fan+1]);
+		}
 	} else
 		return;
 	
@@ -298,10 +305,11 @@ static void update_fans_speed (struct thermostat *th)
 			if (new_speed > 255)
 				new_speed = 255;
 
-			printk(KERN_DEBUG "adt746x: setting fans speed to %d "
-					 "(limit exceeded by %d on %s) \n",
-					new_speed, var,
-					sensor_location[fan_number+1]);
+			if (verbose)
+				printk(KERN_DEBUG "adt746x: Setting fans speed to %d "
+						 "(limit exceeded by %d on %s) \n",
+						new_speed, var,
+						sensor_location[fan_number+1]);
 			write_both_fan_speed(th, new_speed);
 			th->last_var[fan_number] = var;
 		} else if (var < -2) {
@@ -309,8 +317,9 @@ static void update_fans_speed (struct thermostat *th)
 			 * so cold (lastvar >= -1) */
 			if (i == 2 && lastvar < -1) {
 				if (th->last_speed[fan_number] != 0)
-					printk(KERN_DEBUG "adt746x: Stopping "
-						"fans.\n");
+					if (verbose)
+						printk(KERN_DEBUG "adt746x: Stopping "
+							"fans.\n");
 				write_both_fan_speed(th, 0);
 			}
 		}
@@ -406,7 +415,7 @@ static int attach_one_thermostat(struct i2c_adapter *adapter, int addr,
 		th->initial_limits[i] = read_reg(th, LIMIT_REG[i]);
 		set_limit(th, i);
 	}
-	
+
 	printk(KERN_INFO "adt746x: Lowering max temperatures from %d, %d, %d"
 			 " to %d, %d, %d\n",
 			 th->initial_limits[0], th->initial_limits[1],
diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c
index 190878eef990..8d0958c38b6b 100644
--- a/drivers/macintosh/therm_pm72.c
+++ b/drivers/macintosh/therm_pm72.c
@@ -283,9 +283,9 @@ static int therm_pm72_detach(struct i2c_adapter *adapter);
 
 static struct i2c_driver therm_pm72_driver =
 {
-	.owner		= THIS_MODULE,
-	.name		= "therm_pm72",
-	.flags		= I2C_DF_NOTIFY,
+	.driver = {
+		.name	= "therm_pm72",
+	},
 	.attach_adapter	= therm_pm72_attach,
 	.detach_adapter	= therm_pm72_detach,
 };
@@ -1988,18 +1988,13 @@ static void fcu_lookup_fans(struct device_node *fcu_node)
 
 static int fcu_of_probe(struct of_device* dev, const struct of_device_id *match)
 {
-	int rc;
-
 	state = state_detached;
 
 	/* Lookup the fans in the device tree */
 	fcu_lookup_fans(dev->node);
 
 	/* Add the driver */
-	rc = i2c_add_driver(&therm_pm72_driver);
-	if (rc < 0)
-		return rc;
-	return 0;
+	return i2c_add_driver(&therm_pm72_driver);
 }
 
 static int fcu_of_remove(struct of_device* dev)
diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c
index 6aaa1df1a64e..3d9dd2e166aa 100644
--- a/drivers/macintosh/therm_windtunnel.c
+++ b/drivers/macintosh/therm_windtunnel.c
@@ -354,10 +354,10 @@ do_detach( struct i2c_client *client )
 }
 
 static struct i2c_driver g4fan_driver = {  
-	.owner		= THIS_MODULE,
-	.name		= "therm_windtunnel",
+	.driver = {
+		.name	= "therm_windtunnel",
+	},
 	.id		= I2C_DRIVERID_G4FAN,
-	.flags		= I2C_DF_NOTIFY,
 	.attach_adapter = do_attach,
 	.detach_client	= do_detach,
 };
diff --git a/drivers/macintosh/windfarm_lm75_sensor.c b/drivers/macintosh/windfarm_lm75_sensor.c
index a0a41ad0f2b5..57460e46c89f 100644
--- a/drivers/macintosh/windfarm_lm75_sensor.c
+++ b/drivers/macintosh/windfarm_lm75_sensor.c
@@ -47,9 +47,9 @@ static int wf_lm75_attach(struct i2c_adapter *adapter);
 static int wf_lm75_detach(struct i2c_client *client);
 
 static struct i2c_driver wf_lm75_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "wf_lm75",
-	.flags		= I2C_DF_NOTIFY,
+	.driver = {
+		.name	= "wf_lm75",
+	},
 	.attach_adapter	= wf_lm75_attach,
 	.detach_client	= wf_lm75_detach,
 };
@@ -240,12 +240,7 @@ static int wf_lm75_detach(struct i2c_client *client)
 
 static int __init wf_lm75_sensor_init(void)
 {
-	int rc;
-
-	rc = i2c_add_driver(&wf_lm75_driver);
-	if (rc < 0)
-		return rc;
-	return 0;
+	return i2c_add_driver(&wf_lm75_driver);
 }
 
 static void __exit wf_lm75_sensor_exit(void)
diff --git a/drivers/md/.gitignore b/drivers/md/.gitignore
new file mode 100644
index 000000000000..a7afec6b19c6
--- /dev/null
+++ b/drivers/md/.gitignore
@@ -0,0 +1,4 @@
+mktables
+raid6altivec*.c
+raid6int*.c
+raid6tables.c
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index 252d55df9642..76a189ceb529 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -315,6 +315,8 @@ static int write_page(struct bitmap *bitmap, struct page *page, int wait)
 	if (bitmap->file == NULL)
 		return write_sb_page(bitmap->mddev, bitmap->offset, page, wait);
 
+	flush_dcache_page(page); /* make sure visible to anyone reading the file */
+
 	if (wait)
 		lock_page(page);
 	else {
@@ -341,7 +343,7 @@ static int write_page(struct bitmap *bitmap, struct page *page, int wait)
 		/* add to list to be waited for by daemon */
 		struct page_list *item = mempool_alloc(bitmap->write_pool, GFP_NOIO);
 		item->page = page;
-		page_cache_get(page);
+		get_page(page);
 		spin_lock(&bitmap->write_lock);
 		list_add(&item->list, &bitmap->complete_pages);
 		spin_unlock(&bitmap->write_lock);
@@ -357,10 +359,10 @@ static struct page *read_page(struct file *file, unsigned long index,
 	struct inode *inode = file->f_mapping->host;
 	struct page *page = NULL;
 	loff_t isize = i_size_read(inode);
-	unsigned long end_index = isize >> PAGE_CACHE_SHIFT;
+	unsigned long end_index = isize >> PAGE_SHIFT;
 
-	PRINTK("read bitmap file (%dB @ %Lu)\n", (int)PAGE_CACHE_SIZE,
-			(unsigned long long)index << PAGE_CACHE_SHIFT);
+	PRINTK("read bitmap file (%dB @ %Lu)\n", (int)PAGE_SIZE,
+			(unsigned long long)index << PAGE_SHIFT);
 
 	page = read_cache_page(inode->i_mapping, index,
 			(filler_t *)inode->i_mapping->a_ops->readpage, file);
@@ -368,7 +370,7 @@ static struct page *read_page(struct file *file, unsigned long index,
 		goto out;
 	wait_on_page_locked(page);
 	if (!PageUptodate(page) || PageError(page)) {
-		page_cache_release(page);
+		put_page(page);
 		page = ERR_PTR(-EIO);
 		goto out;
 	}
@@ -376,14 +378,14 @@ static struct page *read_page(struct file *file, unsigned long index,
 	if (index > end_index) /* we have read beyond EOF */
 		*bytes_read = 0;
 	else if (index == end_index) /* possible short read */
-		*bytes_read = isize & ~PAGE_CACHE_MASK;
+		*bytes_read = isize & ~PAGE_MASK;
 	else
-		*bytes_read = PAGE_CACHE_SIZE; /* got a full page */
+		*bytes_read = PAGE_SIZE; /* got a full page */
 out:
 	if (IS_ERR(page))
 		printk(KERN_ALERT "md: bitmap read error: (%dB @ %Lu): %ld\n",
-			(int)PAGE_CACHE_SIZE,
-			(unsigned long long)index << PAGE_CACHE_SHIFT,
+			(int)PAGE_SIZE,
+			(unsigned long long)index << PAGE_SHIFT,
 			PTR_ERR(page));
 	return page;
 }
@@ -406,11 +408,11 @@ int bitmap_update_sb(struct bitmap *bitmap)
 		return 0;
 	}
 	spin_unlock_irqrestore(&bitmap->lock, flags);
-	sb = (bitmap_super_t *)kmap(bitmap->sb_page);
+	sb = (bitmap_super_t *)kmap_atomic(bitmap->sb_page, KM_USER0);
 	sb->events = cpu_to_le64(bitmap->mddev->events);
 	if (!bitmap->mddev->degraded)
 		sb->events_cleared = cpu_to_le64(bitmap->mddev->events);
-	kunmap(bitmap->sb_page);
+	kunmap_atomic(sb, KM_USER0);
 	return write_page(bitmap, bitmap->sb_page, 1);
 }
 
@@ -421,7 +423,7 @@ void bitmap_print_sb(struct bitmap *bitmap)
 
 	if (!bitmap || !bitmap->sb_page)
 		return;
-	sb = (bitmap_super_t *)kmap(bitmap->sb_page);
+	sb = (bitmap_super_t *)kmap_atomic(bitmap->sb_page, KM_USER0);
 	printk(KERN_DEBUG "%s: bitmap file superblock:\n", bmname(bitmap));
 	printk(KERN_DEBUG "         magic: %08x\n", le32_to_cpu(sb->magic));
 	printk(KERN_DEBUG "       version: %d\n", le32_to_cpu(sb->version));
@@ -440,7 +442,7 @@ void bitmap_print_sb(struct bitmap *bitmap)
 	printk(KERN_DEBUG "     sync size: %llu KB\n",
 			(unsigned long long)le64_to_cpu(sb->sync_size)/2);
 	printk(KERN_DEBUG "max write behind: %d\n", le32_to_cpu(sb->write_behind));
-	kunmap(bitmap->sb_page);
+	kunmap_atomic(sb, KM_USER0);
 }
 
 /* read the superblock from the bitmap file and initialize some bitmap fields */
@@ -466,7 +468,7 @@ static int bitmap_read_sb(struct bitmap *bitmap)
 		return err;
 	}
 
-	sb = (bitmap_super_t *)kmap(bitmap->sb_page);
+	sb = (bitmap_super_t *)kmap_atomic(bitmap->sb_page, KM_USER0);
 
 	if (bytes_read < sizeof(*sb)) { /* short read */
 		printk(KERN_INFO "%s: bitmap file superblock truncated\n",
@@ -485,12 +487,12 @@ static int bitmap_read_sb(struct bitmap *bitmap)
 	else if (le32_to_cpu(sb->version) < BITMAP_MAJOR_LO ||
 		 le32_to_cpu(sb->version) > BITMAP_MAJOR_HI)
 		reason = "unrecognized superblock version";
-	else if (chunksize < 512 || chunksize > (1024 * 1024 * 4))
-		reason = "bitmap chunksize out of range (512B - 4MB)";
+	else if (chunksize < PAGE_SIZE)
+		reason = "bitmap chunksize too small";
 	else if ((1 << ffz(~chunksize)) != chunksize)
 		reason = "bitmap chunksize not a power of 2";
-	else if (daemon_sleep < 1 || daemon_sleep > 15)
-		reason = "daemon sleep period out of range (1-15s)";
+	else if (daemon_sleep < 1 || daemon_sleep > MAX_SCHEDULE_TIMEOUT / HZ)
+		reason = "daemon sleep period out of range";
 	else if (write_behind > COUNTER_MAX)
 		reason = "write-behind limit out of range (0 - 16383)";
 	if (reason) {
@@ -535,7 +537,7 @@ success:
 		bitmap->events_cleared = bitmap->mddev->events;
 	err = 0;
 out:
-	kunmap(bitmap->sb_page);
+	kunmap_atomic(sb, KM_USER0);
 	if (err)
 		bitmap_print_sb(bitmap);
 	return err;
@@ -558,9 +560,9 @@ static void bitmap_mask_state(struct bitmap *bitmap, enum bitmap_state bits,
 		spin_unlock_irqrestore(&bitmap->lock, flags);
 		return;
 	}
-	page_cache_get(bitmap->sb_page);
+	get_page(bitmap->sb_page);
 	spin_unlock_irqrestore(&bitmap->lock, flags);
-	sb = (bitmap_super_t *)kmap(bitmap->sb_page);
+	sb = (bitmap_super_t *)kmap_atomic(bitmap->sb_page, KM_USER0);
 	switch (op) {
 		case MASK_SET: sb->state |= bits;
 				break;
@@ -568,8 +570,8 @@ static void bitmap_mask_state(struct bitmap *bitmap, enum bitmap_state bits,
 				break;
 		default: BUG();
 	}
-	kunmap(bitmap->sb_page);
-	page_cache_release(bitmap->sb_page);
+	kunmap_atomic(sb, KM_USER0);
+	put_page(bitmap->sb_page);
 }
 
 /*
@@ -622,12 +624,11 @@ static void bitmap_file_unmap(struct bitmap *bitmap)
 
 	while (pages--)
 		if (map[pages]->index != 0) /* 0 is sb_page, release it below */
-			page_cache_release(map[pages]);
+			put_page(map[pages]);
 	kfree(map);
 	kfree(attr);
 
-	if (sb_page)
-		page_cache_release(sb_page);
+	safe_put_page(sb_page);
 }
 
 static void bitmap_stop_daemon(struct bitmap *bitmap);
@@ -654,7 +655,7 @@ static void drain_write_queues(struct bitmap *bitmap)
 
 	while ((item = dequeue_page(bitmap))) {
 		/* don't bother to wait */
-		page_cache_release(item->page);
+		put_page(item->page);
 		mempool_free(item, bitmap->write_pool);
 	}
 
@@ -763,7 +764,7 @@ static void bitmap_file_set_bit(struct bitmap *bitmap, sector_t block)
 
 	/* make sure the page stays cached until it gets written out */
 	if (! (get_page_attr(bitmap, page) & BITMAP_PAGE_DIRTY))
-		page_cache_get(page);
+		get_page(page);
 
  	/* set the bit */
 	kaddr = kmap_atomic(page, KM_USER0);
@@ -854,6 +855,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
 	unsigned long bytes, offset, dummy;
 	int outofdate;
 	int ret = -ENOSPC;
+	void *paddr;
 
 	chunks = bitmap->chunks;
 	file = bitmap->file;
@@ -887,12 +889,10 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
 	if (!bitmap->filemap)
 		goto out;
 
-	bitmap->filemap_attr = kmalloc(sizeof(long) * num_pages, GFP_KERNEL);
+	bitmap->filemap_attr = kzalloc(sizeof(long) * num_pages, GFP_KERNEL);
 	if (!bitmap->filemap_attr)
 		goto out;
 
-	memset(bitmap->filemap_attr, 0, sizeof(long) * num_pages);
-
 	oldindex = ~0L;
 
 	for (i = 0; i < chunks; i++) {
@@ -901,8 +901,6 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
 		bit = file_page_offset(i);
 		if (index != oldindex) { /* this is a new page, read it in */
 			/* unmap the old page, we're done with it */
-			if (oldpage != NULL)
-				kunmap(oldpage);
 			if (index == 0) {
 				/*
 				 * if we're here then the superblock page
@@ -925,30 +923,32 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
 
 			oldindex = index;
 			oldpage = page;
-			kmap(page);
 
 			if (outofdate) {
 				/*
 				 * if bitmap is out of date, dirty the
 			 	 * whole page and write it out
 				 */
-				memset(page_address(page) + offset, 0xff,
+				paddr = kmap_atomic(page, KM_USER0);
+				memset(paddr + offset, 0xff,
 				       PAGE_SIZE - offset);
+				kunmap_atomic(paddr, KM_USER0);
 				ret = write_page(bitmap, page, 1);
 				if (ret) {
-					kunmap(page);
 					/* release, page not in filemap yet */
-					page_cache_release(page);
+					put_page(page);
 					goto out;
 				}
 			}
 
 			bitmap->filemap[bitmap->file_pages++] = page;
 		}
+		paddr = kmap_atomic(page, KM_USER0);
 		if (bitmap->flags & BITMAP_HOSTENDIAN)
-			b = test_bit(bit, page_address(page));
+			b = test_bit(bit, paddr);
 		else
-			b = ext2_test_bit(bit, page_address(page));
+			b = ext2_test_bit(bit, paddr);
+		kunmap_atomic(paddr, KM_USER0);
 		if (b) {
 			/* if the disk bit is set, set the memory bit */
 			bitmap_set_memory_bits(bitmap, i << CHUNK_BLOCK_SHIFT(bitmap),
@@ -963,9 +963,6 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
 	ret = 0;
 	bitmap_mask_state(bitmap, BITMAP_STALE, MASK_UNSET);
 
-	if (page) /* unmap the last page */
-		kunmap(page);
-
 	if (bit_cnt) { /* Kick recovery if any bits were set */
 		set_bit(MD_RECOVERY_NEEDED, &bitmap->mddev->recovery);
 		md_wakeup_thread(bitmap->mddev->thread);
@@ -1021,6 +1018,7 @@ int bitmap_daemon_work(struct bitmap *bitmap)
 	int err = 0;
 	int blocks;
 	int attr;
+	void *paddr;
 
 	if (bitmap == NULL)
 		return 0;
@@ -1043,7 +1041,7 @@ int bitmap_daemon_work(struct bitmap *bitmap)
 			/* skip this page unless it's marked as needing cleaning */
 			if (!((attr=get_page_attr(bitmap, page)) & BITMAP_PAGE_CLEAN)) {
 				if (attr & BITMAP_PAGE_NEEDWRITE) {
-					page_cache_get(page);
+					get_page(page);
 					clear_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE);
 				}
 				spin_unlock_irqrestore(&bitmap->lock, flags);
@@ -1057,13 +1055,13 @@ int bitmap_daemon_work(struct bitmap *bitmap)
 					default:
 						bitmap_file_kick(bitmap);
 					}
-					page_cache_release(page);
+					put_page(page);
 				}
 				continue;
 			}
 
 			/* grab the new page, sync and release the old */
-			page_cache_get(page);
+			get_page(page);
 			if (lastpage != NULL) {
 				if (get_page_attr(bitmap, lastpage) & BITMAP_PAGE_NEEDWRITE) {
 					clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
@@ -1077,14 +1075,12 @@ int bitmap_daemon_work(struct bitmap *bitmap)
 					set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
 					spin_unlock_irqrestore(&bitmap->lock, flags);
 				}
-				kunmap(lastpage);
-				page_cache_release(lastpage);
+				put_page(lastpage);
 				if (err)
 					bitmap_file_kick(bitmap);
 			} else
 				spin_unlock_irqrestore(&bitmap->lock, flags);
 			lastpage = page;
-			kmap(page);
 /*
 			printk("bitmap clean at page %lu\n", j);
 */
@@ -1107,10 +1103,12 @@ int bitmap_daemon_work(struct bitmap *bitmap)
 						  -1);
 
 				/* clear the bit */
+				paddr = kmap_atomic(page, KM_USER0);
 				if (bitmap->flags & BITMAP_HOSTENDIAN)
-					clear_bit(file_page_offset(j), page_address(page));
+					clear_bit(file_page_offset(j), paddr);
 				else
-					ext2_clear_bit(file_page_offset(j), page_address(page));
+					ext2_clear_bit(file_page_offset(j), paddr);
+				kunmap_atomic(paddr, KM_USER0);
 			}
 		}
 		spin_unlock_irqrestore(&bitmap->lock, flags);
@@ -1118,7 +1116,6 @@ int bitmap_daemon_work(struct bitmap *bitmap)
 
 	/* now sync the final page */
 	if (lastpage != NULL) {
-		kunmap(lastpage);
 		spin_lock_irqsave(&bitmap->lock, flags);
 		if (get_page_attr(bitmap, lastpage) &BITMAP_PAGE_NEEDWRITE) {
 			clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
@@ -1133,7 +1130,7 @@ int bitmap_daemon_work(struct bitmap *bitmap)
 			spin_unlock_irqrestore(&bitmap->lock, flags);
 		}
 
-		page_cache_release(lastpage);
+		put_page(lastpage);
 	}
 
 	return err;
@@ -1184,7 +1181,7 @@ static void bitmap_writeback_daemon(mddev_t *mddev)
 		PRINTK("finished page writeback: %p\n", page);
 
 		err = PageError(page);
-		page_cache_release(page);
+		put_page(page);
 		if (err) {
 			printk(KERN_WARNING "%s: bitmap file writeback "
 			       "failed (page %lu): %d\n",
@@ -1530,6 +1527,8 @@ void bitmap_destroy(mddev_t *mddev)
 		return;
 
 	mddev->bitmap = NULL; /* disconnect from the md device */
+	if (mddev->thread)
+		mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT;
 
 	bitmap_free(bitmap);
 }
@@ -1555,12 +1554,10 @@ int bitmap_create(mddev_t *mddev)
 
 	BUG_ON(file && mddev->bitmap_offset);
 
-	bitmap = kmalloc(sizeof(*bitmap), GFP_KERNEL);
+	bitmap = kzalloc(sizeof(*bitmap), GFP_KERNEL);
 	if (!bitmap)
 		return -ENOMEM;
 
-	memset(bitmap, 0, sizeof(*bitmap));
-
 	spin_lock_init(&bitmap->lock);
 	bitmap->mddev = mddev;
 
@@ -1601,12 +1598,11 @@ int bitmap_create(mddev_t *mddev)
 #ifdef INJECT_FATAL_FAULT_1
 	bitmap->bp = NULL;
 #else
-	bitmap->bp = kmalloc(pages * sizeof(*bitmap->bp), GFP_KERNEL);
+	bitmap->bp = kzalloc(pages * sizeof(*bitmap->bp), GFP_KERNEL);
 #endif
 	err = -ENOMEM;
 	if (!bitmap->bp)
 		goto error;
-	memset(bitmap->bp, 0, pages * sizeof(*bitmap->bp));
 
 	bitmap->flags |= BITMAP_ACTIVE;
 
@@ -1636,6 +1632,8 @@ int bitmap_create(mddev_t *mddev)
 
 	if (IS_ERR(bitmap->writeback_daemon))
 		return PTR_ERR(bitmap->writeback_daemon);
+	mddev->thread->timeout = bitmap->daemon_sleep * HZ;
+
 	return bitmap_update_sb(bitmap);
 
  error:
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index cf6631056683..a601a427885c 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -690,6 +690,8 @@ bad3:
 bad2:
 	crypto_free_tfm(tfm);
 bad1:
+	/* Must zero key material before freeing */
+	memset(cc, 0, sizeof(*cc) + cc->key_size * sizeof(u8));
 	kfree(cc);
 	return -EINVAL;
 }
@@ -706,6 +708,9 @@ static void crypt_dtr(struct dm_target *ti)
 		cc->iv_gen_ops->dtr(cc);
 	crypto_free_tfm(cc->tfm);
 	dm_put_device(ti, cc->dev);
+
+	/* Must zero key material before freeing */
+	memset(cc, 0, sizeof(*cc) + cc->key_size * sizeof(u8));
 	kfree(cc);
 }
 
diff --git a/drivers/md/dm-io.h b/drivers/md/dm-io.h
index 1a77f3265706..f9035bfd1a9f 100644
--- a/drivers/md/dm-io.h
+++ b/drivers/md/dm-io.h
@@ -9,9 +9,6 @@
 
 #include "dm.h"
 
-/* FIXME make this configurable */
-#define DM_MAX_IO_REGIONS 8
-
 struct io_region {
 	struct block_device *bdev;
 	sector_t sector;
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index 07d44e19536e..561bda5011e0 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -270,6 +270,7 @@ static int dm_hash_rename(const char *old, const char *new)
 {
 	char *new_name, *old_name;
 	struct hash_cell *hc;
+	struct dm_table *table;
 
 	/*
 	 * duplicate new.
@@ -317,6 +318,15 @@ static int dm_hash_rename(const char *old, const char *new)
 	/* rename the device node in devfs */
 	register_with_devfs(hc);
 
+	/*
+	 * Wake up any dm event waiters.
+	 */
+	table = dm_get_table(hc->md);
+	if (table) {
+		dm_table_event(table);
+		dm_table_put(table);
+	}
+
 	up_write(&_hash_lock);
 	kfree(old_name);
 	return 0;
@@ -683,14 +693,18 @@ static int dev_rename(struct dm_ioctl *param, size_t param_size)
 static int do_suspend(struct dm_ioctl *param)
 {
 	int r = 0;
+	int do_lockfs = 1;
 	struct mapped_device *md;
 
 	md = find_device(param);
 	if (!md)
 		return -ENXIO;
 
+	if (param->flags & DM_SKIP_LOCKFS_FLAG)
+		do_lockfs = 0;
+
 	if (!dm_suspended(md))
-		r = dm_suspend(md);
+		r = dm_suspend(md, do_lockfs);
 
 	if (!r)
 		r = __dev_status(md, param);
@@ -702,6 +716,7 @@ static int do_suspend(struct dm_ioctl *param)
 static int do_resume(struct dm_ioctl *param)
 {
 	int r = 0;
+	int do_lockfs = 1;
 	struct hash_cell *hc;
 	struct mapped_device *md;
 	struct dm_table *new_map;
@@ -727,8 +742,10 @@ static int do_resume(struct dm_ioctl *param)
 	/* Do we need to load a new map ? */
 	if (new_map) {
 		/* Suspend if it isn't already suspended */
+		if (param->flags & DM_SKIP_LOCKFS_FLAG)
+			do_lockfs = 0;
 		if (!dm_suspended(md))
-			dm_suspend(md);
+			dm_suspend(md, do_lockfs);
 
 		r = dm_swap_table(md, new_map);
 		if (r) {
diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c
index a76349cb10a5..efe4adf78530 100644
--- a/drivers/md/dm-log.c
+++ b/drivers/md/dm-log.c
@@ -573,7 +573,7 @@ static int core_get_resync_work(struct dirty_log *log, region_t *region)
 					     lc->sync_search);
 		lc->sync_search = *region + 1;
 
-		if (*region == lc->region_count)
+		if (*region >= lc->region_count)
 			return 0;
 
 	} while (log_test_bit(lc->recovering_bits, *region));
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index 6b0fc1670929..6cfa8d435d55 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -562,6 +562,8 @@ struct mirror_set {
 	region_t nr_regions;
 	int in_sync;
 
+	struct mirror *default_mirror;	/* Default mirror */
+
 	unsigned int nr_mirrors;
 	struct mirror mirror[0];
 };
@@ -611,7 +613,7 @@ static int recover(struct mirror_set *ms, struct region *reg)
 	unsigned long flags = 0;
 
 	/* fill in the source */
-	m = ms->mirror + DEFAULT_MIRROR;
+	m = ms->default_mirror;
 	from.bdev = m->dev->bdev;
 	from.sector = m->offset + region_to_sector(reg->rh, reg->key);
 	if (reg->key == (ms->nr_regions - 1)) {
@@ -627,7 +629,7 @@ static int recover(struct mirror_set *ms, struct region *reg)
 
 	/* fill in the destinations */
 	for (i = 0, dest = to; i < ms->nr_mirrors; i++) {
-		if (i == DEFAULT_MIRROR)
+		if (&ms->mirror[i] == ms->default_mirror)
 			continue;
 
 		m = ms->mirror + i;
@@ -682,7 +684,7 @@ static void do_recovery(struct mirror_set *ms)
 static struct mirror *choose_mirror(struct mirror_set *ms, sector_t sector)
 {
 	/* FIXME: add read balancing */
-	return ms->mirror + DEFAULT_MIRROR;
+	return ms->default_mirror;
 }
 
 /*
@@ -709,7 +711,7 @@ static void do_reads(struct mirror_set *ms, struct bio_list *reads)
 		if (rh_in_sync(&ms->rh, region, 0))
 			m = choose_mirror(ms, bio->bi_sector);
 		else
-			m = ms->mirror + DEFAULT_MIRROR;
+			m = ms->default_mirror;
 
 		map_bio(ms, m, bio);
 		generic_make_request(bio);
@@ -833,7 +835,7 @@ static void do_writes(struct mirror_set *ms, struct bio_list *writes)
 		rh_delay(&ms->rh, bio);
 
 	while ((bio = bio_list_pop(&nosync))) {
-		map_bio(ms, ms->mirror + DEFAULT_MIRROR, bio);
+		map_bio(ms, ms->default_mirror, bio);
 		generic_make_request(bio);
 	}
 }
@@ -900,6 +902,7 @@ static struct mirror_set *alloc_context(unsigned int nr_mirrors,
 	ms->nr_mirrors = nr_mirrors;
 	ms->nr_regions = dm_sector_div_up(ti->len, region_size);
 	ms->in_sync = 0;
+	ms->default_mirror = &ms->mirror[DEFAULT_MIRROR];
 
 	if (rh_init(&ms->rh, ms, dl, region_size, ms->nr_regions)) {
 		ti->error = "dm-mirror: Error creating dirty region hash";
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index ab54f99b7c3b..4b9dd8fb1e5c 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -371,6 +371,20 @@ static inline ulong round_up(ulong n, ulong size)
 	return (n + size) & ~size;
 }
 
+static void read_snapshot_metadata(struct dm_snapshot *s)
+{
+	if (s->have_metadata)
+		return;
+
+	if (s->store.read_metadata(&s->store)) {
+		down_write(&s->lock);
+		s->valid = 0;
+		up_write(&s->lock);
+	}
+
+	s->have_metadata = 1;
+}
+
 /*
  * Construct a snapshot mapping: <origin_dev> <COW-dev> <p/n> <chunk-size>
  */
@@ -848,16 +862,7 @@ static void snapshot_resume(struct dm_target *ti)
 {
 	struct dm_snapshot *s = (struct dm_snapshot *) ti->private;
 
-	if (s->have_metadata)
-		return;
-
-	if (s->store.read_metadata(&s->store)) {
-		down_write(&s->lock);
-		s->valid = 0;
-		up_write(&s->lock);
-	}
-
-	s->have_metadata = 1;
+	read_snapshot_metadata(s);
 }
 
 static int snapshot_status(struct dm_target *ti, status_type_t type,
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index a6d3baa46f61..a6f2dc66c3db 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -638,7 +638,7 @@ int dm_split_args(int *argc, char ***argvp, char *input)
 static void check_for_valid_limits(struct io_restrictions *rs)
 {
 	if (!rs->max_sectors)
-		rs->max_sectors = MAX_SECTORS;
+		rs->max_sectors = SAFE_MAX_SECTORS;
 	if (!rs->max_phys_segments)
 		rs->max_phys_segments = MAX_PHYS_SEGMENTS;
 	if (!rs->max_hw_segments)
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 930b9fc27953..0e481512f918 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -55,6 +55,7 @@ union map_info *dm_get_mapinfo(struct bio *bio)
  */
 #define DMF_BLOCK_IO 0
 #define DMF_SUSPENDED 1
+#define DMF_FROZEN 2
 
 struct mapped_device {
 	struct rw_semaphore io_lock;
@@ -97,7 +98,7 @@ struct mapped_device {
 	 * freeze/thaw support require holding onto a super block
 	 */
 	struct super_block *frozen_sb;
-	struct block_device *frozen_bdev;
+	struct block_device *suspended_bdev;
 };
 
 #define MIN_IOS 256
@@ -836,9 +837,9 @@ static void __set_size(struct mapped_device *md, sector_t size)
 {
 	set_capacity(md->disk, size);
 
-	down(&md->frozen_bdev->bd_inode->i_sem);
-	i_size_write(md->frozen_bdev->bd_inode, (loff_t)size << SECTOR_SHIFT);
-	up(&md->frozen_bdev->bd_inode->i_sem);
+	down(&md->suspended_bdev->bd_inode->i_sem);
+	i_size_write(md->suspended_bdev->bd_inode, (loff_t)size << SECTOR_SHIFT);
+	up(&md->suspended_bdev->bd_inode->i_sem);
 }
 
 static int __bind(struct mapped_device *md, struct dm_table *t)
@@ -902,10 +903,9 @@ int dm_create_with_minor(unsigned int minor, struct mapped_device **result)
 	return create_aux(minor, 1, result);
 }
 
-void *dm_get_mdptr(dev_t dev)
+static struct mapped_device *dm_find_md(dev_t dev)
 {
 	struct mapped_device *md;
-	void *mdptr = NULL;
 	unsigned minor = MINOR(dev);
 
 	if (MAJOR(dev) != _major || minor >= (1 << MINORBITS))
@@ -914,12 +914,32 @@ void *dm_get_mdptr(dev_t dev)
 	down(&_minor_lock);
 
 	md = idr_find(&_minor_idr, minor);
-
-	if (md && (dm_disk(md)->first_minor == minor))
-		mdptr = md->interface_ptr;
+	if (!md || (dm_disk(md)->first_minor != minor))
+		md = NULL;
 
 	up(&_minor_lock);
 
+	return md;
+}
+
+struct mapped_device *dm_get_md(dev_t dev)
+{
+	struct mapped_device *md = dm_find_md(dev);
+
+	if (md)
+		dm_get(md);
+
+	return md;
+}
+
+void *dm_get_mdptr(dev_t dev)
+{
+	struct mapped_device *md;
+	void *mdptr = NULL;
+
+	md = dm_find_md(dev);
+	if (md)
+		mdptr = md->interface_ptr;
 	return mdptr;
 }
 
@@ -991,43 +1011,33 @@ out:
  */
 static int lock_fs(struct mapped_device *md)
 {
-	int r = -ENOMEM;
-
-	md->frozen_bdev = bdget_disk(md->disk, 0);
-	if (!md->frozen_bdev) {
-		DMWARN("bdget failed in lock_fs");
-		goto out;
-	}
+	int r;
 
 	WARN_ON(md->frozen_sb);
 
-	md->frozen_sb = freeze_bdev(md->frozen_bdev);
+	md->frozen_sb = freeze_bdev(md->suspended_bdev);
 	if (IS_ERR(md->frozen_sb)) {
 		r = PTR_ERR(md->frozen_sb);
-		goto out_bdput;
+		md->frozen_sb = NULL;
+		return r;
 	}
 
+	set_bit(DMF_FROZEN, &md->flags);
+
 	/* don't bdput right now, we don't want the bdev
-	 * to go away while it is locked.  We'll bdput
-	 * in unlock_fs
+	 * to go away while it is locked.
 	 */
 	return 0;
-
-out_bdput:
-	bdput(md->frozen_bdev);
-	md->frozen_sb = NULL;
-	md->frozen_bdev = NULL;
-out:
-	return r;
 }
 
 static void unlock_fs(struct mapped_device *md)
 {
-	thaw_bdev(md->frozen_bdev, md->frozen_sb);
-	bdput(md->frozen_bdev);
+	if (!test_bit(DMF_FROZEN, &md->flags))
+		return;
 
+	thaw_bdev(md->suspended_bdev, md->frozen_sb);
 	md->frozen_sb = NULL;
-	md->frozen_bdev = NULL;
+	clear_bit(DMF_FROZEN, &md->flags);
 }
 
 /*
@@ -1037,7 +1047,7 @@ static void unlock_fs(struct mapped_device *md)
  * dm_bind_table, dm_suspend must be called to flush any in
  * flight bios and ensure that any further io gets deferred.
  */
-int dm_suspend(struct mapped_device *md)
+int dm_suspend(struct mapped_device *md, int do_lockfs)
 {
 	struct dm_table *map = NULL;
 	DECLARE_WAITQUEUE(wait, current);
@@ -1053,10 +1063,19 @@ int dm_suspend(struct mapped_device *md)
 	/* This does not get reverted if there's an error later. */
 	dm_table_presuspend_targets(map);
 
-	/* Flush I/O to the device. */
-	r = lock_fs(md);
-	if (r)
+	md->suspended_bdev = bdget_disk(md->disk, 0);
+	if (!md->suspended_bdev) {
+		DMWARN("bdget failed in dm_suspend");
+		r = -ENOMEM;
 		goto out;
+	}
+
+	/* Flush I/O to the device. */
+	if (do_lockfs) {
+		r = lock_fs(md);
+		if (r)
+			goto out;
+	}
 
 	/*
 	 * First we set the BLOCK_IO flag so no more ios will be mapped.
@@ -1105,6 +1124,11 @@ int dm_suspend(struct mapped_device *md)
 	r = 0;
 
 out:
+	if (r && md->suspended_bdev) {
+		bdput(md->suspended_bdev);
+		md->suspended_bdev = NULL;
+	}
+
 	dm_table_put(map);
 	up(&md->suspend_lock);
 	return r;
@@ -1135,6 +1159,9 @@ int dm_resume(struct mapped_device *md)
 
 	unlock_fs(md);
 
+	bdput(md->suspended_bdev);
+	md->suspended_bdev = NULL;
+
 	clear_bit(DMF_SUSPENDED, &md->flags);
 
 	dm_table_unplug_all(map);
diff --git a/drivers/md/dm.h b/drivers/md/dm.h
index e38c3fc1a1db..4eaf075da217 100644
--- a/drivers/md/dm.h
+++ b/drivers/md/dm.h
@@ -28,7 +28,7 @@
  * in types.h.
  */
 #ifdef CONFIG_LBD
-#define SECTOR_FORMAT "%Lu"
+#define SECTOR_FORMAT "%llu"
 #else
 #define SECTOR_FORMAT "%lu"
 #endif
@@ -58,6 +58,7 @@ int dm_create(struct mapped_device **md);
 int dm_create_with_minor(unsigned int minor, struct mapped_device **md);
 void dm_set_mdptr(struct mapped_device *md, void *ptr);
 void *dm_get_mdptr(dev_t dev);
+struct mapped_device *dm_get_md(dev_t dev);
 
 /*
  * Reference counting for md.
@@ -68,7 +69,7 @@ void dm_put(struct mapped_device *md);
 /*
  * A device can still be used while suspended, but I/O is deferred.
  */
-int dm_suspend(struct mapped_device *md);
+int dm_suspend(struct mapped_device *md, int with_lockfs);
 int dm_resume(struct mapped_device *md);
 
 /*
diff --git a/drivers/md/faulty.c b/drivers/md/faulty.c
index 0248f8e7eac0..a7a5ab554338 100644
--- a/drivers/md/faulty.c
+++ b/drivers/md/faulty.c
@@ -316,9 +316,10 @@ static int stop(mddev_t *mddev)
 	return 0;
 }
 
-static mdk_personality_t faulty_personality =
+static struct mdk_personality faulty_personality =
 {
 	.name		= "faulty",
+	.level		= LEVEL_FAULTY,
 	.owner		= THIS_MODULE,
 	.make_request	= make_request,
 	.run		= run,
@@ -329,15 +330,17 @@ static mdk_personality_t faulty_personality =
 
 static int __init raid_init(void)
 {
-	return register_md_personality(FAULTY, &faulty_personality);
+	return register_md_personality(&faulty_personality);
 }
 
 static void raid_exit(void)
 {
-	unregister_md_personality(FAULTY);
+	unregister_md_personality(&faulty_personality);
 }
 
 module_init(raid_init);
 module_exit(raid_exit);
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("md-personality-10"); /* faulty */
+MODULE_ALIAS("md-faulty");
+MODULE_ALIAS("md-level--5");
diff --git a/drivers/md/kcopyd.c b/drivers/md/kcopyd.c
index eb7036485975..ca99979c868a 100644
--- a/drivers/md/kcopyd.c
+++ b/drivers/md/kcopyd.c
@@ -561,11 +561,13 @@ int kcopyd_copy(struct kcopyd_client *kc, struct io_region *from,
  * Cancels a kcopyd job, eg. someone might be deactivating a
  * mirror.
  */
+#if 0
 int kcopyd_cancel(struct kcopyd_job *job, int block)
 {
 	/* FIXME: finish */
 	return -1;
 }
+#endif  /*  0  */
 
 /*-----------------------------------------------------------------
  * Unit setup
@@ -684,4 +686,3 @@ void kcopyd_client_destroy(struct kcopyd_client *kc)
 EXPORT_SYMBOL(kcopyd_client_create);
 EXPORT_SYMBOL(kcopyd_client_destroy);
 EXPORT_SYMBOL(kcopyd_copy);
-EXPORT_SYMBOL(kcopyd_cancel);
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index 946efef3a8f5..777585458c85 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -121,11 +121,10 @@ static int linear_run (mddev_t *mddev)
 	sector_t curr_offset;
 	struct list_head *tmp;
 
-	conf = kmalloc (sizeof (*conf) + mddev->raid_disks*sizeof(dev_info_t),
+	conf = kzalloc (sizeof (*conf) + mddev->raid_disks*sizeof(dev_info_t),
 			GFP_KERNEL);
 	if (!conf)
 		goto out;
-	memset(conf, 0, sizeof(*conf) + mddev->raid_disks*sizeof(dev_info_t));
 	mddev->private = conf;
 
 	cnt = 0;
@@ -352,9 +351,10 @@ static void linear_status (struct seq_file *seq, mddev_t *mddev)
 }
 
 
-static mdk_personality_t linear_personality=
+static struct mdk_personality linear_personality =
 {
 	.name		= "linear",
+	.level		= LEVEL_LINEAR,
 	.owner		= THIS_MODULE,
 	.make_request	= linear_make_request,
 	.run		= linear_run,
@@ -364,16 +364,18 @@ static mdk_personality_t linear_personality=
 
 static int __init linear_init (void)
 {
-	return register_md_personality (LINEAR, &linear_personality);
+	return register_md_personality (&linear_personality);
 }
 
 static void linear_exit (void)
 {
-	unregister_md_personality (LINEAR);
+	unregister_md_personality (&linear_personality);
 }
 
 
 module_init(linear_init);
 module_exit(linear_exit);
 MODULE_LICENSE("GPL");
-MODULE_ALIAS("md-personality-1"); /* LINEAR */
+MODULE_ALIAS("md-personality-1"); /* LINEAR - deprecated*/
+MODULE_ALIAS("md-linear");
+MODULE_ALIAS("md-level--1");
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 8175a2a222da..1b76fb29fb70 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -42,6 +42,7 @@
 #include <linux/devfs_fs_kernel.h>
 #include <linux/buffer_head.h> /* for invalidate_bdev */
 #include <linux/suspend.h>
+#include <linux/poll.h>
 
 #include <linux/init.h>
 
@@ -67,7 +68,7 @@
 static void autostart_arrays (int part);
 #endif
 
-static mdk_personality_t *pers[MAX_PERSONALITY];
+static LIST_HEAD(pers_list);
 static DEFINE_SPINLOCK(pers_lock);
 
 /*
@@ -80,10 +81,22 @@ static DEFINE_SPINLOCK(pers_lock);
  * idle IO detection.
  *
  * you can change it via /proc/sys/dev/raid/speed_limit_min and _max.
+ * or /sys/block/mdX/md/sync_speed_{min,max}
  */
 
 static int sysctl_speed_limit_min = 1000;
 static int sysctl_speed_limit_max = 200000;
+static inline int speed_min(mddev_t *mddev)
+{
+	return mddev->sync_speed_min ?
+		mddev->sync_speed_min : sysctl_speed_limit_min;
+}
+
+static inline int speed_max(mddev_t *mddev)
+{
+	return mddev->sync_speed_max ?
+		mddev->sync_speed_max : sysctl_speed_limit_max;
+}
 
 static struct ctl_table_header *raid_table_header;
 
@@ -134,6 +147,24 @@ static struct block_device_operations md_fops;
 static int start_readonly;
 
 /*
+ * We have a system wide 'event count' that is incremented
+ * on any 'interesting' event, and readers of /proc/mdstat
+ * can use 'poll' or 'select' to find out when the event
+ * count increases.
+ *
+ * Events are:
+ *  start array, stop array, error, add device, remove device,
+ *  start build, activate spare
+ */
+static DECLARE_WAIT_QUEUE_HEAD(md_event_waiters);
+static atomic_t md_event_count;
+static void md_new_event(mddev_t *mddev)
+{
+	atomic_inc(&md_event_count);
+	wake_up(&md_event_waiters);
+}
+
+/*
  * Enables to iterate over all existing md arrays
  * all_mddevs_lock protects this list.
  */
@@ -209,12 +240,10 @@ static mddev_t * mddev_find(dev_t unit)
 	}
 	spin_unlock(&all_mddevs_lock);
 
-	new = (mddev_t *) kmalloc(sizeof(*new), GFP_KERNEL);
+	new = kzalloc(sizeof(*new), GFP_KERNEL);
 	if (!new)
 		return NULL;
 
-	memset(new, 0, sizeof(*new));
-
 	new->unit = unit;
 	if (MAJOR(unit) == MD_MAJOR)
 		new->md_minor = MINOR(unit);
@@ -262,7 +291,7 @@ static inline void mddev_unlock(mddev_t * mddev)
 	md_wakeup_thread(mddev->thread);
 }
 
-mdk_rdev_t * find_rdev_nr(mddev_t *mddev, int nr)
+static mdk_rdev_t * find_rdev_nr(mddev_t *mddev, int nr)
 {
 	mdk_rdev_t * rdev;
 	struct list_head *tmp;
@@ -286,6 +315,18 @@ static mdk_rdev_t * find_rdev(mddev_t * mddev, dev_t dev)
 	return NULL;
 }
 
+static struct mdk_personality *find_pers(int level, char *clevel)
+{
+	struct mdk_personality *pers;
+	list_for_each_entry(pers, &pers_list, list) {
+		if (level != LEVEL_NONE && pers->level == level)
+			return pers;
+		if (strcmp(pers->name, clevel)==0)
+			return pers;
+	}
+	return NULL;
+}
+
 static inline sector_t calc_dev_sboffset(struct block_device *bdev)
 {
 	sector_t size = bdev->bd_inode->i_size >> BLOCK_SIZE_BITS;
@@ -320,7 +361,7 @@ static int alloc_disk_sb(mdk_rdev_t * rdev)
 static void free_disk_sb(mdk_rdev_t * rdev)
 {
 	if (rdev->sb_page) {
-		page_cache_release(rdev->sb_page);
+		put_page(rdev->sb_page);
 		rdev->sb_loaded = 0;
 		rdev->sb_page = NULL;
 		rdev->sb_offset = 0;
@@ -461,6 +502,7 @@ int sync_page_io(struct block_device *bdev, sector_t sector, int size,
 	bio_put(bio);
 	return ret;
 }
+EXPORT_SYMBOL_GPL(sync_page_io);
 
 static int read_disk_sb(mdk_rdev_t * rdev, int size)
 {
@@ -665,6 +707,10 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version
 	}
 	rdev->size = calc_dev_size(rdev, sb->chunk_size);
 
+	if (rdev->size < sb->size && sb->level > 1)
+		/* "this cannot possibly happen" ... */
+		ret = -EINVAL;
+
  abort:
 	return ret;
 }
@@ -688,6 +734,7 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
 		mddev->ctime = sb->ctime;
 		mddev->utime = sb->utime;
 		mddev->level = sb->level;
+		mddev->clevel[0] = 0;
 		mddev->layout = sb->layout;
 		mddev->raid_disks = sb->raid_disks;
 		mddev->size = sb->size;
@@ -714,9 +761,10 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
 
 		if (sb->state & (1<<MD_SB_BITMAP_PRESENT) &&
 		    mddev->bitmap_file == NULL) {
-			if (mddev->level != 1 && mddev->level != 5 && mddev->level != 6) {
+			if (mddev->level != 1 && mddev->level != 5 && mddev->level != 6
+			    && mddev->level != 10) {
 				/* FIXME use a better test */
-				printk(KERN_WARNING "md: bitmaps only support for raid1\n");
+				printk(KERN_WARNING "md: bitmaps not supported for this level.\n");
 				return -EINVAL;
 			}
 			mddev->bitmap_offset = mddev->default_bitmap_offset;
@@ -968,6 +1016,7 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
 	}
 	rdev->preferred_minor = 0xffff;
 	rdev->data_offset = le64_to_cpu(sb->data_offset);
+	atomic_set(&rdev->corrected_errors, le32_to_cpu(sb->cnt_corrected_read));
 
 	rdev->sb_size = le32_to_cpu(sb->max_dev) * 2 + 256;
 	bmask = queue_hardsect_size(rdev->bdev->bd_disk->queue)-1;
@@ -1006,6 +1055,9 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
 	rdev->size = le64_to_cpu(sb->data_size)/2;
 	if (le32_to_cpu(sb->chunksize))
 		rdev->size &= ~((sector_t)le32_to_cpu(sb->chunksize)/2 - 1);
+
+	if (le32_to_cpu(sb->size) > rdev->size*2)
+		return -EINVAL;
 	return 0;
 }
 
@@ -1023,6 +1075,7 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
 		mddev->ctime = le64_to_cpu(sb->ctime) & ((1ULL << 32)-1);
 		mddev->utime = le64_to_cpu(sb->utime) & ((1ULL << 32)-1);
 		mddev->level = le32_to_cpu(sb->level);
+		mddev->clevel[0] = 0;
 		mddev->layout = le32_to_cpu(sb->layout);
 		mddev->raid_disks = le32_to_cpu(sb->raid_disks);
 		mddev->size = le64_to_cpu(sb->size)/2;
@@ -1037,8 +1090,9 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
 
 		if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_BITMAP_OFFSET) &&
 		    mddev->bitmap_file == NULL ) {
-			if (mddev->level != 1) {
-				printk(KERN_WARNING "md: bitmaps only supported for raid1\n");
+			if (mddev->level != 1 && mddev->level != 5 && mddev->level != 6
+			    && mddev->level != 10) {
+				printk(KERN_WARNING "md: bitmaps not supported for this level.\n");
 				return -EINVAL;
 			}
 			mddev->bitmap_offset = (__s32)le32_to_cpu(sb->bitmap_offset);
@@ -1105,6 +1159,8 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev)
 	else
 		sb->resync_offset = cpu_to_le64(0);
 
+	sb->cnt_corrected_read = atomic_read(&rdev->corrected_errors);
+
 	if (mddev->bitmap && mddev->bitmap_file == NULL) {
 		sb->bitmap_offset = cpu_to_le32((__u32)mddev->bitmap_offset);
 		sb->feature_map = cpu_to_le32(MD_FEATURE_BITMAP_OFFSET);
@@ -1187,6 +1243,14 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
 		MD_BUG();
 		return -EINVAL;
 	}
+	/* make sure rdev->size exceeds mddev->size */
+	if (rdev->size && (mddev->size == 0 || rdev->size < mddev->size)) {
+		if (mddev->pers)
+			/* Cannot change size, so fail */
+			return -ENOSPC;
+		else
+			mddev->size = rdev->size;
+	}
 	same_pdev = match_dev_unit(mddev, rdev);
 	if (same_pdev)
 		printk(KERN_WARNING
@@ -1496,6 +1560,26 @@ repeat:
 
 }
 
+/* words written to sysfs files may, or my not, be \n terminated.
+ * We want to accept with case. For this we use cmd_match.
+ */
+static int cmd_match(const char *cmd, const char *str)
+{
+	/* See if cmd, written into a sysfs file, matches
+	 * str.  They must either be the same, or cmd can
+	 * have a trailing newline
+	 */
+	while (*cmd && *str && *cmd == *str) {
+		cmd++;
+		str++;
+	}
+	if (*cmd == '\n')
+		cmd++;
+	if (*str || *cmd)
+		return 0;
+	return 1;
+}
+
 struct rdev_sysfs_entry {
 	struct attribute attr;
 	ssize_t (*show)(mdk_rdev_t *, char *);
@@ -1538,9 +1622,113 @@ super_show(mdk_rdev_t *rdev, char *page)
 }
 static struct rdev_sysfs_entry rdev_super = __ATTR_RO(super);
 
+static ssize_t
+errors_show(mdk_rdev_t *rdev, char *page)
+{
+	return sprintf(page, "%d\n", atomic_read(&rdev->corrected_errors));
+}
+
+static ssize_t
+errors_store(mdk_rdev_t *rdev, const char *buf, size_t len)
+{
+	char *e;
+	unsigned long n = simple_strtoul(buf, &e, 10);
+	if (*buf && (*e == 0 || *e == '\n')) {
+		atomic_set(&rdev->corrected_errors, n);
+		return len;
+	}
+	return -EINVAL;
+}
+static struct rdev_sysfs_entry rdev_errors =
+__ATTR(errors, 0644, errors_show, errors_store);
+
+static ssize_t
+slot_show(mdk_rdev_t *rdev, char *page)
+{
+	if (rdev->raid_disk < 0)
+		return sprintf(page, "none\n");
+	else
+		return sprintf(page, "%d\n", rdev->raid_disk);
+}
+
+static ssize_t
+slot_store(mdk_rdev_t *rdev, const char *buf, size_t len)
+{
+	char *e;
+	int slot = simple_strtoul(buf, &e, 10);
+	if (strncmp(buf, "none", 4)==0)
+		slot = -1;
+	else if (e==buf || (*e && *e!= '\n'))
+		return -EINVAL;
+	if (rdev->mddev->pers)
+		/* Cannot set slot in active array (yet) */
+		return -EBUSY;
+	if (slot >= rdev->mddev->raid_disks)
+		return -ENOSPC;
+	rdev->raid_disk = slot;
+	/* assume it is working */
+	rdev->flags = 0;
+	set_bit(In_sync, &rdev->flags);
+	return len;
+}
+
+
+static struct rdev_sysfs_entry rdev_slot =
+__ATTR(slot, 0644, slot_show, slot_store);
+
+static ssize_t
+offset_show(mdk_rdev_t *rdev, char *page)
+{
+	return sprintf(page, "%llu\n", (unsigned long long)rdev->data_offset);
+}
+
+static ssize_t
+offset_store(mdk_rdev_t *rdev, const char *buf, size_t len)
+{
+	char *e;
+	unsigned long long offset = simple_strtoull(buf, &e, 10);
+	if (e==buf || (*e && *e != '\n'))
+		return -EINVAL;
+	if (rdev->mddev->pers)
+		return -EBUSY;
+	rdev->data_offset = offset;
+	return len;
+}
+
+static struct rdev_sysfs_entry rdev_offset =
+__ATTR(offset, 0644, offset_show, offset_store);
+
+static ssize_t
+rdev_size_show(mdk_rdev_t *rdev, char *page)
+{
+	return sprintf(page, "%llu\n", (unsigned long long)rdev->size);
+}
+
+static ssize_t
+rdev_size_store(mdk_rdev_t *rdev, const char *buf, size_t len)
+{
+	char *e;
+	unsigned long long size = simple_strtoull(buf, &e, 10);
+	if (e==buf || (*e && *e != '\n'))
+		return -EINVAL;
+	if (rdev->mddev->pers)
+		return -EBUSY;
+	rdev->size = size;
+	if (size < rdev->mddev->size || rdev->mddev->size == 0)
+		rdev->mddev->size = size;
+	return len;
+}
+
+static struct rdev_sysfs_entry rdev_size =
+__ATTR(size, 0644, rdev_size_show, rdev_size_store);
+
 static struct attribute *rdev_default_attrs[] = {
 	&rdev_state.attr,
 	&rdev_super.attr,
+	&rdev_errors.attr,
+	&rdev_slot.attr,
+	&rdev_offset.attr,
+	&rdev_size.attr,
 	NULL,
 };
 static ssize_t
@@ -1598,12 +1786,11 @@ static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_mi
 	mdk_rdev_t *rdev;
 	sector_t size;
 
-	rdev = (mdk_rdev_t *) kmalloc(sizeof(*rdev), GFP_KERNEL);
+	rdev = kzalloc(sizeof(*rdev), GFP_KERNEL);
 	if (!rdev) {
 		printk(KERN_ERR "md: could not alloc mem for new device!\n");
 		return ERR_PTR(-ENOMEM);
 	}
-	memset(rdev, 0, sizeof(*rdev));
 
 	if ((err = alloc_disk_sb(rdev)))
 		goto abort_free;
@@ -1621,6 +1808,7 @@ static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_mi
 	rdev->data_offset = 0;
 	atomic_set(&rdev->nr_pending, 0);
 	atomic_set(&rdev->read_errors, 0);
+	atomic_set(&rdev->corrected_errors, 0);
 
 	size = rdev->bdev->bd_inode->i_size >> BLOCK_SIZE_BITS;
 	if (!size) {
@@ -1725,16 +1913,37 @@ static void analyze_sbs(mddev_t * mddev)
 static ssize_t
 level_show(mddev_t *mddev, char *page)
 {
-	mdk_personality_t *p = mddev->pers;
-	if (p == NULL && mddev->raid_disks == 0)
-		return 0;
-	if (mddev->level >= 0)
-		return sprintf(page, "raid%d\n", mddev->level);
-	else
+	struct mdk_personality *p = mddev->pers;
+	if (p)
 		return sprintf(page, "%s\n", p->name);
+	else if (mddev->clevel[0])
+		return sprintf(page, "%s\n", mddev->clevel);
+	else if (mddev->level != LEVEL_NONE)
+		return sprintf(page, "%d\n", mddev->level);
+	else
+		return 0;
+}
+
+static ssize_t
+level_store(mddev_t *mddev, const char *buf, size_t len)
+{
+	int rv = len;
+	if (mddev->pers)
+		return -EBUSY;
+	if (len == 0)
+		return 0;
+	if (len >= sizeof(mddev->clevel))
+		return -ENOSPC;
+	strncpy(mddev->clevel, buf, len);
+	if (mddev->clevel[len-1] == '\n')
+		len--;
+	mddev->clevel[len] = 0;
+	mddev->level = LEVEL_NONE;
+	return rv;
 }
 
-static struct md_sysfs_entry md_level = __ATTR_RO(level);
+static struct md_sysfs_entry md_level =
+__ATTR(level, 0644, level_show, level_store);
 
 static ssize_t
 raid_disks_show(mddev_t *mddev, char *page)
@@ -1744,7 +1953,197 @@ raid_disks_show(mddev_t *mddev, char *page)
 	return sprintf(page, "%d\n", mddev->raid_disks);
 }
 
-static struct md_sysfs_entry md_raid_disks = __ATTR_RO(raid_disks);
+static int update_raid_disks(mddev_t *mddev, int raid_disks);
+
+static ssize_t
+raid_disks_store(mddev_t *mddev, const char *buf, size_t len)
+{
+	/* can only set raid_disks if array is not yet active */
+	char *e;
+	int rv = 0;
+	unsigned long n = simple_strtoul(buf, &e, 10);
+
+	if (!*buf || (*e && *e != '\n'))
+		return -EINVAL;
+
+	if (mddev->pers)
+		rv = update_raid_disks(mddev, n);
+	else
+		mddev->raid_disks = n;
+	return rv ? rv : len;
+}
+static struct md_sysfs_entry md_raid_disks =
+__ATTR(raid_disks, 0644, raid_disks_show, raid_disks_store);
+
+static ssize_t
+chunk_size_show(mddev_t *mddev, char *page)
+{
+	return sprintf(page, "%d\n", mddev->chunk_size);
+}
+
+static ssize_t
+chunk_size_store(mddev_t *mddev, const char *buf, size_t len)
+{
+	/* can only set chunk_size if array is not yet active */
+	char *e;
+	unsigned long n = simple_strtoul(buf, &e, 10);
+
+	if (mddev->pers)
+		return -EBUSY;
+	if (!*buf || (*e && *e != '\n'))
+		return -EINVAL;
+
+	mddev->chunk_size = n;
+	return len;
+}
+static struct md_sysfs_entry md_chunk_size =
+__ATTR(chunk_size, 0644, chunk_size_show, chunk_size_store);
+
+static ssize_t
+null_show(mddev_t *mddev, char *page)
+{
+	return -EINVAL;
+}
+
+static ssize_t
+new_dev_store(mddev_t *mddev, const char *buf, size_t len)
+{
+	/* buf must be %d:%d\n? giving major and minor numbers */
+	/* The new device is added to the array.
+	 * If the array has a persistent superblock, we read the
+	 * superblock to initialise info and check validity.
+	 * Otherwise, only checking done is that in bind_rdev_to_array,
+	 * which mainly checks size.
+	 */
+	char *e;
+	int major = simple_strtoul(buf, &e, 10);
+	int minor;
+	dev_t dev;
+	mdk_rdev_t *rdev;
+	int err;
+
+	if (!*buf || *e != ':' || !e[1] || e[1] == '\n')
+		return -EINVAL;
+	minor = simple_strtoul(e+1, &e, 10);
+	if (*e && *e != '\n')
+		return -EINVAL;
+	dev = MKDEV(major, minor);
+	if (major != MAJOR(dev) ||
+	    minor != MINOR(dev))
+		return -EOVERFLOW;
+
+
+	if (mddev->persistent) {
+		rdev = md_import_device(dev, mddev->major_version,
+					mddev->minor_version);
+		if (!IS_ERR(rdev) && !list_empty(&mddev->disks)) {
+			mdk_rdev_t *rdev0 = list_entry(mddev->disks.next,
+						       mdk_rdev_t, same_set);
+			err = super_types[mddev->major_version]
+				.load_super(rdev, rdev0, mddev->minor_version);
+			if (err < 0)
+				goto out;
+		}
+	} else
+		rdev = md_import_device(dev, -1, -1);
+
+	if (IS_ERR(rdev))
+		return PTR_ERR(rdev);
+	err = bind_rdev_to_array(rdev, mddev);
+ out:
+	if (err)
+		export_rdev(rdev);
+	return err ? err : len;
+}
+
+static struct md_sysfs_entry md_new_device =
+__ATTR(new_dev, 0200, null_show, new_dev_store);
+
+static ssize_t
+size_show(mddev_t *mddev, char *page)
+{
+	return sprintf(page, "%llu\n", (unsigned long long)mddev->size);
+}
+
+static int update_size(mddev_t *mddev, unsigned long size);
+
+static ssize_t
+size_store(mddev_t *mddev, const char *buf, size_t len)
+{
+	/* If array is inactive, we can reduce the component size, but
+	 * not increase it (except from 0).
+	 * If array is active, we can try an on-line resize
+	 */
+	char *e;
+	int err = 0;
+	unsigned long long size = simple_strtoull(buf, &e, 10);
+	if (!*buf || *buf == '\n' ||
+	    (*e && *e != '\n'))
+		return -EINVAL;
+
+	if (mddev->pers) {
+		err = update_size(mddev, size);
+		md_update_sb(mddev);
+	} else {
+		if (mddev->size == 0 ||
+		    mddev->size > size)
+			mddev->size = size;
+		else
+			err = -ENOSPC;
+	}
+	return err ? err : len;
+}
+
+static struct md_sysfs_entry md_size =
+__ATTR(component_size, 0644, size_show, size_store);
+
+
+/* Metdata version.
+ * This is either 'none' for arrays with externally managed metadata,
+ * or N.M for internally known formats
+ */
+static ssize_t
+metadata_show(mddev_t *mddev, char *page)
+{
+	if (mddev->persistent)
+		return sprintf(page, "%d.%d\n",
+			       mddev->major_version, mddev->minor_version);
+	else
+		return sprintf(page, "none\n");
+}
+
+static ssize_t
+metadata_store(mddev_t *mddev, const char *buf, size_t len)
+{
+	int major, minor;
+	char *e;
+	if (!list_empty(&mddev->disks))
+		return -EBUSY;
+
+	if (cmd_match(buf, "none")) {
+		mddev->persistent = 0;
+		mddev->major_version = 0;
+		mddev->minor_version = 90;
+		return len;
+	}
+	major = simple_strtoul(buf, &e, 10);
+	if (e==buf || *e != '.')
+		return -EINVAL;
+	buf = e+1;
+	minor = simple_strtoul(buf, &e, 10);
+	if (e==buf || *e != '\n')
+		return -EINVAL;
+	if (major >= sizeof(super_types)/sizeof(super_types[0]) ||
+	    super_types[major].name == NULL)
+		return -ENOENT;
+	mddev->major_version = major;
+	mddev->minor_version = minor;
+	mddev->persistent = 1;
+	return len;
+}
+
+static struct md_sysfs_entry md_metadata =
+__ATTR(metadata_version, 0644, metadata_show, metadata_store);
 
 static ssize_t
 action_show(mddev_t *mddev, char *page)
@@ -1771,31 +2170,27 @@ action_store(mddev_t *mddev, const char *page, size_t len)
 	if (!mddev->pers || !mddev->pers->sync_request)
 		return -EINVAL;
 
-	if (strcmp(page, "idle")==0 || strcmp(page, "idle\n")==0) {
+	if (cmd_match(page, "idle")) {
 		if (mddev->sync_thread) {
 			set_bit(MD_RECOVERY_INTR, &mddev->recovery);
 			md_unregister_thread(mddev->sync_thread);
 			mddev->sync_thread = NULL;
 			mddev->recovery = 0;
 		}
-		return len;
-	}
-
-	if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) ||
-	    test_bit(MD_RECOVERY_NEEDED, &mddev->recovery))
+	} else if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) ||
+		   test_bit(MD_RECOVERY_NEEDED, &mddev->recovery))
 		return -EBUSY;
-	if (strcmp(page, "resync")==0 || strcmp(page, "resync\n")==0 ||
-	    strcmp(page, "recover")==0 || strcmp(page, "recover\n")==0)
+	else if (cmd_match(page, "resync") || cmd_match(page, "recover"))
 		set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
 	else {
-		if (strcmp(page, "check")==0 || strcmp(page, "check\n")==0)
+		if (cmd_match(page, "check"))
 			set_bit(MD_RECOVERY_CHECK, &mddev->recovery);
-		else if (strcmp(page, "repair")!=0 && strcmp(page, "repair\n")!=0)
+		else if (cmd_match(page, "repair"))
 			return -EINVAL;
 		set_bit(MD_RECOVERY_REQUESTED, &mddev->recovery);
 		set_bit(MD_RECOVERY_SYNC, &mddev->recovery);
-		set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
 	}
+	set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
 	md_wakeup_thread(mddev->thread);
 	return len;
 }
@@ -1814,15 +2209,107 @@ md_scan_mode = __ATTR(sync_action, S_IRUGO|S_IWUSR, action_show, action_store);
 static struct md_sysfs_entry
 md_mismatches = __ATTR_RO(mismatch_cnt);
 
+static ssize_t
+sync_min_show(mddev_t *mddev, char *page)
+{
+	return sprintf(page, "%d (%s)\n", speed_min(mddev),
+		       mddev->sync_speed_min ? "local": "system");
+}
+
+static ssize_t
+sync_min_store(mddev_t *mddev, const char *buf, size_t len)
+{
+	int min;
+	char *e;
+	if (strncmp(buf, "system", 6)==0) {
+		mddev->sync_speed_min = 0;
+		return len;
+	}
+	min = simple_strtoul(buf, &e, 10);
+	if (buf == e || (*e && *e != '\n') || min <= 0)
+		return -EINVAL;
+	mddev->sync_speed_min = min;
+	return len;
+}
+
+static struct md_sysfs_entry md_sync_min =
+__ATTR(sync_speed_min, S_IRUGO|S_IWUSR, sync_min_show, sync_min_store);
+
+static ssize_t
+sync_max_show(mddev_t *mddev, char *page)
+{
+	return sprintf(page, "%d (%s)\n", speed_max(mddev),
+		       mddev->sync_speed_max ? "local": "system");
+}
+
+static ssize_t
+sync_max_store(mddev_t *mddev, const char *buf, size_t len)
+{
+	int max;
+	char *e;
+	if (strncmp(buf, "system", 6)==0) {
+		mddev->sync_speed_max = 0;
+		return len;
+	}
+	max = simple_strtoul(buf, &e, 10);
+	if (buf == e || (*e && *e != '\n') || max <= 0)
+		return -EINVAL;
+	mddev->sync_speed_max = max;
+	return len;
+}
+
+static struct md_sysfs_entry md_sync_max =
+__ATTR(sync_speed_max, S_IRUGO|S_IWUSR, sync_max_show, sync_max_store);
+
+
+static ssize_t
+sync_speed_show(mddev_t *mddev, char *page)
+{
+	unsigned long resync, dt, db;
+	resync = (mddev->curr_resync - atomic_read(&mddev->recovery_active));
+	dt = ((jiffies - mddev->resync_mark) / HZ);
+	if (!dt) dt++;
+	db = resync - (mddev->resync_mark_cnt);
+	return sprintf(page, "%ld\n", db/dt/2); /* K/sec */
+}
+
+static struct md_sysfs_entry
+md_sync_speed = __ATTR_RO(sync_speed);
+
+static ssize_t
+sync_completed_show(mddev_t *mddev, char *page)
+{
+	unsigned long max_blocks, resync;
+
+	if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery))
+		max_blocks = mddev->resync_max_sectors;
+	else
+		max_blocks = mddev->size << 1;
+
+	resync = (mddev->curr_resync - atomic_read(&mddev->recovery_active));
+	return sprintf(page, "%lu / %lu\n", resync, max_blocks);
+}
+
+static struct md_sysfs_entry
+md_sync_completed = __ATTR_RO(sync_completed);
+
 static struct attribute *md_default_attrs[] = {
 	&md_level.attr,
 	&md_raid_disks.attr,
+	&md_chunk_size.attr,
+	&md_size.attr,
+	&md_metadata.attr,
+	&md_new_device.attr,
 	NULL,
 };
 
 static struct attribute *md_redundancy_attrs[] = {
 	&md_scan_mode.attr,
 	&md_mismatches.attr,
+	&md_sync_min.attr,
+	&md_sync_max.attr,
+	&md_sync_speed.attr,
+	&md_sync_completed.attr,
 	NULL,
 };
 static struct attribute_group md_redundancy_group = {
@@ -1937,14 +2424,16 @@ static void md_safemode_timeout(unsigned long data)
 	md_wakeup_thread(mddev->thread);
 }
 
+static int start_dirty_degraded;
 
 static int do_md_run(mddev_t * mddev)
 {
-	int pnum, err;
+	int err;
 	int chunk_size;
 	struct list_head *tmp;
 	mdk_rdev_t *rdev;
 	struct gendisk *disk;
+	struct mdk_personality *pers;
 	char b[BDEVNAME_SIZE];
 
 	if (list_empty(&mddev->disks))
@@ -1961,20 +2450,8 @@ static int do_md_run(mddev_t * mddev)
 		analyze_sbs(mddev);
 
 	chunk_size = mddev->chunk_size;
-	pnum = level_to_pers(mddev->level);
 
-	if ((pnum != MULTIPATH) && (pnum != RAID1)) {
-		if (!chunk_size) {
-			/*
-			 * 'default chunksize' in the old md code used to
-			 * be PAGE_SIZE, baaad.
-			 * we abort here to be on the safe side. We don't
-			 * want to continue the bad practice.
-			 */
-			printk(KERN_ERR 
-				"no chunksize specified, see 'man raidtab'\n");
-			return -EINVAL;
-		}
+	if (chunk_size) {
 		if (chunk_size > MAX_CHUNK_SIZE) {
 			printk(KERN_ERR "too big chunk_size: %d > %d\n",
 				chunk_size, MAX_CHUNK_SIZE);
@@ -2010,10 +2487,10 @@ static int do_md_run(mddev_t * mddev)
 	}
 
 #ifdef CONFIG_KMOD
-	if (!pers[pnum])
-	{
-		request_module("md-personality-%d", pnum);
-	}
+	if (mddev->level != LEVEL_NONE)
+		request_module("md-level-%d", mddev->level);
+	else if (mddev->clevel[0])
+		request_module("md-%s", mddev->clevel);
 #endif
 
 	/*
@@ -2035,30 +2512,39 @@ static int do_md_run(mddev_t * mddev)
 		return -ENOMEM;
 
 	spin_lock(&pers_lock);
-	if (!pers[pnum] || !try_module_get(pers[pnum]->owner)) {
+	pers = find_pers(mddev->level, mddev->clevel);
+	if (!pers || !try_module_get(pers->owner)) {
 		spin_unlock(&pers_lock);
-		printk(KERN_WARNING "md: personality %d is not loaded!\n",
-		       pnum);
+		if (mddev->level != LEVEL_NONE)
+			printk(KERN_WARNING "md: personality for level %d is not loaded!\n",
+			       mddev->level);
+		else
+			printk(KERN_WARNING "md: personality for level %s is not loaded!\n",
+			       mddev->clevel);
 		return -EINVAL;
 	}
-
-	mddev->pers = pers[pnum];
+	mddev->pers = pers;
 	spin_unlock(&pers_lock);
+	mddev->level = pers->level;
+	strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel));
 
 	mddev->recovery = 0;
 	mddev->resync_max_sectors = mddev->size << 1; /* may be over-ridden by personality */
 	mddev->barriers_work = 1;
+	mddev->ok_start_degraded = start_dirty_degraded;
 
 	if (start_readonly)
 		mddev->ro = 2; /* read-only, but switch on first write */
 
-	/* before we start the array running, initialise the bitmap */
-	err = bitmap_create(mddev);
-	if (err)
-		printk(KERN_ERR "%s: failed to create bitmap (%d)\n",
-			mdname(mddev), err);
-	else
-		err = mddev->pers->run(mddev);
+	err = mddev->pers->run(mddev);
+	if (!err && mddev->pers->sync_request) {
+		err = bitmap_create(mddev);
+		if (err) {
+			printk(KERN_ERR "%s: failed to create bitmap (%d)\n",
+			       mdname(mddev), err);
+			mddev->pers->stop(mddev);
+		}
+	}
 	if (err) {
 		printk(KERN_ERR "md: pers->run() failed ...\n");
 		module_put(mddev->pers->owner);
@@ -2104,6 +2590,7 @@ static int do_md_run(mddev_t * mddev)
 	mddev->queue->make_request_fn = mddev->pers->make_request;
 
 	mddev->changed = 1;
+	md_new_event(mddev);
 	return 0;
 }
 
@@ -2231,6 +2718,7 @@ static int do_md_stop(mddev_t * mddev, int ro)
 		printk(KERN_INFO "md: %s switched to read-only mode.\n",
 			mdname(mddev));
 	err = 0;
+	md_new_event(mddev);
 out:
 	return err;
 }
@@ -2668,12 +3156,6 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
 		if (info->state & (1<<MD_DISK_WRITEMOSTLY))
 			set_bit(WriteMostly, &rdev->flags);
 
-		err = bind_rdev_to_array(rdev, mddev);
-		if (err) {
-			export_rdev(rdev);
-			return err;
-		}
-
 		if (!mddev->persistent) {
 			printk(KERN_INFO "md: nonpersistent superblock ...\n");
 			rdev->sb_offset = rdev->bdev->bd_inode->i_size >> BLOCK_SIZE_BITS;
@@ -2681,8 +3163,11 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
 			rdev->sb_offset = calc_dev_sboffset(rdev->bdev);
 		rdev->size = calc_dev_size(rdev, mddev->chunk_size);
 
-		if (!mddev->size || (mddev->size > rdev->size))
-			mddev->size = rdev->size;
+		err = bind_rdev_to_array(rdev, mddev);
+		if (err) {
+			export_rdev(rdev);
+			return err;
+		}
 	}
 
 	return 0;
@@ -2705,6 +3190,7 @@ static int hot_remove_disk(mddev_t * mddev, dev_t dev)
 
 	kick_rdev_from_array(rdev);
 	md_update_sb(mddev);
+	md_new_event(mddev);
 
 	return 0;
 busy:
@@ -2753,15 +3239,6 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev)
 	size = calc_dev_size(rdev, mddev->chunk_size);
 	rdev->size = size;
 
-	if (size < mddev->size) {
-		printk(KERN_WARNING 
-			"%s: disk size %llu blocks < array size %llu\n",
-			mdname(mddev), (unsigned long long)size,
-			(unsigned long long)mddev->size);
-		err = -ENOSPC;
-		goto abort_export;
-	}
-
 	if (test_bit(Faulty, &rdev->flags)) {
 		printk(KERN_WARNING 
 			"md: can not hot-add faulty %s disk to %s!\n",
@@ -2771,7 +3248,9 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev)
 	}
 	clear_bit(In_sync, &rdev->flags);
 	rdev->desc_nr = -1;
-	bind_rdev_to_array(rdev, mddev);
+	err = bind_rdev_to_array(rdev, mddev);
+	if (err)
+		goto abort_export;
 
 	/*
 	 * The rest should better be atomic, we can have disk failures
@@ -2795,7 +3274,7 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev)
 	 */
 	set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
 	md_wakeup_thread(mddev->thread);
-
+	md_new_event(mddev);
 	return 0;
 
 abort_unbind_export:
@@ -2942,6 +3421,81 @@ static int set_array_info(mddev_t * mddev, mdu_array_info_t *info)
 	return 0;
 }
 
+static int update_size(mddev_t *mddev, unsigned long size)
+{
+	mdk_rdev_t * rdev;
+	int rv;
+	struct list_head *tmp;
+
+	if (mddev->pers->resize == NULL)
+		return -EINVAL;
+	/* The "size" is the amount of each device that is used.
+	 * This can only make sense for arrays with redundancy.
+	 * linear and raid0 always use whatever space is available
+	 * We can only consider changing the size if no resync
+	 * or reconstruction is happening, and if the new size
+	 * is acceptable. It must fit before the sb_offset or,
+	 * if that is <data_offset, it must fit before the
+	 * size of each device.
+	 * If size is zero, we find the largest size that fits.
+	 */
+	if (mddev->sync_thread)
+		return -EBUSY;
+	ITERATE_RDEV(mddev,rdev,tmp) {
+		sector_t avail;
+		int fit = (size == 0);
+		if (rdev->sb_offset > rdev->data_offset)
+			avail = (rdev->sb_offset*2) - rdev->data_offset;
+		else
+			avail = get_capacity(rdev->bdev->bd_disk)
+				- rdev->data_offset;
+		if (fit && (size == 0 || size > avail/2))
+			size = avail/2;
+		if (avail < ((sector_t)size << 1))
+			return -ENOSPC;
+	}
+	rv = mddev->pers->resize(mddev, (sector_t)size *2);
+	if (!rv) {
+		struct block_device *bdev;
+
+		bdev = bdget_disk(mddev->gendisk, 0);
+		if (bdev) {
+			down(&bdev->bd_inode->i_sem);
+			i_size_write(bdev->bd_inode, mddev->array_size << 10);
+			up(&bdev->bd_inode->i_sem);
+			bdput(bdev);
+		}
+	}
+	return rv;
+}
+
+static int update_raid_disks(mddev_t *mddev, int raid_disks)
+{
+	int rv;
+	/* change the number of raid disks */
+	if (mddev->pers->reshape == NULL)
+		return -EINVAL;
+	if (raid_disks <= 0 ||
+	    raid_disks >= mddev->max_disks)
+		return -EINVAL;
+	if (mddev->sync_thread)
+		return -EBUSY;
+	rv = mddev->pers->reshape(mddev, raid_disks);
+	if (!rv) {
+		struct block_device *bdev;
+
+		bdev = bdget_disk(mddev->gendisk, 0);
+		if (bdev) {
+			down(&bdev->bd_inode->i_sem);
+			i_size_write(bdev->bd_inode, mddev->array_size << 10);
+			up(&bdev->bd_inode->i_sem);
+			bdput(bdev);
+		}
+	}
+	return rv;
+}
+
+
 /*
  * update_array_info is used to change the configuration of an
  * on-line array.
@@ -2990,71 +3544,12 @@ static int update_array_info(mddev_t *mddev, mdu_array_info_t *info)
 		else
 			return mddev->pers->reconfig(mddev, info->layout, -1);
 	}
-	if (mddev->size != info->size) {
-		mdk_rdev_t * rdev;
-		struct list_head *tmp;
-		if (mddev->pers->resize == NULL)
-			return -EINVAL;
-		/* The "size" is the amount of each device that is used.
-		 * This can only make sense for arrays with redundancy.
-		 * linear and raid0 always use whatever space is available
-		 * We can only consider changing the size if no resync
-		 * or reconstruction is happening, and if the new size
-		 * is acceptable. It must fit before the sb_offset or,
-		 * if that is <data_offset, it must fit before the
-		 * size of each device.
-		 * If size is zero, we find the largest size that fits.
-		 */
-		if (mddev->sync_thread)
-			return -EBUSY;
-		ITERATE_RDEV(mddev,rdev,tmp) {
-			sector_t avail;
-			int fit = (info->size == 0);
-			if (rdev->sb_offset > rdev->data_offset)
-				avail = (rdev->sb_offset*2) - rdev->data_offset;
-			else
-				avail = get_capacity(rdev->bdev->bd_disk)
-					- rdev->data_offset;
-			if (fit && (info->size == 0 || info->size > avail/2))
-				info->size = avail/2;
-			if (avail < ((sector_t)info->size << 1))
-				return -ENOSPC;
-		}
-		rv = mddev->pers->resize(mddev, (sector_t)info->size *2);
-		if (!rv) {
-			struct block_device *bdev;
-
-			bdev = bdget_disk(mddev->gendisk, 0);
-			if (bdev) {
-				down(&bdev->bd_inode->i_sem);
-				i_size_write(bdev->bd_inode, mddev->array_size << 10);
-				up(&bdev->bd_inode->i_sem);
-				bdput(bdev);
-			}
-		}
-	}
-	if (mddev->raid_disks    != info->raid_disks) {
-		/* change the number of raid disks */
-		if (mddev->pers->reshape == NULL)
-			return -EINVAL;
-		if (info->raid_disks <= 0 ||
-		    info->raid_disks >= mddev->max_disks)
-			return -EINVAL;
-		if (mddev->sync_thread)
-			return -EBUSY;
-		rv = mddev->pers->reshape(mddev, info->raid_disks);
-		if (!rv) {
-			struct block_device *bdev;
-
-			bdev = bdget_disk(mddev->gendisk, 0);
-			if (bdev) {
-				down(&bdev->bd_inode->i_sem);
-				i_size_write(bdev->bd_inode, mddev->array_size << 10);
-				up(&bdev->bd_inode->i_sem);
-				bdput(bdev);
-			}
-		}
-	}
+	if (mddev->size != info->size)
+		rv = update_size(mddev, info->size);
+
+	if (mddev->raid_disks    != info->raid_disks)
+		rv = update_raid_disks(mddev, info->raid_disks);
+
 	if ((state ^ info->state) & (1<<MD_SB_BITMAP_PRESENT)) {
 		if (mddev->pers->quiesce == NULL)
 			return -EINVAL;
@@ -3476,11 +3971,10 @@ mdk_thread_t *md_register_thread(void (*run) (mddev_t *), mddev_t *mddev,
 {
 	mdk_thread_t *thread;
 
-	thread = kmalloc(sizeof(mdk_thread_t), GFP_KERNEL);
+	thread = kzalloc(sizeof(mdk_thread_t), GFP_KERNEL);
 	if (!thread)
 		return NULL;
 
-	memset(thread, 0, sizeof(mdk_thread_t));
 	init_waitqueue_head(&thread->wqueue);
 
 	thread->run = run;
@@ -3524,6 +4018,7 @@ void md_error(mddev_t *mddev, mdk_rdev_t *rdev)
 	set_bit(MD_RECOVERY_INTR, &mddev->recovery);
 	set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
 	md_wakeup_thread(mddev->thread);
+	md_new_event(mddev);
 }
 
 /* seq_file implementation /proc/mdstat */
@@ -3664,24 +4159,29 @@ static void md_seq_stop(struct seq_file *seq, void *v)
 		mddev_put(mddev);
 }
 
+struct mdstat_info {
+	int event;
+};
+
 static int md_seq_show(struct seq_file *seq, void *v)
 {
 	mddev_t *mddev = v;
 	sector_t size;
 	struct list_head *tmp2;
 	mdk_rdev_t *rdev;
-	int i;
+	struct mdstat_info *mi = seq->private;
 	struct bitmap *bitmap;
 
 	if (v == (void*)1) {
+		struct mdk_personality *pers;
 		seq_printf(seq, "Personalities : ");
 		spin_lock(&pers_lock);
-		for (i = 0; i < MAX_PERSONALITY; i++)
-			if (pers[i])
-				seq_printf(seq, "[%s] ", pers[i]->name);
+		list_for_each_entry(pers, &pers_list, list)
+			seq_printf(seq, "[%s] ", pers->name);
 
 		spin_unlock(&pers_lock);
 		seq_printf(seq, "\n");
+		mi->event = atomic_read(&md_event_count);
 		return 0;
 	}
 	if (v == (void*)2) {
@@ -3790,47 +4290,68 @@ static struct seq_operations md_seq_ops = {
 static int md_seq_open(struct inode *inode, struct file *file)
 {
 	int error;
+	struct mdstat_info *mi = kmalloc(sizeof(*mi), GFP_KERNEL);
+	if (mi == NULL)
+		return -ENOMEM;
 
 	error = seq_open(file, &md_seq_ops);
+	if (error)
+		kfree(mi);
+	else {
+		struct seq_file *p = file->private_data;
+		p->private = mi;
+		mi->event = atomic_read(&md_event_count);
+	}
 	return error;
 }
 
+static int md_seq_release(struct inode *inode, struct file *file)
+{
+	struct seq_file *m = file->private_data;
+	struct mdstat_info *mi = m->private;
+	m->private = NULL;
+	kfree(mi);
+	return seq_release(inode, file);
+}
+
+static unsigned int mdstat_poll(struct file *filp, poll_table *wait)
+{
+	struct seq_file *m = filp->private_data;
+	struct mdstat_info *mi = m->private;
+	int mask;
+
+	poll_wait(filp, &md_event_waiters, wait);
+
+	/* always allow read */
+	mask = POLLIN | POLLRDNORM;
+
+	if (mi->event != atomic_read(&md_event_count))
+		mask |= POLLERR | POLLPRI;
+	return mask;
+}
+
 static struct file_operations md_seq_fops = {
 	.open           = md_seq_open,
 	.read           = seq_read,
 	.llseek         = seq_lseek,
-	.release	= seq_release,
+	.release	= md_seq_release,
+	.poll		= mdstat_poll,
 };
 
-int register_md_personality(int pnum, mdk_personality_t *p)
+int register_md_personality(struct mdk_personality *p)
 {
-	if (pnum >= MAX_PERSONALITY) {
-		printk(KERN_ERR
-		       "md: tried to install personality %s as nr %d, but max is %lu\n",
-		       p->name, pnum, MAX_PERSONALITY-1);
-		return -EINVAL;
-	}
-
 	spin_lock(&pers_lock);
-	if (pers[pnum]) {
-		spin_unlock(&pers_lock);
-		return -EBUSY;
-	}
-
-	pers[pnum] = p;
-	printk(KERN_INFO "md: %s personality registered as nr %d\n", p->name, pnum);
+	list_add_tail(&p->list, &pers_list);
+	printk(KERN_INFO "md: %s personality registered for level %d\n", p->name, p->level);
 	spin_unlock(&pers_lock);
 	return 0;
 }
 
-int unregister_md_personality(int pnum)
+int unregister_md_personality(struct mdk_personality *p)
 {
-	if (pnum >= MAX_PERSONALITY)
-		return -EINVAL;
-
-	printk(KERN_INFO "md: %s personality unregistered\n", pers[pnum]->name);
+	printk(KERN_INFO "md: %s personality unregistered\n", p->name);
 	spin_lock(&pers_lock);
-	pers[pnum] = NULL;
+	list_del_init(&p->list);
 	spin_unlock(&pers_lock);
 	return 0;
 }
@@ -4012,10 +4533,10 @@ static void md_do_sync(mddev_t *mddev)
 
 	printk(KERN_INFO "md: syncing RAID array %s\n", mdname(mddev));
 	printk(KERN_INFO "md: minimum _guaranteed_ reconstruction speed:"
-		" %d KB/sec/disc.\n", sysctl_speed_limit_min);
+		" %d KB/sec/disc.\n", speed_min(mddev));
 	printk(KERN_INFO "md: using maximum available idle IO bandwidth "
 	       "(but not more than %d KB/sec) for reconstruction.\n",
-	       sysctl_speed_limit_max);
+	       speed_max(mddev));
 
 	is_mddev_idle(mddev); /* this also initializes IO event counters */
 	/* we don't use the checkpoint if there's a bitmap */
@@ -4056,7 +4577,7 @@ static void md_do_sync(mddev_t *mddev)
 
 		skipped = 0;
 		sectors = mddev->pers->sync_request(mddev, j, &skipped,
-					    currspeed < sysctl_speed_limit_min);
+					    currspeed < speed_min(mddev));
 		if (sectors == 0) {
 			set_bit(MD_RECOVERY_ERR, &mddev->recovery);
 			goto out;
@@ -4069,7 +4590,11 @@ static void md_do_sync(mddev_t *mddev)
 
 		j += sectors;
 		if (j>1) mddev->curr_resync = j;
-
+		if (last_check == 0)
+			/* this is the earliers that rebuilt will be
+			 * visible in /proc/mdstat
+			 */
+			md_new_event(mddev);
 
 		if (last_check + window > io_sectors || j == max_sectors)
 			continue;
@@ -4117,8 +4642,8 @@ static void md_do_sync(mddev_t *mddev)
 		currspeed = ((unsigned long)(io_sectors-mddev->resync_mark_cnt))/2
 			/((jiffies-mddev->resync_mark)/HZ +1) +1;
 
-		if (currspeed > sysctl_speed_limit_min) {
-			if ((currspeed > sysctl_speed_limit_max) ||
+		if (currspeed > speed_min(mddev)) {
+			if ((currspeed > speed_max(mddev)) ||
 					!is_mddev_idle(mddev)) {
 				msleep(500);
 				goto repeat;
@@ -4255,6 +4780,7 @@ void md_check_recovery(mddev_t *mddev)
 			mddev->recovery = 0;
 			/* flag recovery needed just to double check */
 			set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+			md_new_event(mddev);
 			goto unlock;
 		}
 		/* Clear some bits that don't mean anything, but
@@ -4292,6 +4818,7 @@ void md_check_recovery(mddev_t *mddev)
 						sprintf(nm, "rd%d", rdev->raid_disk);
 						sysfs_create_link(&mddev->kobj, &rdev->kobj, nm);
 						spares++;
+						md_new_event(mddev);
 					} else
 						break;
 				}
@@ -4324,9 +4851,9 @@ void md_check_recovery(mddev_t *mddev)
 					mdname(mddev));
 				/* leave the spares where they are, it shouldn't hurt */
 				mddev->recovery = 0;
-			} else {
+			} else
 				md_wakeup_thread(mddev->sync_thread);
-			}
+			md_new_event(mddev);
 		}
 	unlock:
 		mddev_unlock(mddev);
@@ -4503,12 +5030,14 @@ static int set_ro(const char *val, struct kernel_param *kp)
 	int num = simple_strtoul(val, &e, 10);
 	if (*val && (*e == '\0' || *e == '\n')) {
 		start_readonly = num;
-		return 0;;
+		return 0;
 	}
 	return -EINVAL;
 }
 
 module_param_call(start_ro, set_ro, get_ro, NULL, 0600);
+module_param(start_dirty_degraded, int, 0644);
+
 
 EXPORT_SYMBOL(register_md_personality);
 EXPORT_SYMBOL(unregister_md_personality);
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index 145cdc5ad008..e6aa309a66d7 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -35,15 +35,10 @@
 #define	NR_RESERVED_BUFS	32
 
 
-static mdk_personality_t multipath_personality;
-
-
 static void *mp_pool_alloc(gfp_t gfp_flags, void *data)
 {
 	struct multipath_bh *mpb;
-	mpb = kmalloc(sizeof(*mpb), gfp_flags);
-	if (mpb) 
-		memset(mpb, 0, sizeof(*mpb));
+	mpb = kzalloc(sizeof(*mpb), gfp_flags);
 	return mpb;
 }
 
@@ -444,7 +439,7 @@ static int multipath_run (mddev_t *mddev)
 	 * should be freed in multipath_stop()]
 	 */
 
-	conf = kmalloc(sizeof(multipath_conf_t), GFP_KERNEL);
+	conf = kzalloc(sizeof(multipath_conf_t), GFP_KERNEL);
 	mddev->private = conf;
 	if (!conf) {
 		printk(KERN_ERR 
@@ -452,9 +447,8 @@ static int multipath_run (mddev_t *mddev)
 			mdname(mddev));
 		goto out;
 	}
-	memset(conf, 0, sizeof(*conf));
 
-	conf->multipaths = kmalloc(sizeof(struct multipath_info)*mddev->raid_disks,
+	conf->multipaths = kzalloc(sizeof(struct multipath_info)*mddev->raid_disks,
 				   GFP_KERNEL);
 	if (!conf->multipaths) {
 		printk(KERN_ERR 
@@ -462,7 +456,6 @@ static int multipath_run (mddev_t *mddev)
 			mdname(mddev));
 		goto out_free_conf;
 	}
-	memset(conf->multipaths, 0, sizeof(struct multipath_info)*mddev->raid_disks);
 
 	conf->working_disks = 0;
 	ITERATE_RDEV(mddev,rdev,tmp) {
@@ -557,9 +550,10 @@ static int multipath_stop (mddev_t *mddev)
 	return 0;
 }
 
-static mdk_personality_t multipath_personality=
+static struct mdk_personality multipath_personality =
 {
 	.name		= "multipath",
+	.level		= LEVEL_MULTIPATH,
 	.owner		= THIS_MODULE,
 	.make_request	= multipath_make_request,
 	.run		= multipath_run,
@@ -572,15 +566,17 @@ static mdk_personality_t multipath_personality=
 
 static int __init multipath_init (void)
 {
-	return register_md_personality (MULTIPATH, &multipath_personality);
+	return register_md_personality (&multipath_personality);
 }
 
 static void __exit multipath_exit (void)
 {
-	unregister_md_personality (MULTIPATH);
+	unregister_md_personality (&multipath_personality);
 }
 
 module_init(multipath_init);
 module_exit(multipath_exit);
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("md-personality-7"); /* MULTIPATH */
+MODULE_ALIAS("md-multipath");
+MODULE_ALIAS("md-level--4");
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index fece3277c2a5..abbca150202b 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -113,21 +113,16 @@ static int create_strip_zones (mddev_t *mddev)
 	}
 	printk("raid0: FINAL %d zones\n", conf->nr_strip_zones);
 
-	conf->strip_zone = kmalloc(sizeof(struct strip_zone)*
+	conf->strip_zone = kzalloc(sizeof(struct strip_zone)*
 				conf->nr_strip_zones, GFP_KERNEL);
 	if (!conf->strip_zone)
 		return 1;
-	conf->devlist = kmalloc(sizeof(mdk_rdev_t*)*
+	conf->devlist = kzalloc(sizeof(mdk_rdev_t*)*
 				conf->nr_strip_zones*mddev->raid_disks,
 				GFP_KERNEL);
 	if (!conf->devlist)
 		return 1;
 
-	memset(conf->strip_zone, 0,sizeof(struct strip_zone)*
-				   conf->nr_strip_zones);
-	memset(conf->devlist, 0,
-	       sizeof(mdk_rdev_t*) * conf->nr_strip_zones * mddev->raid_disks);
-
 	/* The first zone must contain all devices, so here we check that
 	 * there is a proper alignment of slots to devices and find them all
 	 */
@@ -280,7 +275,11 @@ static int raid0_run (mddev_t *mddev)
 	mdk_rdev_t *rdev;
 	struct list_head *tmp;
 
-	printk("%s: setting max_sectors to %d, segment boundary to %d\n",
+	if (mddev->chunk_size == 0) {
+		printk(KERN_ERR "md/raid0: non-zero chunk size required.\n");
+		return -EINVAL;
+	}
+	printk(KERN_INFO "%s: setting max_sectors to %d, segment boundary to %d\n",
 	       mdname(mddev),
 	       mddev->chunk_size >> 9,
 	       (mddev->chunk_size>>1)-1);
@@ -361,7 +360,7 @@ static int raid0_run (mddev_t *mddev)
 	 * chunksize should be used in that case.
 	 */
 	{
-		int stripe = mddev->raid_disks * mddev->chunk_size / PAGE_CACHE_SIZE;
+		int stripe = mddev->raid_disks * mddev->chunk_size / PAGE_SIZE;
 		if (mddev->queue->backing_dev_info.ra_pages < 2* stripe)
 			mddev->queue->backing_dev_info.ra_pages = 2* stripe;
 	}
@@ -512,9 +511,10 @@ static void raid0_status (struct seq_file *seq, mddev_t *mddev)
 	return;
 }
 
-static mdk_personality_t raid0_personality=
+static struct mdk_personality raid0_personality=
 {
 	.name		= "raid0",
+	.level		= 0,
 	.owner		= THIS_MODULE,
 	.make_request	= raid0_make_request,
 	.run		= raid0_run,
@@ -524,15 +524,17 @@ static mdk_personality_t raid0_personality=
 
 static int __init raid0_init (void)
 {
-	return register_md_personality (RAID0, &raid0_personality);
+	return register_md_personality (&raid0_personality);
 }
 
 static void raid0_exit (void)
 {
-	unregister_md_personality (RAID0);
+	unregister_md_personality (&raid0_personality);
 }
 
 module_init(raid0_init);
 module_exit(raid0_exit);
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("md-personality-2"); /* RAID0 */
+MODULE_ALIAS("md-raid0");
+MODULE_ALIAS("md-level-0");
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 229d7b204297..a06ff91f27e2 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -47,10 +47,11 @@
  */
 #define	NR_RAID1_BIOS 256
 
-static mdk_personality_t raid1_personality;
 
 static void unplug_slaves(mddev_t *mddev);
 
+static void allow_barrier(conf_t *conf);
+static void lower_barrier(conf_t *conf);
 
 static void * r1bio_pool_alloc(gfp_t gfp_flags, void *data)
 {
@@ -59,10 +60,8 @@ static void * r1bio_pool_alloc(gfp_t gfp_flags, void *data)
 	int size = offsetof(r1bio_t, bios[pi->raid_disks]);
 
 	/* allocate a r1bio with room for raid_disks entries in the bios array */
-	r1_bio = kmalloc(size, gfp_flags);
-	if (r1_bio)
-		memset(r1_bio, 0, size);
-	else
+	r1_bio = kzalloc(size, gfp_flags);
+	if (!r1_bio)
 		unplug_slaves(pi->mddev);
 
 	return r1_bio;
@@ -104,15 +103,30 @@ static void * r1buf_pool_alloc(gfp_t gfp_flags, void *data)
 	}
 	/*
 	 * Allocate RESYNC_PAGES data pages and attach them to
-	 * the first bio;
+	 * the first bio.
+	 * If this is a user-requested check/repair, allocate
+	 * RESYNC_PAGES for each bio.
 	 */
-	bio = r1_bio->bios[0];
-	for (i = 0; i < RESYNC_PAGES; i++) {
-		page = alloc_page(gfp_flags);
-		if (unlikely(!page))
-			goto out_free_pages;
-
-		bio->bi_io_vec[i].bv_page = page;
+	if (test_bit(MD_RECOVERY_REQUESTED, &pi->mddev->recovery))
+		j = pi->raid_disks;
+	else
+		j = 1;
+	while(j--) {
+		bio = r1_bio->bios[j];
+		for (i = 0; i < RESYNC_PAGES; i++) {
+			page = alloc_page(gfp_flags);
+			if (unlikely(!page))
+				goto out_free_pages;
+
+			bio->bi_io_vec[i].bv_page = page;
+		}
+	}
+	/* If not user-requests, copy the page pointers to all bios */
+	if (!test_bit(MD_RECOVERY_REQUESTED, &pi->mddev->recovery)) {
+		for (i=0; i<RESYNC_PAGES ; i++)
+			for (j=1; j<pi->raid_disks; j++)
+				r1_bio->bios[j]->bi_io_vec[i].bv_page =
+					r1_bio->bios[0]->bi_io_vec[i].bv_page;
 	}
 
 	r1_bio->master_bio = NULL;
@@ -120,8 +134,10 @@ static void * r1buf_pool_alloc(gfp_t gfp_flags, void *data)
 	return r1_bio;
 
 out_free_pages:
-	for ( ; i > 0 ; i--)
-		__free_page(bio->bi_io_vec[i-1].bv_page);
+	for (i=0; i < RESYNC_PAGES ; i++)
+		for (j=0 ; j < pi->raid_disks; j++)
+			safe_put_page(r1_bio->bios[j]->bi_io_vec[i].bv_page);
+	j = -1;
 out_free_bio:
 	while ( ++j < pi->raid_disks )
 		bio_put(r1_bio->bios[j]);
@@ -132,14 +148,16 @@ out_free_bio:
 static void r1buf_pool_free(void *__r1_bio, void *data)
 {
 	struct pool_info *pi = data;
-	int i;
+	int i,j;
 	r1bio_t *r1bio = __r1_bio;
-	struct bio *bio = r1bio->bios[0];
 
-	for (i = 0; i < RESYNC_PAGES; i++) {
-		__free_page(bio->bi_io_vec[i].bv_page);
-		bio->bi_io_vec[i].bv_page = NULL;
-	}
+	for (i = 0; i < RESYNC_PAGES; i++)
+		for (j = pi->raid_disks; j-- ;) {
+			if (j == 0 ||
+			    r1bio->bios[j]->bi_io_vec[i].bv_page !=
+			    r1bio->bios[0]->bi_io_vec[i].bv_page)
+				safe_put_page(r1bio->bios[j]->bi_io_vec[i].bv_page);
+		}
 	for (i=0 ; i < pi->raid_disks; i++)
 		bio_put(r1bio->bios[i]);
 
@@ -152,7 +170,7 @@ static void put_all_bios(conf_t *conf, r1bio_t *r1_bio)
 
 	for (i = 0; i < conf->raid_disks; i++) {
 		struct bio **bio = r1_bio->bios + i;
-		if (*bio)
+		if (*bio && *bio != IO_BLOCKED)
 			bio_put(*bio);
 		*bio = NULL;
 	}
@@ -160,20 +178,13 @@ static void put_all_bios(conf_t *conf, r1bio_t *r1_bio)
 
 static inline void free_r1bio(r1bio_t *r1_bio)
 {
-	unsigned long flags;
-
 	conf_t *conf = mddev_to_conf(r1_bio->mddev);
 
 	/*
 	 * Wake up any possible resync thread that waits for the device
 	 * to go idle.
 	 */
-	spin_lock_irqsave(&conf->resync_lock, flags);
-	if (!--conf->nr_pending) {
-		wake_up(&conf->wait_idle);
-		wake_up(&conf->wait_resume);
-	}
-	spin_unlock_irqrestore(&conf->resync_lock, flags);
+	allow_barrier(conf);
 
 	put_all_bios(conf, r1_bio);
 	mempool_free(r1_bio, conf->r1bio_pool);
@@ -182,22 +193,17 @@ static inline void free_r1bio(r1bio_t *r1_bio)
 static inline void put_buf(r1bio_t *r1_bio)
 {
 	conf_t *conf = mddev_to_conf(r1_bio->mddev);
-	unsigned long flags;
+	int i;
 
-	mempool_free(r1_bio, conf->r1buf_pool);
+	for (i=0; i<conf->raid_disks; i++) {
+		struct bio *bio = r1_bio->bios[i];
+		if (bio->bi_end_io)
+			rdev_dec_pending(conf->mirrors[i].rdev, r1_bio->mddev);
+	}
 
-	spin_lock_irqsave(&conf->resync_lock, flags);
-	if (!conf->barrier)
-		BUG();
-	--conf->barrier;
-	wake_up(&conf->wait_resume);
-	wake_up(&conf->wait_idle);
+	mempool_free(r1_bio, conf->r1buf_pool);
 
-	if (!--conf->nr_pending) {
-		wake_up(&conf->wait_idle);
-		wake_up(&conf->wait_resume);
-	}
-	spin_unlock_irqrestore(&conf->resync_lock, flags);
+	lower_barrier(conf);
 }
 
 static void reschedule_retry(r1bio_t *r1_bio)
@@ -208,8 +214,10 @@ static void reschedule_retry(r1bio_t *r1_bio)
 
 	spin_lock_irqsave(&conf->device_lock, flags);
 	list_add(&r1_bio->retry_list, &conf->retry_list);
+	conf->nr_queued ++;
 	spin_unlock_irqrestore(&conf->device_lock, flags);
 
+	wake_up(&conf->wait_barrier);
 	md_wakeup_thread(mddev->thread);
 }
 
@@ -261,9 +269,9 @@ static int raid1_end_read_request(struct bio *bio, unsigned int bytes_done, int
 	/*
 	 * this branch is our 'one mirror IO has finished' event handler:
 	 */
-	if (!uptodate)
-		md_error(r1_bio->mddev, conf->mirrors[mirror].rdev);
-	else
+	update_head_pos(mirror, r1_bio);
+
+	if (uptodate || conf->working_disks <= 1) {
 		/*
 		 * Set R1BIO_Uptodate in our master bio, so that
 		 * we will return a good error code for to the higher
@@ -273,16 +281,11 @@ static int raid1_end_read_request(struct bio *bio, unsigned int bytes_done, int
 		 * user-side. So if something waits for IO, then it will
 		 * wait for the 'master' bio.
 		 */
-		set_bit(R1BIO_Uptodate, &r1_bio->state);
-
-	update_head_pos(mirror, r1_bio);
+		if (uptodate)
+			set_bit(R1BIO_Uptodate, &r1_bio->state);
 
-	/*
-	 * we have only one bio on the read side
-	 */
-	if (uptodate)
 		raid_end_bio_io(r1_bio);
-	else {
+	} else {
 		/*
 		 * oops, read error:
 		 */
@@ -378,7 +381,7 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int
 			/* free extra copy of the data pages */
 			int i = bio->bi_vcnt;
 			while (i--)
-				__free_page(bio->bi_io_vec[i].bv_page);
+				safe_put_page(bio->bi_io_vec[i].bv_page);
 		}
 		/* clear the bitmap if all writes complete successfully */
 		bitmap_endwrite(r1_bio->mddev->bitmap, r1_bio->sector,
@@ -433,11 +436,13 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio)
 		new_disk = 0;
 
 		for (rdev = rcu_dereference(conf->mirrors[new_disk].rdev);
+		     r1_bio->bios[new_disk] == IO_BLOCKED ||
 		     !rdev || !test_bit(In_sync, &rdev->flags)
 			     || test_bit(WriteMostly, &rdev->flags);
 		     rdev = rcu_dereference(conf->mirrors[++new_disk].rdev)) {
 
-			if (rdev && test_bit(In_sync, &rdev->flags))
+			if (rdev && test_bit(In_sync, &rdev->flags) &&
+				r1_bio->bios[new_disk] != IO_BLOCKED)
 				wonly_disk = new_disk;
 
 			if (new_disk == conf->raid_disks - 1) {
@@ -451,11 +456,13 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio)
 
 	/* make sure the disk is operational */
 	for (rdev = rcu_dereference(conf->mirrors[new_disk].rdev);
+	     r1_bio->bios[new_disk] == IO_BLOCKED ||
 	     !rdev || !test_bit(In_sync, &rdev->flags) ||
 		     test_bit(WriteMostly, &rdev->flags);
 	     rdev = rcu_dereference(conf->mirrors[new_disk].rdev)) {
 
-		if (rdev && test_bit(In_sync, &rdev->flags))
+		if (rdev && test_bit(In_sync, &rdev->flags) &&
+		    r1_bio->bios[new_disk] != IO_BLOCKED)
 			wonly_disk = new_disk;
 
 		if (new_disk <= 0)
@@ -492,7 +499,7 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio)
 
 		rdev = rcu_dereference(conf->mirrors[disk].rdev);
 
-		if (!rdev ||
+		if (!rdev || r1_bio->bios[disk] == IO_BLOCKED ||
 		    !test_bit(In_sync, &rdev->flags) ||
 		    test_bit(WriteMostly, &rdev->flags))
 			continue;
@@ -520,7 +527,7 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio)
 			/* cannot risk returning a device that failed
 			 * before we inc'ed nr_pending
 			 */
-			atomic_dec(&rdev->nr_pending);
+			rdev_dec_pending(rdev, conf->mddev);
 			goto retry;
 		}
 		conf->next_seq_sect = this_sector + sectors;
@@ -593,42 +600,119 @@ static int raid1_issue_flush(request_queue_t *q, struct gendisk *disk,
 	return ret;
 }
 
-/*
- * Throttle resync depth, so that we can both get proper overlapping of
- * requests, but are still able to handle normal requests quickly.
+/* Barriers....
+ * Sometimes we need to suspend IO while we do something else,
+ * either some resync/recovery, or reconfigure the array.
+ * To do this we raise a 'barrier'.
+ * The 'barrier' is a counter that can be raised multiple times
+ * to count how many activities are happening which preclude
+ * normal IO.
+ * We can only raise the barrier if there is no pending IO.
+ * i.e. if nr_pending == 0.
+ * We choose only to raise the barrier if no-one is waiting for the
+ * barrier to go down.  This means that as soon as an IO request
+ * is ready, no other operations which require a barrier will start
+ * until the IO request has had a chance.
+ *
+ * So: regular IO calls 'wait_barrier'.  When that returns there
+ *    is no backgroup IO happening,  It must arrange to call
+ *    allow_barrier when it has finished its IO.
+ * backgroup IO calls must call raise_barrier.  Once that returns
+ *    there is no normal IO happeing.  It must arrange to call
+ *    lower_barrier when the particular background IO completes.
  */
 #define RESYNC_DEPTH 32
 
-static void device_barrier(conf_t *conf, sector_t sect)
+static void raise_barrier(conf_t *conf)
 {
 	spin_lock_irq(&conf->resync_lock);
-	wait_event_lock_irq(conf->wait_idle, !waitqueue_active(&conf->wait_resume),
-			    conf->resync_lock, raid1_unplug(conf->mddev->queue));
-	
-	if (!conf->barrier++) {
-		wait_event_lock_irq(conf->wait_idle, !conf->nr_pending,
-				    conf->resync_lock, raid1_unplug(conf->mddev->queue));
-		if (conf->nr_pending)
-			BUG();
+
+	/* Wait until no block IO is waiting */
+	wait_event_lock_irq(conf->wait_barrier, !conf->nr_waiting,
+			    conf->resync_lock,
+			    raid1_unplug(conf->mddev->queue));
+
+	/* block any new IO from starting */
+	conf->barrier++;
+
+	/* No wait for all pending IO to complete */
+	wait_event_lock_irq(conf->wait_barrier,
+			    !conf->nr_pending && conf->barrier < RESYNC_DEPTH,
+			    conf->resync_lock,
+			    raid1_unplug(conf->mddev->queue));
+
+	spin_unlock_irq(&conf->resync_lock);
+}
+
+static void lower_barrier(conf_t *conf)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&conf->resync_lock, flags);
+	conf->barrier--;
+	spin_unlock_irqrestore(&conf->resync_lock, flags);
+	wake_up(&conf->wait_barrier);
+}
+
+static void wait_barrier(conf_t *conf)
+{
+	spin_lock_irq(&conf->resync_lock);
+	if (conf->barrier) {
+		conf->nr_waiting++;
+		wait_event_lock_irq(conf->wait_barrier, !conf->barrier,
+				    conf->resync_lock,
+				    raid1_unplug(conf->mddev->queue));
+		conf->nr_waiting--;
 	}
-	wait_event_lock_irq(conf->wait_resume, conf->barrier < RESYNC_DEPTH,
-			    conf->resync_lock, raid1_unplug(conf->mddev->queue));
-	conf->next_resync = sect;
+	conf->nr_pending++;
+	spin_unlock_irq(&conf->resync_lock);
+}
+
+static void allow_barrier(conf_t *conf)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&conf->resync_lock, flags);
+	conf->nr_pending--;
+	spin_unlock_irqrestore(&conf->resync_lock, flags);
+	wake_up(&conf->wait_barrier);
+}
+
+static void freeze_array(conf_t *conf)
+{
+	/* stop syncio and normal IO and wait for everything to
+	 * go quite.
+	 * We increment barrier and nr_waiting, and then
+	 * wait until barrier+nr_pending match nr_queued+2
+	 */
+	spin_lock_irq(&conf->resync_lock);
+	conf->barrier++;
+	conf->nr_waiting++;
+	wait_event_lock_irq(conf->wait_barrier,
+			    conf->barrier+conf->nr_pending == conf->nr_queued+2,
+			    conf->resync_lock,
+			    raid1_unplug(conf->mddev->queue));
+	spin_unlock_irq(&conf->resync_lock);
+}
+static void unfreeze_array(conf_t *conf)
+{
+	/* reverse the effect of the freeze */
+	spin_lock_irq(&conf->resync_lock);
+	conf->barrier--;
+	conf->nr_waiting--;
+	wake_up(&conf->wait_barrier);
 	spin_unlock_irq(&conf->resync_lock);
 }
 
+
 /* duplicate the data pages for behind I/O */
 static struct page **alloc_behind_pages(struct bio *bio)
 {
 	int i;
 	struct bio_vec *bvec;
-	struct page **pages = kmalloc(bio->bi_vcnt * sizeof(struct page *),
+	struct page **pages = kzalloc(bio->bi_vcnt * sizeof(struct page *),
 					GFP_NOIO);
 	if (unlikely(!pages))
 		goto do_sync_io;
 
-	memset(pages, 0, bio->bi_vcnt * sizeof(struct page *));
-
 	bio_for_each_segment(bvec, bio, i) {
 		pages[i] = alloc_page(GFP_NOIO);
 		if (unlikely(!pages[i]))
@@ -644,7 +728,7 @@ static struct page **alloc_behind_pages(struct bio *bio)
 do_sync_io:
 	if (pages)
 		for (i = 0; i < bio->bi_vcnt && pages[i]; i++)
-			__free_page(pages[i]);
+			put_page(pages[i]);
 	kfree(pages);
 	PRINTK("%dB behind alloc failed, doing sync I/O\n", bio->bi_size);
 	return NULL;
@@ -678,10 +762,7 @@ static int make_request(request_queue_t *q, struct bio * bio)
 	 */
 	md_write_start(mddev, bio); /* wait on superblock update early */
 
-	spin_lock_irq(&conf->resync_lock);
-	wait_event_lock_irq(conf->wait_resume, !conf->barrier, conf->resync_lock, );
-	conf->nr_pending++;
-	spin_unlock_irq(&conf->resync_lock);
+	wait_barrier(conf);
 
 	disk_stat_inc(mddev->gendisk, ios[rw]);
 	disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bio));
@@ -749,7 +830,7 @@ static int make_request(request_queue_t *q, struct bio * bio)
 		    !test_bit(Faulty, &rdev->flags)) {
 			atomic_inc(&rdev->nr_pending);
 			if (test_bit(Faulty, &rdev->flags)) {
-				atomic_dec(&rdev->nr_pending);
+				rdev_dec_pending(rdev, mddev);
 				r1_bio->bios[i] = NULL;
 			} else
 				r1_bio->bios[i] = bio;
@@ -909,13 +990,8 @@ static void print_conf(conf_t *conf)
 
 static void close_sync(conf_t *conf)
 {
-	spin_lock_irq(&conf->resync_lock);
-	wait_event_lock_irq(conf->wait_resume, !conf->barrier,
-			    conf->resync_lock, 	raid1_unplug(conf->mddev->queue));
-	spin_unlock_irq(&conf->resync_lock);
-
-	if (conf->barrier) BUG();
-	if (waitqueue_active(&conf->wait_idle)) BUG();
+	wait_barrier(conf);
+	allow_barrier(conf);
 
 	mempool_destroy(conf->r1buf_pool);
 	conf->r1buf_pool = NULL;
@@ -1015,28 +1091,27 @@ abort:
 
 static int end_sync_read(struct bio *bio, unsigned int bytes_done, int error)
 {
-	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
 	r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private);
-	conf_t *conf = mddev_to_conf(r1_bio->mddev);
+	int i;
 
 	if (bio->bi_size)
 		return 1;
 
-	if (r1_bio->bios[r1_bio->read_disk] != bio)
-		BUG();
-	update_head_pos(r1_bio->read_disk, r1_bio);
+	for (i=r1_bio->mddev->raid_disks; i--; )
+		if (r1_bio->bios[i] == bio)
+			break;
+	BUG_ON(i < 0);
+	update_head_pos(i, r1_bio);
 	/*
 	 * we have read a block, now it needs to be re-written,
 	 * or re-read if the read failed.
 	 * We don't do much here, just schedule handling by raid1d
 	 */
-	if (!uptodate) {
-		md_error(r1_bio->mddev,
-			 conf->mirrors[r1_bio->read_disk].rdev);
-	} else
+	if (test_bit(BIO_UPTODATE, &bio->bi_flags))
 		set_bit(R1BIO_Uptodate, &r1_bio->state);
-	rdev_dec_pending(conf->mirrors[r1_bio->read_disk].rdev, conf->mddev);
-	reschedule_retry(r1_bio);
+
+	if (atomic_dec_and_test(&r1_bio->remaining))
+		reschedule_retry(r1_bio);
 	return 0;
 }
 
@@ -1066,7 +1141,6 @@ static int end_sync_write(struct bio *bio, unsigned int bytes_done, int error)
 		md_done_sync(mddev, r1_bio->sectors, uptodate);
 		put_buf(r1_bio);
 	}
-	rdev_dec_pending(conf->mirrors[mirror].rdev, mddev);
 	return 0;
 }
 
@@ -1079,34 +1153,173 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio)
 
 	bio = r1_bio->bios[r1_bio->read_disk];
 
-/*
-	if (r1_bio->sector == 0) printk("First sync write startss\n");
-*/
-	/*
-	 * schedule writes
-	 */
+
+	if (test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) {
+		/* We have read all readable devices.  If we haven't
+		 * got the block, then there is no hope left.
+		 * If we have, then we want to do a comparison
+		 * and skip the write if everything is the same.
+		 * If any blocks failed to read, then we need to
+		 * attempt an over-write
+		 */
+		int primary;
+		if (!test_bit(R1BIO_Uptodate, &r1_bio->state)) {
+			for (i=0; i<mddev->raid_disks; i++)
+				if (r1_bio->bios[i]->bi_end_io == end_sync_read)
+					md_error(mddev, conf->mirrors[i].rdev);
+
+			md_done_sync(mddev, r1_bio->sectors, 1);
+			put_buf(r1_bio);
+			return;
+		}
+		for (primary=0; primary<mddev->raid_disks; primary++)
+			if (r1_bio->bios[primary]->bi_end_io == end_sync_read &&
+			    test_bit(BIO_UPTODATE, &r1_bio->bios[primary]->bi_flags)) {
+				r1_bio->bios[primary]->bi_end_io = NULL;
+				rdev_dec_pending(conf->mirrors[primary].rdev, mddev);
+				break;
+			}
+		r1_bio->read_disk = primary;
+		for (i=0; i<mddev->raid_disks; i++)
+			if (r1_bio->bios[i]->bi_end_io == end_sync_read &&
+			    test_bit(BIO_UPTODATE, &r1_bio->bios[i]->bi_flags)) {
+				int j;
+				int vcnt = r1_bio->sectors >> (PAGE_SHIFT- 9);
+				struct bio *pbio = r1_bio->bios[primary];
+				struct bio *sbio = r1_bio->bios[i];
+				for (j = vcnt; j-- ; )
+					if (memcmp(page_address(pbio->bi_io_vec[j].bv_page),
+						   page_address(sbio->bi_io_vec[j].bv_page),
+						   PAGE_SIZE))
+						break;
+				if (j >= 0)
+					mddev->resync_mismatches += r1_bio->sectors;
+				if (j < 0 || test_bit(MD_RECOVERY_CHECK, &mddev->recovery)) {
+					sbio->bi_end_io = NULL;
+					rdev_dec_pending(conf->mirrors[i].rdev, mddev);
+				} else {
+					/* fixup the bio for reuse */
+					sbio->bi_vcnt = vcnt;
+					sbio->bi_size = r1_bio->sectors << 9;
+					sbio->bi_idx = 0;
+					sbio->bi_phys_segments = 0;
+					sbio->bi_hw_segments = 0;
+					sbio->bi_hw_front_size = 0;
+					sbio->bi_hw_back_size = 0;
+					sbio->bi_flags &= ~(BIO_POOL_MASK - 1);
+					sbio->bi_flags |= 1 << BIO_UPTODATE;
+					sbio->bi_next = NULL;
+					sbio->bi_sector = r1_bio->sector +
+						conf->mirrors[i].rdev->data_offset;
+					sbio->bi_bdev = conf->mirrors[i].rdev->bdev;
+				}
+			}
+	}
 	if (!test_bit(R1BIO_Uptodate, &r1_bio->state)) {
-		/*
-		 * There is no point trying a read-for-reconstruct as
-		 * reconstruct is about to be aborted
+		/* ouch - failed to read all of that.
+		 * Try some synchronous reads of other devices to get
+		 * good data, much like with normal read errors.  Only
+		 * read into the pages we already have so they we don't
+		 * need to re-issue the read request.
+		 * We don't need to freeze the array, because being in an
+		 * active sync request, there is no normal IO, and
+		 * no overlapping syncs.
 		 */
-		char b[BDEVNAME_SIZE];
-		printk(KERN_ALERT "raid1: %s: unrecoverable I/O read error"
-			" for block %llu\n",
-			bdevname(bio->bi_bdev,b), 
-			(unsigned long long)r1_bio->sector);
-		md_done_sync(mddev, r1_bio->sectors, 0);
-		put_buf(r1_bio);
-		return;
+		sector_t sect = r1_bio->sector;
+		int sectors = r1_bio->sectors;
+		int idx = 0;
+
+		while(sectors) {
+			int s = sectors;
+			int d = r1_bio->read_disk;
+			int success = 0;
+			mdk_rdev_t *rdev;
+
+			if (s > (PAGE_SIZE>>9))
+				s = PAGE_SIZE >> 9;
+			do {
+				if (r1_bio->bios[d]->bi_end_io == end_sync_read) {
+					rdev = conf->mirrors[d].rdev;
+					if (sync_page_io(rdev->bdev,
+							 sect + rdev->data_offset,
+							 s<<9,
+							 bio->bi_io_vec[idx].bv_page,
+							 READ)) {
+						success = 1;
+						break;
+					}
+				}
+				d++;
+				if (d == conf->raid_disks)
+					d = 0;
+			} while (!success && d != r1_bio->read_disk);
+
+			if (success) {
+				int start = d;
+				/* write it back and re-read */
+				set_bit(R1BIO_Uptodate, &r1_bio->state);
+				while (d != r1_bio->read_disk) {
+					if (d == 0)
+						d = conf->raid_disks;
+					d--;
+					if (r1_bio->bios[d]->bi_end_io != end_sync_read)
+						continue;
+					rdev = conf->mirrors[d].rdev;
+					atomic_add(s, &rdev->corrected_errors);
+					if (sync_page_io(rdev->bdev,
+							 sect + rdev->data_offset,
+							 s<<9,
+							 bio->bi_io_vec[idx].bv_page,
+							 WRITE) == 0)
+						md_error(mddev, rdev);
+				}
+				d = start;
+				while (d != r1_bio->read_disk) {
+					if (d == 0)
+						d = conf->raid_disks;
+					d--;
+					if (r1_bio->bios[d]->bi_end_io != end_sync_read)
+						continue;
+					rdev = conf->mirrors[d].rdev;
+					if (sync_page_io(rdev->bdev,
+							 sect + rdev->data_offset,
+							 s<<9,
+							 bio->bi_io_vec[idx].bv_page,
+							 READ) == 0)
+						md_error(mddev, rdev);
+				}
+			} else {
+				char b[BDEVNAME_SIZE];
+				/* Cannot read from anywhere, array is toast */
+				md_error(mddev, conf->mirrors[r1_bio->read_disk].rdev);
+				printk(KERN_ALERT "raid1: %s: unrecoverable I/O read error"
+				       " for block %llu\n",
+				       bdevname(bio->bi_bdev,b),
+				       (unsigned long long)r1_bio->sector);
+				md_done_sync(mddev, r1_bio->sectors, 0);
+				put_buf(r1_bio);
+				return;
+			}
+			sectors -= s;
+			sect += s;
+			idx ++;
+		}
 	}
 
+	/*
+	 * schedule writes
+	 */
 	atomic_set(&r1_bio->remaining, 1);
 	for (i = 0; i < disks ; i++) {
 		wbio = r1_bio->bios[i];
-		if (wbio->bi_end_io != end_sync_write)
+		if (wbio->bi_end_io == NULL ||
+		    (wbio->bi_end_io == end_sync_read &&
+		     (i == r1_bio->read_disk ||
+		      !test_bit(MD_RECOVERY_SYNC, &mddev->recovery))))
 			continue;
 
-		atomic_inc(&conf->mirrors[i].rdev->nr_pending);
+		wbio->bi_rw = WRITE;
+		wbio->bi_end_io = end_sync_write;
 		atomic_inc(&r1_bio->remaining);
 		md_sync_acct(conf->mirrors[i].rdev->bdev, wbio->bi_size >> 9);
 
@@ -1167,6 +1380,7 @@ static void raid1d(mddev_t *mddev)
 			break;
 		r1_bio = list_entry(head->prev, r1bio_t, retry_list);
 		list_del(head->prev);
+		conf->nr_queued--;
 		spin_unlock_irqrestore(&conf->device_lock, flags);
 
 		mddev = r1_bio->mddev;
@@ -1206,6 +1420,86 @@ static void raid1d(mddev_t *mddev)
 				}
 		} else {
 			int disk;
+
+			/* we got a read error. Maybe the drive is bad.  Maybe just
+			 * the block and we can fix it.
+			 * We freeze all other IO, and try reading the block from
+			 * other devices.  When we find one, we re-write
+			 * and check it that fixes the read error.
+			 * This is all done synchronously while the array is
+			 * frozen
+			 */
+			sector_t sect = r1_bio->sector;
+			int sectors = r1_bio->sectors;
+			freeze_array(conf);
+			if (mddev->ro == 0) while(sectors) {
+				int s = sectors;
+				int d = r1_bio->read_disk;
+				int success = 0;
+
+				if (s > (PAGE_SIZE>>9))
+					s = PAGE_SIZE >> 9;
+
+				do {
+					rdev = conf->mirrors[d].rdev;
+					if (rdev &&
+					    test_bit(In_sync, &rdev->flags) &&
+					    sync_page_io(rdev->bdev,
+							 sect + rdev->data_offset,
+							 s<<9,
+							 conf->tmppage, READ))
+						success = 1;
+					else {
+						d++;
+						if (d == conf->raid_disks)
+							d = 0;
+					}
+				} while (!success && d != r1_bio->read_disk);
+
+				if (success) {
+					/* write it back and re-read */
+					int start = d;
+					while (d != r1_bio->read_disk) {
+						if (d==0)
+							d = conf->raid_disks;
+						d--;
+						rdev = conf->mirrors[d].rdev;
+						atomic_add(s, &rdev->corrected_errors);
+						if (rdev &&
+						    test_bit(In_sync, &rdev->flags)) {
+							if (sync_page_io(rdev->bdev,
+									 sect + rdev->data_offset,
+									 s<<9, conf->tmppage, WRITE) == 0)
+								/* Well, this device is dead */
+								md_error(mddev, rdev);
+						}
+					}
+					d = start;
+					while (d != r1_bio->read_disk) {
+						if (d==0)
+							d = conf->raid_disks;
+						d--;
+						rdev = conf->mirrors[d].rdev;
+						if (rdev &&
+						    test_bit(In_sync, &rdev->flags)) {
+							if (sync_page_io(rdev->bdev,
+									 sect + rdev->data_offset,
+									 s<<9, conf->tmppage, READ) == 0)
+								/* Well, this device is dead */
+								md_error(mddev, rdev);
+						}
+					}
+				} else {
+					/* Cannot read from anywhere -- bye bye array */
+					md_error(mddev, conf->mirrors[r1_bio->read_disk].rdev);
+					break;
+				}
+				sectors -= s;
+				sect += s;
+			}
+
+			unfreeze_array(conf);
+
 			bio = r1_bio->bios[r1_bio->read_disk];
 			if ((disk=read_balance(conf, r1_bio)) == -1) {
 				printk(KERN_ALERT "raid1: %s: unrecoverable I/O"
@@ -1214,7 +1508,8 @@ static void raid1d(mddev_t *mddev)
 				       (unsigned long long)r1_bio->sector);
 				raid_end_bio_io(r1_bio);
 			} else {
-				r1_bio->bios[r1_bio->read_disk] = NULL;
+				r1_bio->bios[r1_bio->read_disk] =
+					mddev->ro ? IO_BLOCKED : NULL;
 				r1_bio->read_disk = disk;
 				bio_put(bio);
 				bio = bio_clone(r1_bio->master_bio, GFP_NOIO);
@@ -1269,14 +1564,13 @@ static int init_resync(conf_t *conf)
 static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster)
 {
 	conf_t *conf = mddev_to_conf(mddev);
-	mirror_info_t *mirror;
 	r1bio_t *r1_bio;
 	struct bio *bio;
 	sector_t max_sector, nr_sectors;
-	int disk;
+	int disk = -1;
 	int i;
-	int wonly;
-	int write_targets = 0;
+	int wonly = -1;
+	int write_targets = 0, read_targets = 0;
 	int sync_blocks;
 	int still_degraded = 0;
 
@@ -1317,55 +1611,35 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
 		return sync_blocks;
 	}
 	/*
-	 * If there is non-resync activity waiting for us then
-	 * put in a delay to throttle resync.
+	 * If there is non-resync activity waiting for a turn,
+	 * and resync is going fast enough,
+	 * then let it though before starting on this new sync request.
 	 */
-	if (!go_faster && waitqueue_active(&conf->wait_resume))
+	if (!go_faster && conf->nr_waiting)
 		msleep_interruptible(1000);
-	device_barrier(conf, sector_nr + RESYNC_SECTORS);
-
-	/*
-	 * If reconstructing, and >1 working disc,
-	 * could dedicate one to rebuild and others to
-	 * service read requests ..
-	 */
-	disk = conf->last_used;
-	/* make sure disk is operational */
-	wonly = disk;
-	while (conf->mirrors[disk].rdev == NULL ||
-	       !test_bit(In_sync, &conf->mirrors[disk].rdev->flags) ||
-	       test_bit(WriteMostly, &conf->mirrors[disk].rdev->flags)
-		) {
-		if (conf->mirrors[disk].rdev  &&
-		    test_bit(In_sync, &conf->mirrors[disk].rdev->flags))
-			wonly = disk;
-		if (disk <= 0)
-			disk = conf->raid_disks;
-		disk--;
-		if (disk == conf->last_used) {
-			disk = wonly;
-			break;
-		}
-	}
-	conf->last_used = disk;
-	atomic_inc(&conf->mirrors[disk].rdev->nr_pending);
 
+	raise_barrier(conf);
 
-	mirror = conf->mirrors + disk;
+	conf->next_resync = sector_nr;
 
 	r1_bio = mempool_alloc(conf->r1buf_pool, GFP_NOIO);
-
-	spin_lock_irq(&conf->resync_lock);
-	conf->nr_pending++;
-	spin_unlock_irq(&conf->resync_lock);
+	rcu_read_lock();
+	/*
+	 * If we get a correctably read error during resync or recovery,
+	 * we might want to read from a different device.  So we
+	 * flag all drives that could conceivably be read from for READ,
+	 * and any others (which will be non-In_sync devices) for WRITE.
+	 * If a read fails, we try reading from something else for which READ
+	 * is OK.
+	 */
 
 	r1_bio->mddev = mddev;
 	r1_bio->sector = sector_nr;
 	r1_bio->state = 0;
 	set_bit(R1BIO_IsSync, &r1_bio->state);
-	r1_bio->read_disk = disk;
 
 	for (i=0; i < conf->raid_disks; i++) {
+		mdk_rdev_t *rdev;
 		bio = r1_bio->bios[i];
 
 		/* take from bio_init */
@@ -1380,35 +1654,49 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
 		bio->bi_end_io = NULL;
 		bio->bi_private = NULL;
 
-		if (i == disk) {
-			bio->bi_rw = READ;
-			bio->bi_end_io = end_sync_read;
-		} else if (conf->mirrors[i].rdev == NULL ||
-			   test_bit(Faulty, &conf->mirrors[i].rdev->flags)) {
+		rdev = rcu_dereference(conf->mirrors[i].rdev);
+		if (rdev == NULL ||
+			   test_bit(Faulty, &rdev->flags)) {
 			still_degraded = 1;
 			continue;
-		} else if (!test_bit(In_sync, &conf->mirrors[i].rdev->flags) ||
-			   sector_nr + RESYNC_SECTORS > mddev->recovery_cp   ||
-			   test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) {
+		} else if (!test_bit(In_sync, &rdev->flags)) {
 			bio->bi_rw = WRITE;
 			bio->bi_end_io = end_sync_write;
 			write_targets ++;
-		} else
-			/* no need to read or write here */
-			continue;
-		bio->bi_sector = sector_nr + conf->mirrors[i].rdev->data_offset;
-		bio->bi_bdev = conf->mirrors[i].rdev->bdev;
+		} else {
+			/* may need to read from here */
+			bio->bi_rw = READ;
+			bio->bi_end_io = end_sync_read;
+			if (test_bit(WriteMostly, &rdev->flags)) {
+				if (wonly < 0)
+					wonly = i;
+			} else {
+				if (disk < 0)
+					disk = i;
+			}
+			read_targets++;
+		}
+		atomic_inc(&rdev->nr_pending);
+		bio->bi_sector = sector_nr + rdev->data_offset;
+		bio->bi_bdev = rdev->bdev;
 		bio->bi_private = r1_bio;
 	}
+	rcu_read_unlock();
+	if (disk < 0)
+		disk = wonly;
+	r1_bio->read_disk = disk;
+
+	if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) && read_targets > 0)
+		/* extra read targets are also write targets */
+		write_targets += read_targets-1;
 
-	if (write_targets == 0) {
+	if (write_targets == 0 || read_targets == 0) {
 		/* There is nowhere to write, so all non-sync
 		 * drives must be failed - so we are finished
 		 */
 		sector_t rv = max_sector - sector_nr;
 		*skipped = 1;
 		put_buf(r1_bio);
-		rdev_dec_pending(conf->mirrors[disk].rdev, mddev);
 		return rv;
 	}
 
@@ -1436,10 +1724,10 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
 		for (i=0 ; i < conf->raid_disks; i++) {
 			bio = r1_bio->bios[i];
 			if (bio->bi_end_io) {
-				page = r1_bio->bios[0]->bi_io_vec[bio->bi_vcnt].bv_page;
+				page = bio->bi_io_vec[bio->bi_vcnt].bv_page;
 				if (bio_add_page(bio, page, len, 0) == 0) {
 					/* stop here */
-					r1_bio->bios[0]->bi_io_vec[bio->bi_vcnt].bv_page = page;
+					bio->bi_io_vec[bio->bi_vcnt].bv_page = page;
 					while (i > 0) {
 						i--;
 						bio = r1_bio->bios[i];
@@ -1459,12 +1747,28 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
 		sync_blocks -= (len>>9);
 	} while (r1_bio->bios[disk]->bi_vcnt < RESYNC_PAGES);
  bio_full:
-	bio = r1_bio->bios[disk];
 	r1_bio->sectors = nr_sectors;
 
-	md_sync_acct(mirror->rdev->bdev, nr_sectors);
+	/* For a user-requested sync, we read all readable devices and do a
+	 * compare
+	 */
+	if (test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) {
+		atomic_set(&r1_bio->remaining, read_targets);
+		for (i=0; i<conf->raid_disks; i++) {
+			bio = r1_bio->bios[i];
+			if (bio->bi_end_io == end_sync_read) {
+				md_sync_acct(conf->mirrors[i].rdev->bdev, nr_sectors);
+				generic_make_request(bio);
+			}
+		}
+	} else {
+		atomic_set(&r1_bio->remaining, 1);
+		bio = r1_bio->bios[r1_bio->read_disk];
+		md_sync_acct(conf->mirrors[r1_bio->read_disk].rdev->bdev,
+			     nr_sectors);
+		generic_make_request(bio);
 
-	generic_make_request(bio);
+	}
 
 	return nr_sectors;
 }
@@ -1487,18 +1791,19 @@ static int run(mddev_t *mddev)
 	 * bookkeeping area. [whatever we allocate in run(),
 	 * should be freed in stop()]
 	 */
-	conf = kmalloc(sizeof(conf_t), GFP_KERNEL);
+	conf = kzalloc(sizeof(conf_t), GFP_KERNEL);
 	mddev->private = conf;
 	if (!conf)
 		goto out_no_mem;
 
-	memset(conf, 0, sizeof(*conf));
-	conf->mirrors = kmalloc(sizeof(struct mirror_info)*mddev->raid_disks, 
+	conf->mirrors = kzalloc(sizeof(struct mirror_info)*mddev->raid_disks,
 				 GFP_KERNEL);
 	if (!conf->mirrors)
 		goto out_no_mem;
 
-	memset(conf->mirrors, 0, sizeof(struct mirror_info)*mddev->raid_disks);
+	conf->tmppage = alloc_page(GFP_KERNEL);
+	if (!conf->tmppage)
+		goto out_no_mem;
 
 	conf->poolinfo = kmalloc(sizeof(*conf->poolinfo), GFP_KERNEL);
 	if (!conf->poolinfo)
@@ -1542,8 +1847,7 @@ static int run(mddev_t *mddev)
 		mddev->recovery_cp = MaxSector;
 
 	spin_lock_init(&conf->resync_lock);
-	init_waitqueue_head(&conf->wait_idle);
-	init_waitqueue_head(&conf->wait_resume);
+	init_waitqueue_head(&conf->wait_barrier);
 
 	bio_list_init(&conf->pending_bio_list);
 	bio_list_init(&conf->flushing_bio_list);
@@ -1583,7 +1887,6 @@ static int run(mddev_t *mddev)
 		       mdname(mddev));
 		goto out_free_conf;
 	}
-	if (mddev->bitmap) mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
 
 	printk(KERN_INFO 
 		"raid1: raid set %s active with %d out of %d mirrors\n",
@@ -1608,6 +1911,7 @@ out_free_conf:
 		if (conf->r1bio_pool)
 			mempool_destroy(conf->r1bio_pool);
 		kfree(conf->mirrors);
+		safe_put_page(conf->tmppage);
 		kfree(conf->poolinfo);
 		kfree(conf);
 		mddev->private = NULL;
@@ -1706,19 +2010,14 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks)
 		kfree(newpoolinfo);
 		return -ENOMEM;
 	}
-	newmirrors = kmalloc(sizeof(struct mirror_info) * raid_disks, GFP_KERNEL);
+	newmirrors = kzalloc(sizeof(struct mirror_info) * raid_disks, GFP_KERNEL);
 	if (!newmirrors) {
 		kfree(newpoolinfo);
 		mempool_destroy(newpool);
 		return -ENOMEM;
 	}
-	memset(newmirrors, 0, sizeof(struct mirror_info)*raid_disks);
 
-	spin_lock_irq(&conf->resync_lock);
-	conf->barrier++;
-	wait_event_lock_irq(conf->wait_idle, !conf->nr_pending,
-			    conf->resync_lock, raid1_unplug(mddev->queue));
-	spin_unlock_irq(&conf->resync_lock);
+	raise_barrier(conf);
 
 	/* ok, everything is stopped */
 	oldpool = conf->r1bio_pool;
@@ -1738,12 +2037,7 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks)
 	conf->raid_disks = mddev->raid_disks = raid_disks;
 
 	conf->last_used = 0; /* just make sure it is in-range */
-	spin_lock_irq(&conf->resync_lock);
-	conf->barrier--;
-	spin_unlock_irq(&conf->resync_lock);
-	wake_up(&conf->wait_resume);
-	wake_up(&conf->wait_idle);
-
+	lower_barrier(conf);
 
 	set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
 	md_wakeup_thread(mddev->thread);
@@ -1758,33 +2052,19 @@ static void raid1_quiesce(mddev_t *mddev, int state)
 
 	switch(state) {
 	case 1:
-		spin_lock_irq(&conf->resync_lock);
-		conf->barrier++;
-		wait_event_lock_irq(conf->wait_idle, !conf->nr_pending,
-				    conf->resync_lock, raid1_unplug(mddev->queue));
-		spin_unlock_irq(&conf->resync_lock);
+		raise_barrier(conf);
 		break;
 	case 0:
-		spin_lock_irq(&conf->resync_lock);
-		conf->barrier--;
-		spin_unlock_irq(&conf->resync_lock);
-		wake_up(&conf->wait_resume);
-		wake_up(&conf->wait_idle);
+		lower_barrier(conf);
 		break;
 	}
-	if (mddev->thread) {
-		if (mddev->bitmap)
-			mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
-		else
-			mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT;
-		md_wakeup_thread(mddev->thread);
-	}
 }
 
 
-static mdk_personality_t raid1_personality =
+static struct mdk_personality raid1_personality =
 {
 	.name		= "raid1",
+	.level		= 1,
 	.owner		= THIS_MODULE,
 	.make_request	= make_request,
 	.run		= run,
@@ -1802,15 +2082,17 @@ static mdk_personality_t raid1_personality =
 
 static int __init raid_init(void)
 {
-	return register_md_personality(RAID1, &raid1_personality);
+	return register_md_personality(&raid1_personality);
 }
 
 static void raid_exit(void)
 {
-	unregister_md_personality(RAID1);
+	unregister_md_personality(&raid1_personality);
 }
 
 module_init(raid_init);
 module_exit(raid_exit);
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("md-personality-3"); /* RAID1 */
+MODULE_ALIAS("md-raid1");
+MODULE_ALIAS("md-level-1");
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 713dc9c2c730..9e658e519a27 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -18,7 +18,9 @@
  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include "dm-bio-list.h"
 #include <linux/raid/raid10.h>
+#include <linux/raid/bitmap.h>
 
 /*
  * RAID10 provides a combination of RAID0 and RAID1 functionality.
@@ -47,6 +49,9 @@
 
 static void unplug_slaves(mddev_t *mddev);
 
+static void allow_barrier(conf_t *conf);
+static void lower_barrier(conf_t *conf);
+
 static void * r10bio_pool_alloc(gfp_t gfp_flags, void *data)
 {
 	conf_t *conf = data;
@@ -54,10 +59,8 @@ static void * r10bio_pool_alloc(gfp_t gfp_flags, void *data)
 	int size = offsetof(struct r10bio_s, devs[conf->copies]);
 
 	/* allocate a r10bio with room for raid_disks entries in the bios array */
-	r10_bio = kmalloc(size, gfp_flags);
-	if (r10_bio)
-		memset(r10_bio, 0, size);
-	else
+	r10_bio = kzalloc(size, gfp_flags);
+	if (!r10_bio)
 		unplug_slaves(conf->mddev);
 
 	return r10_bio;
@@ -129,10 +132,10 @@ static void * r10buf_pool_alloc(gfp_t gfp_flags, void *data)
 
 out_free_pages:
 	for ( ; i > 0 ; i--)
-		__free_page(bio->bi_io_vec[i-1].bv_page);
+		safe_put_page(bio->bi_io_vec[i-1].bv_page);
 	while (j--)
 		for (i = 0; i < RESYNC_PAGES ; i++)
-			__free_page(r10_bio->devs[j].bio->bi_io_vec[i].bv_page);
+			safe_put_page(r10_bio->devs[j].bio->bi_io_vec[i].bv_page);
 	j = -1;
 out_free_bio:
 	while ( ++j < nalloc )
@@ -152,7 +155,7 @@ static void r10buf_pool_free(void *__r10_bio, void *data)
 		struct bio *bio = r10bio->devs[j].bio;
 		if (bio) {
 			for (i = 0; i < RESYNC_PAGES; i++) {
-				__free_page(bio->bi_io_vec[i].bv_page);
+				safe_put_page(bio->bi_io_vec[i].bv_page);
 				bio->bi_io_vec[i].bv_page = NULL;
 			}
 			bio_put(bio);
@@ -167,7 +170,7 @@ static void put_all_bios(conf_t *conf, r10bio_t *r10_bio)
 
 	for (i = 0; i < conf->copies; i++) {
 		struct bio **bio = & r10_bio->devs[i].bio;
-		if (*bio)
+		if (*bio && *bio != IO_BLOCKED)
 			bio_put(*bio);
 		*bio = NULL;
 	}
@@ -175,20 +178,13 @@ static void put_all_bios(conf_t *conf, r10bio_t *r10_bio)
 
 static inline void free_r10bio(r10bio_t *r10_bio)
 {
-	unsigned long flags;
-
 	conf_t *conf = mddev_to_conf(r10_bio->mddev);
 
 	/*
 	 * Wake up any possible resync thread that waits for the device
 	 * to go idle.
 	 */
-	spin_lock_irqsave(&conf->resync_lock, flags);
-	if (!--conf->nr_pending) {
-		wake_up(&conf->wait_idle);
-		wake_up(&conf->wait_resume);
-	}
-	spin_unlock_irqrestore(&conf->resync_lock, flags);
+	allow_barrier(conf);
 
 	put_all_bios(conf, r10_bio);
 	mempool_free(r10_bio, conf->r10bio_pool);
@@ -197,22 +193,10 @@ static inline void free_r10bio(r10bio_t *r10_bio)
 static inline void put_buf(r10bio_t *r10_bio)
 {
 	conf_t *conf = mddev_to_conf(r10_bio->mddev);
-	unsigned long flags;
 
 	mempool_free(r10_bio, conf->r10buf_pool);
 
-	spin_lock_irqsave(&conf->resync_lock, flags);
-	if (!conf->barrier)
-		BUG();
-	--conf->barrier;
-	wake_up(&conf->wait_resume);
-	wake_up(&conf->wait_idle);
-
-	if (!--conf->nr_pending) {
-		wake_up(&conf->wait_idle);
-		wake_up(&conf->wait_resume);
-	}
-	spin_unlock_irqrestore(&conf->resync_lock, flags);
+	lower_barrier(conf);
 }
 
 static void reschedule_retry(r10bio_t *r10_bio)
@@ -223,6 +207,7 @@ static void reschedule_retry(r10bio_t *r10_bio)
 
 	spin_lock_irqsave(&conf->device_lock, flags);
 	list_add(&r10_bio->retry_list, &conf->retry_list);
+	conf->nr_queued ++;
 	spin_unlock_irqrestore(&conf->device_lock, flags);
 
 	md_wakeup_thread(mddev->thread);
@@ -268,9 +253,9 @@ static int raid10_end_read_request(struct bio *bio, unsigned int bytes_done, int
 	/*
 	 * this branch is our 'one mirror IO has finished' event handler:
 	 */
-	if (!uptodate)
-		md_error(r10_bio->mddev, conf->mirrors[dev].rdev);
-	else
+	update_head_pos(slot, r10_bio);
+
+	if (uptodate) {
 		/*
 		 * Set R10BIO_Uptodate in our master bio, so that
 		 * we will return a good error code to the higher
@@ -281,15 +266,8 @@ static int raid10_end_read_request(struct bio *bio, unsigned int bytes_done, int
 		 * wait for the 'master' bio.
 		 */
 		set_bit(R10BIO_Uptodate, &r10_bio->state);
-
-	update_head_pos(slot, r10_bio);
-
-	/*
-	 * we have only one bio on the read side
-	 */
-	if (uptodate)
 		raid_end_bio_io(r10_bio);
-	else {
+	} else {
 		/*
 		 * oops, read error:
 		 */
@@ -322,9 +300,11 @@ static int raid10_end_write_request(struct bio *bio, unsigned int bytes_done, in
 	/*
 	 * this branch is our 'one mirror IO has finished' event handler:
 	 */
-	if (!uptodate)
+	if (!uptodate) {
 		md_error(r10_bio->mddev, conf->mirrors[dev].rdev);
-	else
+		/* an I/O failed, we can't clear the bitmap */
+		set_bit(R10BIO_Degraded, &r10_bio->state);
+	} else
 		/*
 		 * Set R10BIO_Uptodate in our master bio, so that
 		 * we will return a good error code for to the higher
@@ -344,6 +324,11 @@ static int raid10_end_write_request(struct bio *bio, unsigned int bytes_done, in
 	 * already.
 	 */
 	if (atomic_dec_and_test(&r10_bio->remaining)) {
+		/* clear the bitmap if all writes complete successfully */
+		bitmap_endwrite(r10_bio->mddev->bitmap, r10_bio->sector,
+				r10_bio->sectors,
+				!test_bit(R10BIO_Degraded, &r10_bio->state),
+				0);
 		md_write_end(r10_bio->mddev);
 		raid_end_bio_io(r10_bio);
 	}
@@ -502,8 +487,9 @@ static int read_balance(conf_t *conf, r10bio_t *r10_bio)
 	rcu_read_lock();
 	/*
 	 * Check if we can balance. We can balance on the whole
-	 * device if no resync is going on, or below the resync window.
-	 * We take the first readable disk when above the resync window.
+	 * device if no resync is going on (recovery is ok), or below
+	 * the resync window. We take the first readable disk when
+	 * above the resync window.
 	 */
 	if (conf->mddev->recovery_cp < MaxSector
 	    && (this_sector + sectors >= conf->next_resync)) {
@@ -512,6 +498,7 @@ static int read_balance(conf_t *conf, r10bio_t *r10_bio)
 		disk = r10_bio->devs[slot].devnum;
 
 		while ((rdev = rcu_dereference(conf->mirrors[disk].rdev)) == NULL ||
+		       r10_bio->devs[slot].bio == IO_BLOCKED ||
 		       !test_bit(In_sync, &rdev->flags)) {
 			slot++;
 			if (slot == conf->copies) {
@@ -529,6 +516,7 @@ static int read_balance(conf_t *conf, r10bio_t *r10_bio)
 	slot = 0;
 	disk = r10_bio->devs[slot].devnum;
 	while ((rdev=rcu_dereference(conf->mirrors[disk].rdev)) == NULL ||
+	       r10_bio->devs[slot].bio == IO_BLOCKED ||
 	       !test_bit(In_sync, &rdev->flags)) {
 		slot ++;
 		if (slot == conf->copies) {
@@ -549,6 +537,7 @@ static int read_balance(conf_t *conf, r10bio_t *r10_bio)
 
 
 		if ((rdev=rcu_dereference(conf->mirrors[ndisk].rdev)) == NULL ||
+		    r10_bio->devs[nslot].bio == IO_BLOCKED ||
 		    !test_bit(In_sync, &rdev->flags))
 			continue;
 
@@ -607,7 +596,10 @@ static void unplug_slaves(mddev_t *mddev)
 
 static void raid10_unplug(request_queue_t *q)
 {
+	mddev_t *mddev = q->queuedata;
+
 	unplug_slaves(q->queuedata);
+	md_wakeup_thread(mddev->thread);
 }
 
 static int raid10_issue_flush(request_queue_t *q, struct gendisk *disk,
@@ -640,27 +632,107 @@ static int raid10_issue_flush(request_queue_t *q, struct gendisk *disk,
 	return ret;
 }
 
-/*
- * Throttle resync depth, so that we can both get proper overlapping of
- * requests, but are still able to handle normal requests quickly.
+/* Barriers....
+ * Sometimes we need to suspend IO while we do something else,
+ * either some resync/recovery, or reconfigure the array.
+ * To do this we raise a 'barrier'.
+ * The 'barrier' is a counter that can be raised multiple times
+ * to count how many activities are happening which preclude
+ * normal IO.
+ * We can only raise the barrier if there is no pending IO.
+ * i.e. if nr_pending == 0.
+ * We choose only to raise the barrier if no-one is waiting for the
+ * barrier to go down.  This means that as soon as an IO request
+ * is ready, no other operations which require a barrier will start
+ * until the IO request has had a chance.
+ *
+ * So: regular IO calls 'wait_barrier'.  When that returns there
+ *    is no backgroup IO happening,  It must arrange to call
+ *    allow_barrier when it has finished its IO.
+ * backgroup IO calls must call raise_barrier.  Once that returns
+ *    there is no normal IO happeing.  It must arrange to call
+ *    lower_barrier when the particular background IO completes.
  */
 #define RESYNC_DEPTH 32
 
-static void device_barrier(conf_t *conf, sector_t sect)
+static void raise_barrier(conf_t *conf, int force)
+{
+	BUG_ON(force && !conf->barrier);
+	spin_lock_irq(&conf->resync_lock);
+
+	/* Wait until no block IO is waiting (unless 'force') */
+	wait_event_lock_irq(conf->wait_barrier, force || !conf->nr_waiting,
+			    conf->resync_lock,
+			    raid10_unplug(conf->mddev->queue));
+
+	/* block any new IO from starting */
+	conf->barrier++;
+
+	/* No wait for all pending IO to complete */
+	wait_event_lock_irq(conf->wait_barrier,
+			    !conf->nr_pending && conf->barrier < RESYNC_DEPTH,
+			    conf->resync_lock,
+			    raid10_unplug(conf->mddev->queue));
+
+	spin_unlock_irq(&conf->resync_lock);
+}
+
+static void lower_barrier(conf_t *conf)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&conf->resync_lock, flags);
+	conf->barrier--;
+	spin_unlock_irqrestore(&conf->resync_lock, flags);
+	wake_up(&conf->wait_barrier);
+}
+
+static void wait_barrier(conf_t *conf)
 {
 	spin_lock_irq(&conf->resync_lock);
-	wait_event_lock_irq(conf->wait_idle, !waitqueue_active(&conf->wait_resume),
-			    conf->resync_lock, unplug_slaves(conf->mddev));
-
-	if (!conf->barrier++) {
-		wait_event_lock_irq(conf->wait_idle, !conf->nr_pending,
-				    conf->resync_lock, unplug_slaves(conf->mddev));
-		if (conf->nr_pending)
-			BUG();
+	if (conf->barrier) {
+		conf->nr_waiting++;
+		wait_event_lock_irq(conf->wait_barrier, !conf->barrier,
+				    conf->resync_lock,
+				    raid10_unplug(conf->mddev->queue));
+		conf->nr_waiting--;
 	}
-	wait_event_lock_irq(conf->wait_resume, conf->barrier < RESYNC_DEPTH,
-			    conf->resync_lock, unplug_slaves(conf->mddev));
-	conf->next_resync = sect;
+	conf->nr_pending++;
+	spin_unlock_irq(&conf->resync_lock);
+}
+
+static void allow_barrier(conf_t *conf)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&conf->resync_lock, flags);
+	conf->nr_pending--;
+	spin_unlock_irqrestore(&conf->resync_lock, flags);
+	wake_up(&conf->wait_barrier);
+}
+
+static void freeze_array(conf_t *conf)
+{
+	/* stop syncio and normal IO and wait for everything to
+	 * go quiet.
+	 * We increment barrier and nr_waiting, and then
+	 * wait until barrier+nr_pending match nr_queued+2
+	 */
+	spin_lock_irq(&conf->resync_lock);
+	conf->barrier++;
+	conf->nr_waiting++;
+	wait_event_lock_irq(conf->wait_barrier,
+			    conf->barrier+conf->nr_pending == conf->nr_queued+2,
+			    conf->resync_lock,
+			    raid10_unplug(conf->mddev->queue));
+	spin_unlock_irq(&conf->resync_lock);
+}
+
+static void unfreeze_array(conf_t *conf)
+{
+	/* reverse the effect of the freeze */
+	spin_lock_irq(&conf->resync_lock);
+	conf->barrier--;
+	conf->nr_waiting--;
+	wake_up(&conf->wait_barrier);
 	spin_unlock_irq(&conf->resync_lock);
 }
 
@@ -674,6 +746,8 @@ static int make_request(request_queue_t *q, struct bio * bio)
 	int i;
 	int chunk_sects = conf->chunk_mask + 1;
 	const int rw = bio_data_dir(bio);
+	struct bio_list bl;
+	unsigned long flags;
 
 	if (unlikely(bio_barrier(bio))) {
 		bio_endio(bio, bio->bi_size, -EOPNOTSUPP);
@@ -719,10 +793,7 @@ static int make_request(request_queue_t *q, struct bio * bio)
 	 * thread has put up a bar for new requests.
 	 * Continue immediately if no resync is active currently.
 	 */
-	spin_lock_irq(&conf->resync_lock);
-	wait_event_lock_irq(conf->wait_resume, !conf->barrier, conf->resync_lock, );
-	conf->nr_pending++;
-	spin_unlock_irq(&conf->resync_lock);
+	wait_barrier(conf);
 
 	disk_stat_inc(mddev->gendisk, ios[rw]);
 	disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bio));
@@ -734,6 +805,7 @@ static int make_request(request_queue_t *q, struct bio * bio)
 
 	r10_bio->mddev = mddev;
 	r10_bio->sector = bio->bi_sector;
+	r10_bio->state = 0;
 
 	if (rw == READ) {
 		/*
@@ -778,13 +850,16 @@ static int make_request(request_queue_t *q, struct bio * bio)
 		    !test_bit(Faulty, &rdev->flags)) {
 			atomic_inc(&rdev->nr_pending);
 			r10_bio->devs[i].bio = bio;
-		} else
+		} else {
 			r10_bio->devs[i].bio = NULL;
+			set_bit(R10BIO_Degraded, &r10_bio->state);
+		}
 	}
 	rcu_read_unlock();
 
-	atomic_set(&r10_bio->remaining, 1);
+	atomic_set(&r10_bio->remaining, 0);
 
+	bio_list_init(&bl);
 	for (i = 0; i < conf->copies; i++) {
 		struct bio *mbio;
 		int d = r10_bio->devs[i].devnum;
@@ -802,13 +877,14 @@ static int make_request(request_queue_t *q, struct bio * bio)
 		mbio->bi_private = r10_bio;
 
 		atomic_inc(&r10_bio->remaining);
-		generic_make_request(mbio);
+		bio_list_add(&bl, mbio);
 	}
 
-	if (atomic_dec_and_test(&r10_bio->remaining)) {
-		md_write_end(mddev);
-		raid_end_bio_io(r10_bio);
-	}
+	bitmap_startwrite(mddev->bitmap, bio->bi_sector, r10_bio->sectors, 0);
+	spin_lock_irqsave(&conf->device_lock, flags);
+	bio_list_merge(&conf->pending_bio_list, &bl);
+	blk_plug_device(mddev->queue);
+	spin_unlock_irqrestore(&conf->device_lock, flags);
 
 	return 0;
 }
@@ -897,13 +973,8 @@ static void print_conf(conf_t *conf)
 
 static void close_sync(conf_t *conf)
 {
-	spin_lock_irq(&conf->resync_lock);
-	wait_event_lock_irq(conf->wait_resume, !conf->barrier,
-			    conf->resync_lock, 	unplug_slaves(conf->mddev));
-	spin_unlock_irq(&conf->resync_lock);
-
-	if (conf->barrier) BUG();
-	if (waitqueue_active(&conf->wait_idle)) BUG();
+	wait_barrier(conf);
+	allow_barrier(conf);
 
 	mempool_destroy(conf->r10buf_pool);
 	conf->r10buf_pool = NULL;
@@ -971,7 +1042,12 @@ static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
 	if (!enough(conf))
 		return 0;
 
-	for (mirror=0; mirror < mddev->raid_disks; mirror++)
+	if (rdev->saved_raid_disk >= 0 &&
+	    conf->mirrors[rdev->saved_raid_disk].rdev == NULL)
+		mirror = rdev->saved_raid_disk;
+	else
+		mirror = 0;
+	for ( ; mirror < mddev->raid_disks; mirror++)
 		if ( !(p=conf->mirrors+mirror)->rdev) {
 
 			blk_queue_stack_limits(mddev->queue,
@@ -987,6 +1063,8 @@ static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
 			p->head_position = 0;
 			rdev->raid_disk = mirror;
 			found = 1;
+			if (rdev->saved_raid_disk != mirror)
+				conf->fullsync = 1;
 			rcu_assign_pointer(p->rdev, rdev);
 			break;
 		}
@@ -1027,7 +1105,6 @@ abort:
 
 static int end_sync_read(struct bio *bio, unsigned int bytes_done, int error)
 {
-	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
 	r10bio_t * r10_bio = (r10bio_t *)(bio->bi_private);
 	conf_t *conf = mddev_to_conf(r10_bio->mddev);
 	int i,d;
@@ -1042,9 +1119,16 @@ static int end_sync_read(struct bio *bio, unsigned int bytes_done, int error)
 		BUG();
 	update_head_pos(i, r10_bio);
 	d = r10_bio->devs[i].devnum;
-	if (!uptodate)
-		md_error(r10_bio->mddev,
-			 conf->mirrors[d].rdev);
+
+	if (test_bit(BIO_UPTODATE, &bio->bi_flags))
+		set_bit(R10BIO_Uptodate, &r10_bio->state);
+	else {
+		atomic_add(r10_bio->sectors,
+			   &conf->mirrors[d].rdev->corrected_errors);
+		if (!test_bit(MD_RECOVERY_SYNC, &conf->mddev->recovery))
+			md_error(r10_bio->mddev,
+				 conf->mirrors[d].rdev);
+	}
 
 	/* for reconstruct, we always reschedule after a read.
 	 * for resync, only after all reads
@@ -1132,23 +1216,32 @@ static void sync_request_write(mddev_t *mddev, r10bio_t *r10_bio)
 	fbio = r10_bio->devs[i].bio;
 
 	/* now find blocks with errors */
-	for (i=first+1 ; i < conf->copies ; i++) {
-		int vcnt, j, d;
+	for (i=0 ; i < conf->copies ; i++) {
+		int  j, d;
+		int vcnt = r10_bio->sectors >> (PAGE_SHIFT-9);
 
-		if (!test_bit(BIO_UPTODATE, &r10_bio->devs[i].bio->bi_flags))
-			continue;
-		/* We know that the bi_io_vec layout is the same for
-		 * both 'first' and 'i', so we just compare them.
-		 * All vec entries are PAGE_SIZE;
-		 */
 		tbio = r10_bio->devs[i].bio;
-		vcnt = r10_bio->sectors >> (PAGE_SHIFT-9);
-		for (j = 0; j < vcnt; j++)
-			if (memcmp(page_address(fbio->bi_io_vec[j].bv_page),
-				   page_address(tbio->bi_io_vec[j].bv_page),
-				   PAGE_SIZE))
-				break;
-		if (j == vcnt)
+
+		if (tbio->bi_end_io != end_sync_read)
+			continue;
+		if (i == first)
+			continue;
+		if (test_bit(BIO_UPTODATE, &r10_bio->devs[i].bio->bi_flags)) {
+			/* We know that the bi_io_vec layout is the same for
+			 * both 'first' and 'i', so we just compare them.
+			 * All vec entries are PAGE_SIZE;
+			 */
+			for (j = 0; j < vcnt; j++)
+				if (memcmp(page_address(fbio->bi_io_vec[j].bv_page),
+					   page_address(tbio->bi_io_vec[j].bv_page),
+					   PAGE_SIZE))
+					break;
+			if (j == vcnt)
+				continue;
+			mddev->resync_mismatches += r10_bio->sectors;
+		}
+		if (test_bit(MD_RECOVERY_CHECK, &mddev->recovery))
+			/* Don't fix anything. */
 			continue;
 		/* Ok, we need to write this bio
 		 * First we need to fixup bv_offset, bv_len and
@@ -1227,7 +1320,10 @@ static void recovery_request_write(mddev_t *mddev, r10bio_t *r10_bio)
 
 	atomic_inc(&conf->mirrors[d].rdev->nr_pending);
 	md_sync_acct(conf->mirrors[d].rdev->bdev, wbio->bi_size >> 9);
-	generic_make_request(wbio);
+	if (test_bit(R10BIO_Uptodate, &r10_bio->state))
+		generic_make_request(wbio);
+	else
+		bio_endio(wbio, wbio->bi_size, -EIO);
 }
 
 
@@ -1254,10 +1350,31 @@ static void raid10d(mddev_t *mddev)
 	for (;;) {
 		char b[BDEVNAME_SIZE];
 		spin_lock_irqsave(&conf->device_lock, flags);
+
+		if (conf->pending_bio_list.head) {
+			bio = bio_list_get(&conf->pending_bio_list);
+			blk_remove_plug(mddev->queue);
+			spin_unlock_irqrestore(&conf->device_lock, flags);
+			/* flush any pending bitmap writes to disk before proceeding w/ I/O */
+			if (bitmap_unplug(mddev->bitmap) != 0)
+				printk("%s: bitmap file write failed!\n", mdname(mddev));
+
+			while (bio) { /* submit pending writes */
+				struct bio *next = bio->bi_next;
+				bio->bi_next = NULL;
+				generic_make_request(bio);
+				bio = next;
+			}
+			unplug = 1;
+
+			continue;
+		}
+
 		if (list_empty(head))
 			break;
 		r10_bio = list_entry(head->prev, r10bio_t, retry_list);
 		list_del(head->prev);
+		conf->nr_queued--;
 		spin_unlock_irqrestore(&conf->device_lock, flags);
 
 		mddev = r10_bio->mddev;
@@ -1270,8 +1387,96 @@ static void raid10d(mddev_t *mddev)
 			unplug = 1;
 		} else {
 			int mirror;
+			/* we got a read error. Maybe the drive is bad.  Maybe just
+			 * the block and we can fix it.
+			 * We freeze all other IO, and try reading the block from
+			 * other devices.  When we find one, we re-write
+			 * and check it that fixes the read error.
+			 * This is all done synchronously while the array is
+			 * frozen.
+			 */
+			int sect = 0; /* Offset from r10_bio->sector */
+			int sectors = r10_bio->sectors;
+			freeze_array(conf);
+			if (mddev->ro == 0) while(sectors) {
+				int s = sectors;
+				int sl = r10_bio->read_slot;
+				int success = 0;
+
+				if (s > (PAGE_SIZE>>9))
+					s = PAGE_SIZE >> 9;
+
+				do {
+					int d = r10_bio->devs[sl].devnum;
+					rdev = conf->mirrors[d].rdev;
+					if (rdev &&
+					    test_bit(In_sync, &rdev->flags) &&
+					    sync_page_io(rdev->bdev,
+							 r10_bio->devs[sl].addr +
+							 sect + rdev->data_offset,
+							 s<<9,
+							 conf->tmppage, READ))
+						success = 1;
+					else {
+						sl++;
+						if (sl == conf->copies)
+							sl = 0;
+					}
+				} while (!success && sl != r10_bio->read_slot);
+
+				if (success) {
+					int start = sl;
+					/* write it back and re-read */
+					while (sl != r10_bio->read_slot) {
+						int d;
+						if (sl==0)
+							sl = conf->copies;
+						sl--;
+						d = r10_bio->devs[sl].devnum;
+						rdev = conf->mirrors[d].rdev;
+						atomic_add(s, &rdev->corrected_errors);
+						if (rdev &&
+						    test_bit(In_sync, &rdev->flags)) {
+							if (sync_page_io(rdev->bdev,
+									 r10_bio->devs[sl].addr +
+									 sect + rdev->data_offset,
+									 s<<9, conf->tmppage, WRITE) == 0)
+								/* Well, this device is dead */
+								md_error(mddev, rdev);
+						}
+					}
+					sl = start;
+					while (sl != r10_bio->read_slot) {
+						int d;
+						if (sl==0)
+							sl = conf->copies;
+						sl--;
+						d = r10_bio->devs[sl].devnum;
+						rdev = conf->mirrors[d].rdev;
+						if (rdev &&
+						    test_bit(In_sync, &rdev->flags)) {
+							if (sync_page_io(rdev->bdev,
+									 r10_bio->devs[sl].addr +
+									 sect + rdev->data_offset,
+									 s<<9, conf->tmppage, READ) == 0)
+								/* Well, this device is dead */
+								md_error(mddev, rdev);
+						}
+					}
+				} else {
+					/* Cannot read from anywhere -- bye bye array */
+					md_error(mddev, conf->mirrors[r10_bio->devs[r10_bio->read_slot].devnum].rdev);
+					break;
+				}
+				sectors -= s;
+				sect += s;
+			}
+
+			unfreeze_array(conf);
+
 			bio = r10_bio->devs[r10_bio->read_slot].bio;
-			r10_bio->devs[r10_bio->read_slot].bio = NULL;
+			r10_bio->devs[r10_bio->read_slot].bio =
+				mddev->ro ? IO_BLOCKED : NULL;
 			bio_put(bio);
 			mirror = read_balance(conf, r10_bio);
 			if (mirror == -1) {
@@ -1360,6 +1565,8 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
 	sector_t max_sector, nr_sectors;
 	int disk;
 	int i;
+	int max_sync;
+	int sync_blocks;
 
 	sector_t sectors_skipped = 0;
 	int chunks_skipped = 0;
@@ -1373,6 +1580,29 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
 	if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery))
 		max_sector = mddev->resync_max_sectors;
 	if (sector_nr >= max_sector) {
+		/* If we aborted, we need to abort the
+		 * sync on the 'current' bitmap chucks (there can
+		 * be several when recovering multiple devices).
+		 * as we may have started syncing it but not finished.
+		 * We can find the current address in
+		 * mddev->curr_resync, but for recovery,
+		 * we need to convert that to several
+		 * virtual addresses.
+		 */
+		if (mddev->curr_resync < max_sector) { /* aborted */
+			if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery))
+				bitmap_end_sync(mddev->bitmap, mddev->curr_resync,
+						&sync_blocks, 1);
+			else for (i=0; i<conf->raid_disks; i++) {
+				sector_t sect =
+					raid10_find_virt(conf, mddev->curr_resync, i);
+				bitmap_end_sync(mddev->bitmap, sect,
+						&sync_blocks, 1);
+			}
+		} else /* completed sync */
+			conf->fullsync = 0;
+
+		bitmap_close_sync(mddev->bitmap);
 		close_sync(conf);
 		*skipped = 1;
 		return sectors_skipped;
@@ -1395,9 +1625,8 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
 	 * If there is non-resync activity waiting for us then
 	 * put in a delay to throttle resync.
 	 */
-	if (!go_faster && waitqueue_active(&conf->wait_resume))
+	if (!go_faster && conf->nr_waiting)
 		msleep_interruptible(1000);
-	device_barrier(conf, sector_nr + RESYNC_SECTORS);
 
 	/* Again, very different code for resync and recovery.
 	 * Both must result in an r10bio with a list of bios that
@@ -1414,6 +1643,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
 	 * end_sync_write if we will want to write.
 	 */
 
+	max_sync = RESYNC_PAGES << (PAGE_SHIFT-9);
 	if (!test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
 		/* recovery... the complicated one */
 		int i, j, k;
@@ -1422,14 +1652,29 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
 		for (i=0 ; i<conf->raid_disks; i++)
 			if (conf->mirrors[i].rdev &&
 			    !test_bit(In_sync, &conf->mirrors[i].rdev->flags)) {
+				int still_degraded = 0;
 				/* want to reconstruct this device */
 				r10bio_t *rb2 = r10_bio;
+				sector_t sect = raid10_find_virt(conf, sector_nr, i);
+				int must_sync;
+				/* Unless we are doing a full sync, we only need
+				 * to recover the block if it is set in the bitmap
+				 */
+				must_sync = bitmap_start_sync(mddev->bitmap, sect,
+							      &sync_blocks, 1);
+				if (sync_blocks < max_sync)
+					max_sync = sync_blocks;
+				if (!must_sync &&
+				    !conf->fullsync) {
+					/* yep, skip the sync_blocks here, but don't assume
+					 * that there will never be anything to do here
+					 */
+					chunks_skipped = -1;
+					continue;
+				}
 
 				r10_bio = mempool_alloc(conf->r10buf_pool, GFP_NOIO);
-				spin_lock_irq(&conf->resync_lock);
-				conf->nr_pending++;
-				if (rb2) conf->barrier++;
-				spin_unlock_irq(&conf->resync_lock);
+				raise_barrier(conf, rb2 != NULL);
 				atomic_set(&r10_bio->remaining, 0);
 
 				r10_bio->master_bio = (struct bio*)rb2;
@@ -1437,8 +1682,23 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
 					atomic_inc(&rb2->remaining);
 				r10_bio->mddev = mddev;
 				set_bit(R10BIO_IsRecover, &r10_bio->state);
-				r10_bio->sector = raid10_find_virt(conf, sector_nr, i);
+				r10_bio->sector = sect;
+
 				raid10_find_phys(conf, r10_bio);
+				/* Need to check if this section will still be
+				 * degraded
+				 */
+				for (j=0; j<conf->copies;j++) {
+					int d = r10_bio->devs[j].devnum;
+					if (conf->mirrors[d].rdev == NULL ||
+					    test_bit(Faulty, &conf->mirrors[d].rdev->flags)) {
+						still_degraded = 1;
+						break;
+					}
+				}
+				must_sync = bitmap_start_sync(mddev->bitmap, sect,
+							      &sync_blocks, still_degraded);
+
 				for (j=0; j<conf->copies;j++) {
 					int d = r10_bio->devs[j].devnum;
 					if (conf->mirrors[d].rdev &&
@@ -1498,14 +1758,22 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
 	} else {
 		/* resync. Schedule a read for every block at this virt offset */
 		int count = 0;
-		r10_bio = mempool_alloc(conf->r10buf_pool, GFP_NOIO);
 
-		spin_lock_irq(&conf->resync_lock);
-		conf->nr_pending++;
-		spin_unlock_irq(&conf->resync_lock);
+		if (!bitmap_start_sync(mddev->bitmap, sector_nr,
+				       &sync_blocks, mddev->degraded) &&
+		    !conf->fullsync && !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) {
+			/* We can skip this block */
+			*skipped = 1;
+			return sync_blocks + sectors_skipped;
+		}
+		if (sync_blocks < max_sync)
+			max_sync = sync_blocks;
+		r10_bio = mempool_alloc(conf->r10buf_pool, GFP_NOIO);
 
 		r10_bio->mddev = mddev;
 		atomic_set(&r10_bio->remaining, 0);
+		raise_barrier(conf, 0);
+		conf->next_resync = sector_nr;
 
 		r10_bio->master_bio = NULL;
 		r10_bio->sector = sector_nr;
@@ -1558,6 +1826,8 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
 	}
 
 	nr_sectors = 0;
+	if (sector_nr + max_sync < max_sector)
+		max_sector = sector_nr + max_sync;
 	do {
 		struct page *page;
 		int len = PAGE_SIZE;
@@ -1632,11 +1902,11 @@ static int run(mddev_t *mddev)
 	int nc, fc;
 	sector_t stride, size;
 
-	if (mddev->level != 10) {
-		printk(KERN_ERR "raid10: %s: raid level not set correctly... (%d)\n",
-		       mdname(mddev), mddev->level);
-		goto out;
+	if (mddev->chunk_size == 0) {
+		printk(KERN_ERR "md/raid10: non-zero chunk size required.\n");
+		return -EINVAL;
 	}
+
 	nc = mddev->layout & 255;
 	fc = (mddev->layout >> 8) & 255;
 	if ((nc*fc) <2 || (nc*fc) > mddev->raid_disks ||
@@ -1650,22 +1920,24 @@ static int run(mddev_t *mddev)
 	 * bookkeeping area. [whatever we allocate in run(),
 	 * should be freed in stop()]
 	 */
-	conf = kmalloc(sizeof(conf_t), GFP_KERNEL);
+	conf = kzalloc(sizeof(conf_t), GFP_KERNEL);
 	mddev->private = conf;
 	if (!conf) {
 		printk(KERN_ERR "raid10: couldn't allocate memory for %s\n",
 			mdname(mddev));
 		goto out;
 	}
-	memset(conf, 0, sizeof(*conf));
-	conf->mirrors = kmalloc(sizeof(struct mirror_info)*mddev->raid_disks,
+	conf->mirrors = kzalloc(sizeof(struct mirror_info)*mddev->raid_disks,
 				 GFP_KERNEL);
 	if (!conf->mirrors) {
 		printk(KERN_ERR "raid10: couldn't allocate memory for %s\n",
 		       mdname(mddev));
 		goto out_free_conf;
 	}
-	memset(conf->mirrors, 0, sizeof(struct mirror_info)*mddev->raid_disks);
+
+	conf->tmppage = alloc_page(GFP_KERNEL);
+	if (!conf->tmppage)
+		goto out_free_conf;
 
 	conf->near_copies = nc;
 	conf->far_copies = fc;
@@ -1713,8 +1985,7 @@ static int run(mddev_t *mddev)
 	INIT_LIST_HEAD(&conf->retry_list);
 
 	spin_lock_init(&conf->resync_lock);
-	init_waitqueue_head(&conf->wait_idle);
-	init_waitqueue_head(&conf->wait_resume);
+	init_waitqueue_head(&conf->wait_barrier);
 
 	/* need to check that every block has at least one working mirror */
 	if (!enough(conf)) {
@@ -1763,7 +2034,7 @@ static int run(mddev_t *mddev)
 	 * maybe...
 	 */
 	{
-		int stripe = conf->raid_disks * mddev->chunk_size / PAGE_CACHE_SIZE;
+		int stripe = conf->raid_disks * mddev->chunk_size / PAGE_SIZE;
 		stripe /= conf->near_copies;
 		if (mddev->queue->backing_dev_info.ra_pages < 2* stripe)
 			mddev->queue->backing_dev_info.ra_pages = 2* stripe;
@@ -1776,6 +2047,7 @@ static int run(mddev_t *mddev)
 out_free_conf:
 	if (conf->r10bio_pool)
 		mempool_destroy(conf->r10bio_pool);
+	safe_put_page(conf->tmppage);
 	kfree(conf->mirrors);
 	kfree(conf);
 	mddev->private = NULL;
@@ -1798,10 +2070,31 @@ static int stop(mddev_t *mddev)
 	return 0;
 }
 
+static void raid10_quiesce(mddev_t *mddev, int state)
+{
+	conf_t *conf = mddev_to_conf(mddev);
+
+	switch(state) {
+	case 1:
+		raise_barrier(conf, 0);
+		break;
+	case 0:
+		lower_barrier(conf);
+		break;
+	}
+	if (mddev->thread) {
+		if (mddev->bitmap)
+			mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
+		else
+			mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT;
+		md_wakeup_thread(mddev->thread);
+	}
+}
 
-static mdk_personality_t raid10_personality =
+static struct mdk_personality raid10_personality =
 {
 	.name		= "raid10",
+	.level		= 10,
 	.owner		= THIS_MODULE,
 	.make_request	= make_request,
 	.run		= run,
@@ -1812,19 +2105,22 @@ static mdk_personality_t raid10_personality =
 	.hot_remove_disk= raid10_remove_disk,
 	.spare_active	= raid10_spare_active,
 	.sync_request	= sync_request,
+	.quiesce	= raid10_quiesce,
 };
 
 static int __init raid_init(void)
 {
-	return register_md_personality(RAID10, &raid10_personality);
+	return register_md_personality(&raid10_personality);
 }
 
 static void raid_exit(void)
 {
-	unregister_md_personality(RAID10);
+	unregister_md_personality(&raid10_personality);
 }
 
 module_init(raid_init);
 module_exit(raid_exit);
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("md-personality-9"); /* RAID10 */
+MODULE_ALIAS("md-raid10");
+MODULE_ALIAS("md-level-10");
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index fafc4bc045f7..54f4a9847e38 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -35,12 +35,10 @@
 #define STRIPE_SHIFT		(PAGE_SHIFT - 9)
 #define STRIPE_SECTORS		(STRIPE_SIZE>>9)
 #define	IO_THRESHOLD		1
-#define HASH_PAGES		1
-#define HASH_PAGES_ORDER	0
-#define NR_HASH			(HASH_PAGES * PAGE_SIZE / sizeof(struct stripe_head *))
+#define NR_HASH			(PAGE_SIZE / sizeof(struct hlist_head))
 #define HASH_MASK		(NR_HASH - 1)
 
-#define stripe_hash(conf, sect)	((conf)->stripe_hashtbl[((sect) >> STRIPE_SHIFT) & HASH_MASK])
+#define stripe_hash(conf, sect)	(&((conf)->stripe_hashtbl[((sect) >> STRIPE_SHIFT) & HASH_MASK]))
 
 /* bio's attached to a stripe+device for I/O are linked together in bi_sector
  * order without overlap.  There may be several bio's per stripe+device, and
@@ -113,29 +111,21 @@ static void release_stripe(struct stripe_head *sh)
 	spin_unlock_irqrestore(&conf->device_lock, flags);
 }
 
-static void remove_hash(struct stripe_head *sh)
+static inline void remove_hash(struct stripe_head *sh)
 {
 	PRINTK("remove_hash(), stripe %llu\n", (unsigned long long)sh->sector);
 
-	if (sh->hash_pprev) {
-		if (sh->hash_next)
-			sh->hash_next->hash_pprev = sh->hash_pprev;
-		*sh->hash_pprev = sh->hash_next;
-		sh->hash_pprev = NULL;
-	}
+	hlist_del_init(&sh->hash);
 }
 
-static __inline__ void insert_hash(raid5_conf_t *conf, struct stripe_head *sh)
+static inline void insert_hash(raid5_conf_t *conf, struct stripe_head *sh)
 {
-	struct stripe_head **shp = &stripe_hash(conf, sh->sector);
+	struct hlist_head *hp = stripe_hash(conf, sh->sector);
 
 	PRINTK("insert_hash(), stripe %llu\n", (unsigned long long)sh->sector);
 
 	CHECK_DEVLOCK();
-	if ((sh->hash_next = *shp) != NULL)
-		(*shp)->hash_pprev = &sh->hash_next;
-	*shp = sh;
-	sh->hash_pprev = shp;
+	hlist_add_head(&sh->hash, hp);
 }
 
 
@@ -167,7 +157,7 @@ static void shrink_buffers(struct stripe_head *sh, int num)
 		if (!p)
 			continue;
 		sh->dev[i].page = NULL;
-		page_cache_release(p);
+		put_page(p);
 	}
 }
 
@@ -228,10 +218,11 @@ static inline void init_stripe(struct stripe_head *sh, sector_t sector, int pd_i
 static struct stripe_head *__find_stripe(raid5_conf_t *conf, sector_t sector)
 {
 	struct stripe_head *sh;
+	struct hlist_node *hn;
 
 	CHECK_DEVLOCK();
 	PRINTK("__find_stripe, sector %llu\n", (unsigned long long)sector);
-	for (sh = stripe_hash(conf, sector); sh; sh = sh->hash_next)
+	hlist_for_each_entry(sh, hn, stripe_hash(conf, sector), hash)
 		if (sh->sector == sector)
 			return sh;
 	PRINTK("__stripe %llu not in cache\n", (unsigned long long)sector);
@@ -417,7 +408,7 @@ static int raid5_end_read_request(struct bio * bi, unsigned int bytes_done,
 		set_bit(R5_UPTODATE, &sh->dev[i].flags);
 #endif
 		if (test_bit(R5_ReadError, &sh->dev[i].flags)) {
-			printk("R5: read error corrected!!\n");
+			printk(KERN_INFO "raid5: read error corrected!!\n");
 			clear_bit(R5_ReadError, &sh->dev[i].flags);
 			clear_bit(R5_ReWrite, &sh->dev[i].flags);
 		}
@@ -428,13 +419,14 @@ static int raid5_end_read_request(struct bio * bi, unsigned int bytes_done,
 		clear_bit(R5_UPTODATE, &sh->dev[i].flags);
 		atomic_inc(&conf->disks[i].rdev->read_errors);
 		if (conf->mddev->degraded)
-			printk("R5: read error not correctable.\n");
+			printk(KERN_WARNING "raid5: read error not correctable.\n");
 		else if (test_bit(R5_ReWrite, &sh->dev[i].flags))
 			/* Oh, no!!! */
-			printk("R5: read error NOT corrected!!\n");
+			printk(KERN_WARNING "raid5: read error NOT corrected!!\n");
 		else if (atomic_read(&conf->disks[i].rdev->read_errors)
 			 > conf->max_nr_stripes)
-			printk("raid5: Too many read errors, failing device.\n");
+			printk(KERN_WARNING
+			       "raid5: Too many read errors, failing device.\n");
 		else
 			retry = 1;
 		if (retry)
@@ -604,7 +596,7 @@ static sector_t raid5_compute_sector(sector_t r_sector, unsigned int raid_disks,
 			*dd_idx = (*pd_idx + 1 + *dd_idx) % raid_disks;
 			break;
 		default:
-			printk("raid5: unsupported algorithm %d\n",
+			printk(KERN_ERR "raid5: unsupported algorithm %d\n",
 				conf->algorithm);
 	}
 
@@ -645,7 +637,7 @@ static sector_t compute_blocknr(struct stripe_head *sh, int i)
 			i -= (sh->pd_idx + 1);
 			break;
 		default:
-			printk("raid5: unsupported algorithm %d\n",
+			printk(KERN_ERR "raid5: unsupported algorithm %d\n",
 				conf->algorithm);
 	}
 
@@ -654,7 +646,7 @@ static sector_t compute_blocknr(struct stripe_head *sh, int i)
 
 	check = raid5_compute_sector (r_sector, raid_disks, data_disks, &dummy1, &dummy2, conf);
 	if (check != sh->sector || dummy1 != dd_idx || dummy2 != sh->pd_idx) {
-		printk("compute_blocknr: map not correct\n");
+		printk(KERN_ERR "compute_blocknr: map not correct\n");
 		return 0;
 	}
 	return r_sector;
@@ -737,7 +729,7 @@ static void compute_block(struct stripe_head *sh, int dd_idx)
 		if (test_bit(R5_UPTODATE, &sh->dev[i].flags))
 			ptr[count++] = p;
 		else
-			printk("compute_block() %d, stripe %llu, %d"
+			printk(KERN_ERR "compute_block() %d, stripe %llu, %d"
 				" not present\n", dd_idx,
 				(unsigned long long)sh->sector, i);
 
@@ -960,11 +952,11 @@ static void handle_stripe(struct stripe_head *sh)
 	syncing = test_bit(STRIPE_SYNCING, &sh->state);
 	/* Now to look around and see what can be done */
 
+	rcu_read_lock();
 	for (i=disks; i--; ) {
 		mdk_rdev_t *rdev;
 		dev = &sh->dev[i];
 		clear_bit(R5_Insync, &dev->flags);
-		clear_bit(R5_Syncio, &dev->flags);
 
 		PRINTK("check %d: state 0x%lx read %p write %p written %p\n",
 			i, dev->flags, dev->toread, dev->towrite, dev->written);
@@ -1003,9 +995,9 @@ static void handle_stripe(struct stripe_head *sh)
 				non_overwrite++;
 		}
 		if (dev->written) written++;
-		rdev = conf->disks[i].rdev; /* FIXME, should I be looking rdev */
+		rdev = rcu_dereference(conf->disks[i].rdev);
 		if (!rdev || !test_bit(In_sync, &rdev->flags)) {
-			/* The ReadError flag wil just be confusing now */
+			/* The ReadError flag will just be confusing now */
 			clear_bit(R5_ReadError, &dev->flags);
 			clear_bit(R5_ReWrite, &dev->flags);
 		}
@@ -1016,6 +1008,7 @@ static void handle_stripe(struct stripe_head *sh)
 		} else
 			set_bit(R5_Insync, &dev->flags);
 	}
+	rcu_read_unlock();
 	PRINTK("locked=%d uptodate=%d to_read=%d"
 		" to_write=%d failed=%d failed_num=%d\n",
 		locked, uptodate, to_read, to_write, failed, failed_num);
@@ -1027,10 +1020,13 @@ static void handle_stripe(struct stripe_head *sh)
 			int bitmap_end = 0;
 
 			if (test_bit(R5_ReadError, &sh->dev[i].flags)) {
-				mdk_rdev_t *rdev = conf->disks[i].rdev;
+				mdk_rdev_t *rdev;
+				rcu_read_lock();
+				rdev = rcu_dereference(conf->disks[i].rdev);
 				if (rdev && test_bit(In_sync, &rdev->flags))
 					/* multiple read failures in one stripe */
 					md_error(conf->mddev, rdev);
+				rcu_read_unlock();
 			}
 
 			spin_lock_irq(&conf->device_lock);
@@ -1179,9 +1175,6 @@ static void handle_stripe(struct stripe_head *sh)
 					locked++;
 					PRINTK("Reading block %d (sync=%d)\n", 
 						i, syncing);
-					if (syncing)
-						md_sync_acct(conf->disks[i].rdev->bdev,
-							     STRIPE_SECTORS);
 				}
 			}
 		}
@@ -1288,7 +1281,7 @@ static void handle_stripe(struct stripe_head *sh)
 	 * is available
 	 */
 	if (syncing && locked == 0 &&
-	    !test_bit(STRIPE_INSYNC, &sh->state) && failed <= 1) {
+	    !test_bit(STRIPE_INSYNC, &sh->state)) {
 		set_bit(STRIPE_HANDLE, &sh->state);
 		if (failed == 0) {
 			char *pagea;
@@ -1306,27 +1299,25 @@ static void handle_stripe(struct stripe_head *sh)
 				if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery))
 					/* don't try to repair!! */
 					set_bit(STRIPE_INSYNC, &sh->state);
+				else {
+					compute_block(sh, sh->pd_idx);
+					uptodate++;
+				}
 			}
 		}
 		if (!test_bit(STRIPE_INSYNC, &sh->state)) {
+			/* either failed parity check, or recovery is happening */
 			if (failed==0)
 				failed_num = sh->pd_idx;
-			/* should be able to compute the missing block and write it to spare */
-			if (!test_bit(R5_UPTODATE, &sh->dev[failed_num].flags)) {
-				if (uptodate+1 != disks)
-					BUG();
-				compute_block(sh, failed_num);
-				uptodate++;
-			}
-			if (uptodate != disks)
-				BUG();
 			dev = &sh->dev[failed_num];
+			BUG_ON(!test_bit(R5_UPTODATE, &dev->flags));
+			BUG_ON(uptodate != disks);
+
 			set_bit(R5_LOCKED, &dev->flags);
 			set_bit(R5_Wantwrite, &dev->flags);
 			clear_bit(STRIPE_DEGRADED, &sh->state);
 			locked++;
 			set_bit(STRIPE_INSYNC, &sh->state);
-			set_bit(R5_Syncio, &dev->flags);
 		}
 	}
 	if (syncing && locked == 0 && test_bit(STRIPE_INSYNC, &sh->state)) {
@@ -1392,7 +1383,7 @@ static void handle_stripe(struct stripe_head *sh)
 		rcu_read_unlock();
  
 		if (rdev) {
-			if (test_bit(R5_Syncio, &sh->dev[i].flags))
+			if (syncing)
 				md_sync_acct(rdev->bdev, STRIPE_SECTORS);
 
 			bi->bi_bdev = rdev->bdev;
@@ -1409,6 +1400,9 @@ static void handle_stripe(struct stripe_head *sh)
 			bi->bi_io_vec[0].bv_offset = 0;
 			bi->bi_size = STRIPE_SIZE;
 			bi->bi_next = NULL;
+			if (rw == WRITE &&
+			    test_bit(R5_ReWrite, &sh->dev[i].flags))
+				atomic_add(STRIPE_SECTORS, &rdev->corrected_errors);
 			generic_make_request(bi);
 		} else {
 			if (rw == 1)
@@ -1822,21 +1816,21 @@ static int run(mddev_t *mddev)
 	struct list_head *tmp;
 
 	if (mddev->level != 5 && mddev->level != 4) {
-		printk("raid5: %s: raid level not set to 4/5 (%d)\n", mdname(mddev), mddev->level);
+		printk(KERN_ERR "raid5: %s: raid level not set to 4/5 (%d)\n",
+		       mdname(mddev), mddev->level);
 		return -EIO;
 	}
 
-	mddev->private = kmalloc (sizeof (raid5_conf_t)
-				  + mddev->raid_disks * sizeof(struct disk_info),
-				  GFP_KERNEL);
+	mddev->private = kzalloc(sizeof (raid5_conf_t)
+				 + mddev->raid_disks * sizeof(struct disk_info),
+				 GFP_KERNEL);
 	if ((conf = mddev->private) == NULL)
 		goto abort;
-	memset (conf, 0, sizeof (*conf) + mddev->raid_disks * sizeof(struct disk_info) );
+
 	conf->mddev = mddev;
 
-	if ((conf->stripe_hashtbl = (struct stripe_head **) __get_free_pages(GFP_ATOMIC, HASH_PAGES_ORDER)) == NULL)
+	if ((conf->stripe_hashtbl = kzalloc(PAGE_SIZE, GFP_KERNEL)) == NULL)
 		goto abort;
-	memset(conf->stripe_hashtbl, 0, HASH_PAGES * PAGE_SIZE);
 
 	spin_lock_init(&conf->device_lock);
 	init_waitqueue_head(&conf->wait_for_stripe);
@@ -1903,10 +1897,17 @@ static int run(mddev_t *mddev)
 
 	if (mddev->degraded == 1 &&
 	    mddev->recovery_cp != MaxSector) {
-		printk(KERN_ERR 
-			"raid5: cannot start dirty degraded array for %s\n",
-			mdname(mddev));
-		goto abort;
+		if (mddev->ok_start_degraded)
+			printk(KERN_WARNING
+			       "raid5: starting dirty degraded array: %s"
+			       "- data corruption possible.\n",
+			       mdname(mddev));
+		else {
+			printk(KERN_ERR
+			       "raid5: cannot start dirty degraded array for %s\n",
+			       mdname(mddev));
+			goto abort;
+		}
 	}
 
 	{
@@ -1948,7 +1949,7 @@ static int run(mddev_t *mddev)
 	 */
 	{
 		int stripe = (mddev->raid_disks-1) * mddev->chunk_size
-			/ PAGE_CACHE_SIZE;
+			/ PAGE_SIZE;
 		if (mddev->queue->backing_dev_info.ra_pages < 2 * stripe)
 			mddev->queue->backing_dev_info.ra_pages = 2 * stripe;
 	}
@@ -1956,9 +1957,6 @@ static int run(mddev_t *mddev)
 	/* Ok, everything is just fine now */
 	sysfs_create_group(&mddev->kobj, &raid5_attrs_group);
 
-	if (mddev->bitmap)
-		mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
-
 	mddev->queue->unplug_fn = raid5_unplug_device;
 	mddev->queue->issue_flush_fn = raid5_issue_flush;
 
@@ -1967,9 +1965,7 @@ static int run(mddev_t *mddev)
 abort:
 	if (conf) {
 		print_raid5_conf(conf);
-		if (conf->stripe_hashtbl)
-			free_pages((unsigned long) conf->stripe_hashtbl,
-							HASH_PAGES_ORDER);
+		kfree(conf->stripe_hashtbl);
 		kfree(conf);
 	}
 	mddev->private = NULL;
@@ -1986,7 +1982,7 @@ static int stop(mddev_t *mddev)
 	md_unregister_thread(mddev->thread);
 	mddev->thread = NULL;
 	shrink_stripes(conf);
-	free_pages((unsigned long) conf->stripe_hashtbl, HASH_PAGES_ORDER);
+	kfree(conf->stripe_hashtbl);
 	blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
 	sysfs_remove_group(&mddev->kobj, &raid5_attrs_group);
 	kfree(conf);
@@ -2014,12 +2010,12 @@ static void print_sh (struct stripe_head *sh)
 static void printall (raid5_conf_t *conf)
 {
 	struct stripe_head *sh;
+	struct hlist_node *hn;
 	int i;
 
 	spin_lock_irq(&conf->device_lock);
 	for (i = 0; i < NR_HASH; i++) {
-		sh = conf->stripe_hashtbl[i];
-		for (; sh; sh = sh->hash_next) {
+		hlist_for_each_entry(sh, hn, &conf->stripe_hashtbl[i], hash) {
 			if (sh->raid_conf != conf)
 				continue;
 			print_sh(sh);
@@ -2192,17 +2188,12 @@ static void raid5_quiesce(mddev_t *mddev, int state)
 		spin_unlock_irq(&conf->device_lock);
 		break;
 	}
-	if (mddev->thread) {
-		if (mddev->bitmap)
-			mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
-		else
-			mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT;
-		md_wakeup_thread(mddev->thread);
-	}
 }
-static mdk_personality_t raid5_personality=
+
+static struct mdk_personality raid5_personality =
 {
 	.name		= "raid5",
+	.level		= 5,
 	.owner		= THIS_MODULE,
 	.make_request	= make_request,
 	.run		= run,
@@ -2217,17 +2208,42 @@ static mdk_personality_t raid5_personality=
 	.quiesce	= raid5_quiesce,
 };
 
-static int __init raid5_init (void)
+static struct mdk_personality raid4_personality =
 {
-	return register_md_personality (RAID5, &raid5_personality);
+	.name		= "raid4",
+	.level		= 4,
+	.owner		= THIS_MODULE,
+	.make_request	= make_request,
+	.run		= run,
+	.stop		= stop,
+	.status		= status,
+	.error_handler	= error,
+	.hot_add_disk	= raid5_add_disk,
+	.hot_remove_disk= raid5_remove_disk,
+	.spare_active	= raid5_spare_active,
+	.sync_request	= sync_request,
+	.resize		= raid5_resize,
+	.quiesce	= raid5_quiesce,
+};
+
+static int __init raid5_init(void)
+{
+	register_md_personality(&raid5_personality);
+	register_md_personality(&raid4_personality);
+	return 0;
 }
 
-static void raid5_exit (void)
+static void raid5_exit(void)
 {
-	unregister_md_personality (RAID5);
+	unregister_md_personality(&raid5_personality);
+	unregister_md_personality(&raid4_personality);
 }
 
 module_init(raid5_init);
 module_exit(raid5_exit);
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("md-personality-4"); /* RAID5 */
+MODULE_ALIAS("md-raid5");
+MODULE_ALIAS("md-raid4");
+MODULE_ALIAS("md-level-5");
+MODULE_ALIAS("md-level-4");
diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c
index 0000d162d198..8c823d686a60 100644
--- a/drivers/md/raid6main.c
+++ b/drivers/md/raid6main.c
@@ -40,12 +40,10 @@
 #define STRIPE_SHIFT		(PAGE_SHIFT - 9)
 #define STRIPE_SECTORS		(STRIPE_SIZE>>9)
 #define	IO_THRESHOLD		1
-#define HASH_PAGES		1
-#define HASH_PAGES_ORDER	0
-#define NR_HASH			(HASH_PAGES * PAGE_SIZE / sizeof(struct stripe_head *))
+#define NR_HASH			(PAGE_SIZE / sizeof(struct hlist_head))
 #define HASH_MASK		(NR_HASH - 1)
 
-#define stripe_hash(conf, sect)	((conf)->stripe_hashtbl[((sect) >> STRIPE_SHIFT) & HASH_MASK])
+#define stripe_hash(conf, sect)	(&((conf)->stripe_hashtbl[((sect) >> STRIPE_SHIFT) & HASH_MASK]))
 
 /* bio's attached to a stripe+device for I/O are linked together in bi_sector
  * order without overlap.  There may be several bio's per stripe+device, and
@@ -132,29 +130,21 @@ static void release_stripe(struct stripe_head *sh)
 	spin_unlock_irqrestore(&conf->device_lock, flags);
 }
 
-static void remove_hash(struct stripe_head *sh)
+static inline void remove_hash(struct stripe_head *sh)
 {
 	PRINTK("remove_hash(), stripe %llu\n", (unsigned long long)sh->sector);
 
-	if (sh->hash_pprev) {
-		if (sh->hash_next)
-			sh->hash_next->hash_pprev = sh->hash_pprev;
-		*sh->hash_pprev = sh->hash_next;
-		sh->hash_pprev = NULL;
-	}
+	hlist_del_init(&sh->hash);
 }
 
-static __inline__ void insert_hash(raid6_conf_t *conf, struct stripe_head *sh)
+static inline void insert_hash(raid6_conf_t *conf, struct stripe_head *sh)
 {
-	struct stripe_head **shp = &stripe_hash(conf, sh->sector);
+	struct hlist_head *hp = stripe_hash(conf, sh->sector);
 
 	PRINTK("insert_hash(), stripe %llu\n", (unsigned long long)sh->sector);
 
 	CHECK_DEVLOCK();
-	if ((sh->hash_next = *shp) != NULL)
-		(*shp)->hash_pprev = &sh->hash_next;
-	*shp = sh;
-	sh->hash_pprev = shp;
+	hlist_add_head(&sh->hash, hp);
 }
 
 
@@ -186,7 +176,7 @@ static void shrink_buffers(struct stripe_head *sh, int num)
 		if (!p)
 			continue;
 		sh->dev[i].page = NULL;
-		page_cache_release(p);
+		put_page(p);
 	}
 }
 
@@ -247,10 +237,11 @@ static inline void init_stripe(struct stripe_head *sh, sector_t sector, int pd_i
 static struct stripe_head *__find_stripe(raid6_conf_t *conf, sector_t sector)
 {
 	struct stripe_head *sh;
+	struct hlist_node *hn;
 
 	CHECK_DEVLOCK();
 	PRINTK("__find_stripe, sector %llu\n", (unsigned long long)sector);
-	for (sh = stripe_hash(conf, sector); sh; sh = sh->hash_next)
+	hlist_for_each_entry (sh, hn,  stripe_hash(conf, sector), hash)
 		if (sh->sector == sector)
 			return sh;
 	PRINTK("__stripe %llu not in cache\n", (unsigned long long)sector);
@@ -367,8 +358,8 @@ static void shrink_stripes(raid6_conf_t *conf)
 	conf->slab_cache = NULL;
 }
 
-static int raid6_end_read_request (struct bio * bi, unsigned int bytes_done,
-				   int error)
+static int raid6_end_read_request(struct bio * bi, unsigned int bytes_done,
+				  int error)
 {
  	struct stripe_head *sh = bi->bi_private;
 	raid6_conf_t *conf = sh->raid_conf;
@@ -420,9 +411,35 @@ static int raid6_end_read_request (struct bio * bi, unsigned int bytes_done,
 #else
 		set_bit(R5_UPTODATE, &sh->dev[i].flags);
 #endif
+		if (test_bit(R5_ReadError, &sh->dev[i].flags)) {
+			printk(KERN_INFO "raid6: read error corrected!!\n");
+			clear_bit(R5_ReadError, &sh->dev[i].flags);
+			clear_bit(R5_ReWrite, &sh->dev[i].flags);
+		}
+		if (atomic_read(&conf->disks[i].rdev->read_errors))
+			atomic_set(&conf->disks[i].rdev->read_errors, 0);
 	} else {
-		md_error(conf->mddev, conf->disks[i].rdev);
+		int retry = 0;
 		clear_bit(R5_UPTODATE, &sh->dev[i].flags);
+		atomic_inc(&conf->disks[i].rdev->read_errors);
+		if (conf->mddev->degraded)
+			printk(KERN_WARNING "raid6: read error not correctable.\n");
+		else if (test_bit(R5_ReWrite, &sh->dev[i].flags))
+			/* Oh, no!!! */
+			printk(KERN_WARNING "raid6: read error NOT corrected!!\n");
+		else if (atomic_read(&conf->disks[i].rdev->read_errors)
+			 > conf->max_nr_stripes)
+			printk(KERN_WARNING
+			       "raid6: Too many read errors, failing device.\n");
+		else
+			retry = 1;
+		if (retry)
+			set_bit(R5_ReadError, &sh->dev[i].flags);
+		else {
+			clear_bit(R5_ReadError, &sh->dev[i].flags);
+			clear_bit(R5_ReWrite, &sh->dev[i].flags);
+			md_error(conf->mddev, conf->disks[i].rdev);
+		}
 	}
 	rdev_dec_pending(conf->disks[i].rdev, conf->mddev);
 #if 0
@@ -805,7 +822,7 @@ static void compute_parity(struct stripe_head *sh, int method)
 }
 
 /* Compute one missing block */
-static void compute_block_1(struct stripe_head *sh, int dd_idx)
+static void compute_block_1(struct stripe_head *sh, int dd_idx, int nozero)
 {
 	raid6_conf_t *conf = sh->raid_conf;
 	int i, count, disks = conf->raid_disks;
@@ -821,7 +838,7 @@ static void compute_block_1(struct stripe_head *sh, int dd_idx)
 		compute_parity(sh, UPDATE_PARITY);
 	} else {
 		ptr[0] = page_address(sh->dev[dd_idx].page);
-		memset(ptr[0], 0, STRIPE_SIZE);
+		if (!nozero) memset(ptr[0], 0, STRIPE_SIZE);
 		count = 1;
 		for (i = disks ; i--; ) {
 			if (i == dd_idx || i == qd_idx)
@@ -838,7 +855,8 @@ static void compute_block_1(struct stripe_head *sh, int dd_idx)
 		}
 		if (count != 1)
 			xor_block(count, STRIPE_SIZE, ptr);
-		set_bit(R5_UPTODATE, &sh->dev[dd_idx].flags);
+		if (!nozero) set_bit(R5_UPTODATE, &sh->dev[dd_idx].flags);
+		else clear_bit(R5_UPTODATE, &sh->dev[dd_idx].flags);
 	}
 }
 
@@ -871,7 +889,7 @@ static void compute_block_2(struct stripe_head *sh, int dd_idx1, int dd_idx2)
 			return;
 		} else {
 			/* We're missing D+Q; recompute D from P */
-			compute_block_1(sh, (dd_idx1 == qd_idx) ? dd_idx2 : dd_idx1);
+			compute_block_1(sh, (dd_idx1 == qd_idx) ? dd_idx2 : dd_idx1, 0);
 			compute_parity(sh, UPDATE_PARITY); /* Is this necessary? */
 			return;
 		}
@@ -982,6 +1000,12 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
 }
 
 
+static int page_is_zero(struct page *p)
+{
+	char *a = page_address(p);
+	return ((*(u32*)a) == 0 &&
+		memcmp(a, a+4, STRIPE_SIZE-4)==0);
+}
 /*
  * handle_stripe - do things to a stripe.
  *
@@ -1000,7 +1024,7 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
  *
  */
 
-static void handle_stripe(struct stripe_head *sh)
+static void handle_stripe(struct stripe_head *sh, struct page *tmp_page)
 {
 	raid6_conf_t *conf = sh->raid_conf;
 	int disks = conf->raid_disks;
@@ -1027,11 +1051,11 @@ static void handle_stripe(struct stripe_head *sh)
 	syncing = test_bit(STRIPE_SYNCING, &sh->state);
 	/* Now to look around and see what can be done */
 
+	rcu_read_lock();
 	for (i=disks; i--; ) {
 		mdk_rdev_t *rdev;
 		dev = &sh->dev[i];
 		clear_bit(R5_Insync, &dev->flags);
-		clear_bit(R5_Syncio, &dev->flags);
 
 		PRINTK("check %d: state 0x%lx read %p write %p written %p\n",
 			i, dev->flags, dev->toread, dev->towrite, dev->written);
@@ -1070,14 +1094,21 @@ static void handle_stripe(struct stripe_head *sh)
 				non_overwrite++;
 		}
 		if (dev->written) written++;
-		rdev = conf->disks[i].rdev; /* FIXME, should I be looking rdev */
+		rdev = rcu_dereference(conf->disks[i].rdev);
 		if (!rdev || !test_bit(In_sync, &rdev->flags)) {
+			/* The ReadError flag will just be confusing now */
+			clear_bit(R5_ReadError, &dev->flags);
+			clear_bit(R5_ReWrite, &dev->flags);
+		}
+		if (!rdev || !test_bit(In_sync, &rdev->flags)
+		    || test_bit(R5_ReadError, &dev->flags)) {
 			if ( failed < 2 )
 				failed_num[failed] = i;
 			failed++;
 		} else
 			set_bit(R5_Insync, &dev->flags);
 	}
+	rcu_read_unlock();
 	PRINTK("locked=%d uptodate=%d to_read=%d"
 	       " to_write=%d failed=%d failed_num=%d,%d\n",
 	       locked, uptodate, to_read, to_write, failed,
@@ -1088,6 +1119,17 @@ static void handle_stripe(struct stripe_head *sh)
 	if (failed > 2 && to_read+to_write+written) {
 		for (i=disks; i--; ) {
 			int bitmap_end = 0;
+
+			if (test_bit(R5_ReadError, &sh->dev[i].flags)) {
+				mdk_rdev_t *rdev;
+				rcu_read_lock();
+				rdev = rcu_dereference(conf->disks[i].rdev);
+				if (rdev && test_bit(In_sync, &rdev->flags))
+					/* multiple read failures in one stripe */
+					md_error(conf->mddev, rdev);
+				rcu_read_unlock();
+			}
+
 			spin_lock_irq(&conf->device_lock);
 			/* fail all writes first */
 			bi = sh->dev[i].towrite;
@@ -1123,7 +1165,8 @@ static void handle_stripe(struct stripe_head *sh)
 			}
 
 			/* fail any reads if this device is non-operational */
-			if (!test_bit(R5_Insync, &sh->dev[i].flags)) {
+			if (!test_bit(R5_Insync, &sh->dev[i].flags) ||
+			    test_bit(R5_ReadError, &sh->dev[i].flags)) {
 				bi = sh->dev[i].toread;
 				sh->dev[i].toread = NULL;
 				if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
@@ -1228,7 +1271,7 @@ static void handle_stripe(struct stripe_head *sh)
 				if (uptodate == disks-1) {
 					PRINTK("Computing stripe %llu block %d\n",
 					       (unsigned long long)sh->sector, i);
-					compute_block_1(sh, i);
+					compute_block_1(sh, i, 0);
 					uptodate++;
 				} else if ( uptodate == disks-2 && failed >= 2 ) {
 					/* Computing 2-failure is *very* expensive; only do it if failed >= 2 */
@@ -1259,9 +1302,6 @@ static void handle_stripe(struct stripe_head *sh)
 					locked++;
 					PRINTK("Reading block %d (sync=%d)\n",
 						i, syncing);
-					if (syncing)
-						md_sync_acct(conf->disks[i].rdev->bdev,
-							     STRIPE_SECTORS);
 				}
 			}
 		}
@@ -1323,7 +1363,7 @@ static void handle_stripe(struct stripe_head *sh)
 				/* We have failed blocks and need to compute them */
 				switch ( failed ) {
 				case 0:	BUG();
-				case 1: compute_block_1(sh, failed_num[0]); break;
+				case 1: compute_block_1(sh, failed_num[0], 0); break;
 				case 2: compute_block_2(sh, failed_num[0], failed_num[1]); break;
 				default: BUG();	/* This request should have been failed? */
 				}
@@ -1338,12 +1378,10 @@ static void handle_stripe(struct stripe_head *sh)
 					       (unsigned long long)sh->sector, i);
 					locked++;
 					set_bit(R5_Wantwrite, &sh->dev[i].flags);
-#if 0 /**** FIX: I don't understand the logic here... ****/
-					if (!test_bit(R5_Insync, &sh->dev[i].flags)
-					    || ((i==pd_idx || i==qd_idx) && failed == 0)) /* FIX? */
-						set_bit(STRIPE_INSYNC, &sh->state);
-#endif
 				}
+			/* after a RECONSTRUCT_WRITE, the stripe MUST be in-sync */
+			set_bit(STRIPE_INSYNC, &sh->state);
+
 			if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
 				atomic_dec(&conf->preread_active_stripes);
 				if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD)
@@ -1356,84 +1394,119 @@ static void handle_stripe(struct stripe_head *sh)
 	 * Any reads will already have been scheduled, so we just see if enough data
 	 * is available
 	 */
-	if (syncing && locked == 0 &&
-	    !test_bit(STRIPE_INSYNC, &sh->state) && failed <= 2) {
-		set_bit(STRIPE_HANDLE, &sh->state);
-#if 0 /* RAID-6: Don't support CHECK PARITY yet */
-		if (failed == 0) {
-			char *pagea;
-			if (uptodate != disks)
-				BUG();
-			compute_parity(sh, CHECK_PARITY);
-			uptodate--;
-			pagea = page_address(sh->dev[pd_idx].page);
-			if ((*(u32*)pagea) == 0 &&
-			    !memcmp(pagea, pagea+4, STRIPE_SIZE-4)) {
-				/* parity is correct (on disc, not in buffer any more) */
-				set_bit(STRIPE_INSYNC, &sh->state);
-			}
-		}
-#endif
-		if (!test_bit(STRIPE_INSYNC, &sh->state)) {
-			int failed_needupdate[2];
-			struct r5dev *adev, *bdev;
-
-			if ( failed < 1 )
-				failed_num[0] = pd_idx;
-			if ( failed < 2 )
-				failed_num[1] = (failed_num[0] == qd_idx) ? pd_idx : qd_idx;
+	if (syncing && locked == 0 && !test_bit(STRIPE_INSYNC, &sh->state)) {
+		int update_p = 0, update_q = 0;
+		struct r5dev *dev;
 
-			failed_needupdate[0] = !test_bit(R5_UPTODATE, &sh->dev[failed_num[0]].flags);
-			failed_needupdate[1] = !test_bit(R5_UPTODATE, &sh->dev[failed_num[1]].flags);
+		set_bit(STRIPE_HANDLE, &sh->state);
 
-			PRINTK("sync: failed=%d num=%d,%d fnu=%u%u\n",
-			       failed, failed_num[0], failed_num[1], failed_needupdate[0], failed_needupdate[1]);
+		BUG_ON(failed>2);
+		BUG_ON(uptodate < disks);
+		/* Want to check and possibly repair P and Q.
+		 * However there could be one 'failed' device, in which
+		 * case we can only check one of them, possibly using the
+		 * other to generate missing data
+		 */
 
-#if 0  /* RAID-6: This code seems to require that CHECK_PARITY destroys the uptodateness of the parity */
-			/* should be able to compute the missing block(s) and write to spare */
-			if ( failed_needupdate[0] ^ failed_needupdate[1] ) {
-				if (uptodate+1 != disks)
-					BUG();
-				compute_block_1(sh, failed_needupdate[0] ? failed_num[0] : failed_num[1]);
-				uptodate++;
-			} else if ( failed_needupdate[0] & failed_needupdate[1] ) {
-				if (uptodate+2 != disks)
-					BUG();
-				compute_block_2(sh, failed_num[0], failed_num[1]);
-				uptodate += 2;
+		/* If !tmp_page, we cannot do the calculations,
+		 * but as we have set STRIPE_HANDLE, we will soon be called
+		 * by stripe_handle with a tmp_page - just wait until then.
+		 */
+		if (tmp_page) {
+			if (failed == q_failed) {
+				/* The only possible failed device holds 'Q', so it makes
+				 * sense to check P (If anything else were failed, we would
+				 * have used P to recreate it).
+				 */
+				compute_block_1(sh, pd_idx, 1);
+				if (!page_is_zero(sh->dev[pd_idx].page)) {
+					compute_block_1(sh,pd_idx,0);
+					update_p = 1;
+				}
+			}
+			if (!q_failed && failed < 2) {
+				/* q is not failed, and we didn't use it to generate
+				 * anything, so it makes sense to check it
+				 */
+				memcpy(page_address(tmp_page),
+				       page_address(sh->dev[qd_idx].page),
+				       STRIPE_SIZE);
+				compute_parity(sh, UPDATE_PARITY);
+				if (memcmp(page_address(tmp_page),
+					   page_address(sh->dev[qd_idx].page),
+					   STRIPE_SIZE)!= 0) {
+					clear_bit(STRIPE_INSYNC, &sh->state);
+					update_q = 1;
+				}
+			}
+			if (update_p || update_q) {
+				conf->mddev->resync_mismatches += STRIPE_SECTORS;
+				if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery))
+					/* don't try to repair!! */
+					update_p = update_q = 0;
 			}
-#else
-			compute_block_2(sh, failed_num[0], failed_num[1]);
-			uptodate += failed_needupdate[0] + failed_needupdate[1];
-#endif
 
-			if (uptodate != disks)
-				BUG();
+			/* now write out any block on a failed drive,
+			 * or P or Q if they need it
+			 */
 
-			PRINTK("Marking for sync stripe %llu blocks %d,%d\n",
-			       (unsigned long long)sh->sector, failed_num[0], failed_num[1]);
+			if (failed == 2) {
+				dev = &sh->dev[failed_num[1]];
+				locked++;
+				set_bit(R5_LOCKED, &dev->flags);
+				set_bit(R5_Wantwrite, &dev->flags);
+			}
+			if (failed >= 1) {
+				dev = &sh->dev[failed_num[0]];
+				locked++;
+				set_bit(R5_LOCKED, &dev->flags);
+				set_bit(R5_Wantwrite, &dev->flags);
+			}
 
-			/**** FIX: Should we really do both of these unconditionally? ****/
-			adev = &sh->dev[failed_num[0]];
-			locked += !test_bit(R5_LOCKED, &adev->flags);
-			set_bit(R5_LOCKED, &adev->flags);
-			set_bit(R5_Wantwrite, &adev->flags);
-			bdev = &sh->dev[failed_num[1]];
-			locked += !test_bit(R5_LOCKED, &bdev->flags);
-			set_bit(R5_LOCKED, &bdev->flags);
+			if (update_p) {
+				dev = &sh->dev[pd_idx];
+				locked ++;
+				set_bit(R5_LOCKED, &dev->flags);
+				set_bit(R5_Wantwrite, &dev->flags);
+			}
+			if (update_q) {
+				dev = &sh->dev[qd_idx];
+				locked++;
+				set_bit(R5_LOCKED, &dev->flags);
+				set_bit(R5_Wantwrite, &dev->flags);
+			}
 			clear_bit(STRIPE_DEGRADED, &sh->state);
-			set_bit(R5_Wantwrite, &bdev->flags);
 
 			set_bit(STRIPE_INSYNC, &sh->state);
-			set_bit(R5_Syncio, &adev->flags);
-			set_bit(R5_Syncio, &bdev->flags);
 		}
 	}
+
 	if (syncing && locked == 0 && test_bit(STRIPE_INSYNC, &sh->state)) {
 		md_done_sync(conf->mddev, STRIPE_SECTORS,1);
 		clear_bit(STRIPE_SYNCING, &sh->state);
 	}
 
+	/* If the failed drives are just a ReadError, then we might need
+	 * to progress the repair/check process
+	 */
+	if (failed <= 2 && ! conf->mddev->ro)
+		for (i=0; i<failed;i++) {
+			dev = &sh->dev[failed_num[i]];
+			if (test_bit(R5_ReadError, &dev->flags)
+			    && !test_bit(R5_LOCKED, &dev->flags)
+			    && test_bit(R5_UPTODATE, &dev->flags)
+				) {
+				if (!test_bit(R5_ReWrite, &dev->flags)) {
+					set_bit(R5_Wantwrite, &dev->flags);
+					set_bit(R5_ReWrite, &dev->flags);
+					set_bit(R5_LOCKED, &dev->flags);
+				} else {
+					/* let's read it back */
+					set_bit(R5_Wantread, &dev->flags);
+					set_bit(R5_LOCKED, &dev->flags);
+				}
+			}
+		}
 	spin_unlock(&sh->lock);
 
 	while ((bi=return_bi)) {
@@ -1472,7 +1545,7 @@ static void handle_stripe(struct stripe_head *sh)
 		rcu_read_unlock();
 
 		if (rdev) {
-			if (test_bit(R5_Syncio, &sh->dev[i].flags))
+			if (syncing)
 				md_sync_acct(rdev->bdev, STRIPE_SECTORS);
 
 			bi->bi_bdev = rdev->bdev;
@@ -1489,6 +1562,9 @@ static void handle_stripe(struct stripe_head *sh)
 			bi->bi_io_vec[0].bv_offset = 0;
 			bi->bi_size = STRIPE_SIZE;
 			bi->bi_next = NULL;
+			if (rw == WRITE &&
+			    test_bit(R5_ReWrite, &sh->dev[i].flags))
+				atomic_add(STRIPE_SECTORS, &rdev->corrected_errors);
 			generic_make_request(bi);
 		} else {
 			if (rw == 1)
@@ -1664,7 +1740,7 @@ static int make_request (request_queue_t *q, struct bio * bi)
 			}
 			finish_wait(&conf->wait_for_overlap, &w);
 			raid6_plug_device(conf);
-			handle_stripe(sh);
+			handle_stripe(sh, NULL);
 			release_stripe(sh);
 		} else {
 			/* cannot get stripe for read-ahead, just give-up */
@@ -1728,6 +1804,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
 		return rv;
 	}
 	if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 1) &&
+	    !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery) &&
 	    !conf->fullsync && sync_blocks >= STRIPE_SECTORS) {
 		/* we can skip this block, and probably more */
 		sync_blocks /= STRIPE_SECTORS;
@@ -1765,7 +1842,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
 	clear_bit(STRIPE_INSYNC, &sh->state);
 	spin_unlock(&sh->lock);
 
-	handle_stripe(sh);
+	handle_stripe(sh, NULL);
 	release_stripe(sh);
 
 	return STRIPE_SECTORS;
@@ -1821,7 +1898,7 @@ static void raid6d (mddev_t *mddev)
 		spin_unlock_irq(&conf->device_lock);
 
 		handled++;
-		handle_stripe(sh);
+		handle_stripe(sh, conf->spare_page);
 		release_stripe(sh);
 
 		spin_lock_irq(&conf->device_lock);
@@ -1848,17 +1925,19 @@ static int run(mddev_t *mddev)
 		return -EIO;
 	}
 
-	mddev->private = kmalloc (sizeof (raid6_conf_t)
-				  + mddev->raid_disks * sizeof(struct disk_info),
-				  GFP_KERNEL);
+	mddev->private = kzalloc(sizeof (raid6_conf_t)
+				 + mddev->raid_disks * sizeof(struct disk_info),
+				 GFP_KERNEL);
 	if ((conf = mddev->private) == NULL)
 		goto abort;
-	memset (conf, 0, sizeof (*conf) + mddev->raid_disks * sizeof(struct disk_info) );
 	conf->mddev = mddev;
 
-	if ((conf->stripe_hashtbl = (struct stripe_head **) __get_free_pages(GFP_ATOMIC, HASH_PAGES_ORDER)) == NULL)
+	if ((conf->stripe_hashtbl = kzalloc(PAGE_SIZE, GFP_KERNEL)) == NULL)
+		goto abort;
+
+	conf->spare_page = alloc_page(GFP_KERNEL);
+	if (!conf->spare_page)
 		goto abort;
-	memset(conf->stripe_hashtbl, 0, HASH_PAGES * PAGE_SIZE);
 
 	spin_lock_init(&conf->device_lock);
 	init_waitqueue_head(&conf->wait_for_stripe);
@@ -1929,13 +2008,18 @@ static int run(mddev_t *mddev)
 		goto abort;
 	}
 
-#if 0				/* FIX: For now */
 	if (mddev->degraded > 0 &&
 	    mddev->recovery_cp != MaxSector) {
-		printk(KERN_ERR "raid6: cannot start dirty degraded array for %s\n", mdname(mddev));
-		goto abort;
+		if (mddev->ok_start_degraded)
+			printk(KERN_WARNING "raid6: starting dirty degraded array:%s"
+			       "- data corruption possible.\n",
+			       mdname(mddev));
+		else {
+			printk(KERN_ERR "raid6: cannot start dirty degraded array"
+			       " for %s\n", mdname(mddev));
+			goto abort;
+		}
 	}
-#endif
 
 	{
 		mddev->thread = md_register_thread(raid6d, mddev, "%s_raid6");
@@ -1977,7 +2061,7 @@ static int run(mddev_t *mddev)
 	 */
 	{
 		int stripe = (mddev->raid_disks-2) * mddev->chunk_size
-			/ PAGE_CACHE_SIZE;
+			/ PAGE_SIZE;
 		if (mddev->queue->backing_dev_info.ra_pages < 2 * stripe)
 			mddev->queue->backing_dev_info.ra_pages = 2 * stripe;
 	}
@@ -1985,18 +2069,14 @@ static int run(mddev_t *mddev)
 	/* Ok, everything is just fine now */
 	mddev->array_size =  mddev->size * (mddev->raid_disks - 2);
 
-	if (mddev->bitmap)
-		mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
-
 	mddev->queue->unplug_fn = raid6_unplug_device;
 	mddev->queue->issue_flush_fn = raid6_issue_flush;
 	return 0;
 abort:
 	if (conf) {
 		print_raid6_conf(conf);
-		if (conf->stripe_hashtbl)
-			free_pages((unsigned long) conf->stripe_hashtbl,
-							HASH_PAGES_ORDER);
+		safe_put_page(conf->spare_page);
+		kfree(conf->stripe_hashtbl);
 		kfree(conf);
 	}
 	mddev->private = NULL;
@@ -2013,7 +2093,7 @@ static int stop (mddev_t *mddev)
 	md_unregister_thread(mddev->thread);
 	mddev->thread = NULL;
 	shrink_stripes(conf);
-	free_pages((unsigned long) conf->stripe_hashtbl, HASH_PAGES_ORDER);
+	kfree(conf->stripe_hashtbl);
 	blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
 	kfree(conf);
 	mddev->private = NULL;
@@ -2040,12 +2120,13 @@ static void print_sh (struct seq_file *seq, struct stripe_head *sh)
 static void printall (struct seq_file *seq, raid6_conf_t *conf)
 {
 	struct stripe_head *sh;
+	struct hlist_node *hn;
 	int i;
 
 	spin_lock_irq(&conf->device_lock);
 	for (i = 0; i < NR_HASH; i++) {
 		sh = conf->stripe_hashtbl[i];
-		for (; sh; sh = sh->hash_next) {
+		hlist_for_each_entry(sh, hn, &conf->stripe_hashtbl[i], hash) {
 			if (sh->raid_conf != conf)
 				continue;
 			print_sh(seq, sh);
@@ -2223,17 +2304,12 @@ static void raid6_quiesce(mddev_t *mddev, int state)
 		spin_unlock_irq(&conf->device_lock);
 		break;
 	}
-	if (mddev->thread) {
-		if (mddev->bitmap)
-			mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
-		else
-			mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT;
-		md_wakeup_thread(mddev->thread);
-	}
 }
-static mdk_personality_t raid6_personality=
+
+static struct mdk_personality raid6_personality =
 {
 	.name		= "raid6",
+	.level		= 6,
 	.owner		= THIS_MODULE,
 	.make_request	= make_request,
 	.run		= run,
@@ -2248,7 +2324,7 @@ static mdk_personality_t raid6_personality=
 	.quiesce	= raid6_quiesce,
 };
 
-static int __init raid6_init (void)
+static int __init raid6_init(void)
 {
 	int e;
 
@@ -2256,15 +2332,17 @@ static int __init raid6_init (void)
 	if ( e )
 		return e;
 
-	return register_md_personality (RAID6, &raid6_personality);
+	return register_md_personality(&raid6_personality);
 }
 
 static void raid6_exit (void)
 {
-	unregister_md_personality (RAID6);
+	unregister_md_personality(&raid6_personality);
 }
 
 module_init(raid6_init);
 module_exit(raid6_exit);
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("md-personality-8"); /* RAID6 */
+MODULE_ALIAS("md-raid6");
+MODULE_ALIAS("md-level-6");
diff --git a/drivers/media/dvb/b2c2/flexcop-usb.c b/drivers/media/dvb/b2c2/flexcop-usb.c
index 0a78ba3737a5..a6c91db40ad6 100644
--- a/drivers/media/dvb/b2c2/flexcop-usb.c
+++ b/drivers/media/dvb/b2c2/flexcop-usb.c
@@ -544,7 +544,6 @@ static struct usb_device_id flexcop_usb_table [] = {
 
 /* usb specific object needed to register this driver with the usb subsystem */
 static struct usb_driver flexcop_usb_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "b2c2_flexcop_usb",
 	.probe		= flexcop_usb_probe,
 	.disconnect = flexcop_usb_disconnect,
diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c
index 336fc284fa52..1d69bf031fb9 100644
--- a/drivers/media/dvb/cinergyT2/cinergyT2.c
+++ b/drivers/media/dvb/cinergyT2/cinergyT2.c
@@ -60,7 +60,7 @@ MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
 #define dprintk(level, args...)						\
 do {									\
 	if ((debug & level)) {						\
-		printk("%s: %s(): ", __stringify(KBUILD_MODNAME),	\
+		printk("%s: %s(): ", KBUILD_MODNAME,			\
 		       __FUNCTION__);					\
 		printk(args); }						\
 } while (0)
@@ -986,7 +986,6 @@ static const struct usb_device_id cinergyt2_table [] __devinitdata = {
 MODULE_DEVICE_TABLE(usb, cinergyt2_table);
 
 static struct usb_driver cinergyt2_driver = {
-	.owner	= THIS_MODULE,
 	.name	= "cinergyT2",
 	.probe	= cinergyt2_probe,
 	.disconnect	= cinergyt2_disconnect,
diff --git a/drivers/media/dvb/dvb-usb/a800.c b/drivers/media/dvb/dvb-usb/a800.c
index 8c7beffb045f..ce44aa6bbb83 100644
--- a/drivers/media/dvb/dvb-usb/a800.c
+++ b/drivers/media/dvb/dvb-usb/a800.c
@@ -144,7 +144,6 @@ static struct dvb_usb_properties a800_properties = {
 };
 
 static struct usb_driver a800_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "dvb_usb_a800",
 	.probe		= a800_probe,
 	.disconnect = dvb_usb_device_exit,
diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
index 3fe383f4bb4c..d05fab01cccd 100644
--- a/drivers/media/dvb/dvb-usb/cxusb.c
+++ b/drivers/media/dvb/dvb-usb/cxusb.c
@@ -241,7 +241,6 @@ static struct dvb_usb_properties cxusb_properties = {
 };
 
 static struct usb_driver cxusb_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "dvb_usb_cxusb",
 	.probe		= cxusb_probe,
 	.disconnect = dvb_usb_device_exit,
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mb.c b/drivers/media/dvb/dvb-usb/dibusb-mb.c
index aa271a2496d5..52ac3e5adf5d 100644
--- a/drivers/media/dvb/dvb-usb/dibusb-mb.c
+++ b/drivers/media/dvb/dvb-usb/dibusb-mb.c
@@ -373,7 +373,6 @@ static struct dvb_usb_properties artec_t1_usb2_properties = {
 };
 
 static struct usb_driver dibusb_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "dvb_usb_dibusb_mb",
 	.probe		= dibusb_probe,
 	.disconnect = dvb_usb_device_exit,
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mc.c b/drivers/media/dvb/dvb-usb/dibusb-mc.c
index 6a0912eab396..55802fba3c29 100644
--- a/drivers/media/dvb/dvb-usb/dibusb-mc.c
+++ b/drivers/media/dvb/dvb-usb/dibusb-mc.c
@@ -82,7 +82,6 @@ static struct dvb_usb_properties dibusb_mc_properties = {
 };
 
 static struct usb_driver dibusb_mc_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "dvb_usb_dibusb_mc",
 	.probe		= dibusb_mc_probe,
 	.disconnect = dvb_usb_device_exit,
diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c
index f98e306a5759..450417a9e64b 100644
--- a/drivers/media/dvb/dvb-usb/digitv.c
+++ b/drivers/media/dvb/dvb-usb/digitv.c
@@ -233,7 +233,6 @@ static struct dvb_usb_properties digitv_properties = {
 };
 
 static struct usb_driver digitv_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "dvb_usb_digitv",
 	.probe		= digitv_probe,
 	.disconnect = dvb_usb_device_exit,
diff --git a/drivers/media/dvb/dvb-usb/dtt200u.c b/drivers/media/dvb/dvb-usb/dtt200u.c
index b595476332cd..6e2bac873445 100644
--- a/drivers/media/dvb/dvb-usb/dtt200u.c
+++ b/drivers/media/dvb/dvb-usb/dtt200u.c
@@ -198,7 +198,6 @@ static struct dvb_usb_properties wt220u_properties = {
 
 /* usb specific object needed to register this driver with the usb subsystem */
 static struct usb_driver dtt200u_usb_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "dvb_usb_dtt200u",
 	.probe		= dtt200u_usb_probe,
 	.disconnect = dvb_usb_device_exit,
diff --git a/drivers/media/dvb/dvb-usb/nova-t-usb2.c b/drivers/media/dvb/dvb-usb/nova-t-usb2.c
index 1841a66427bf..fac48fc7a4ac 100644
--- a/drivers/media/dvb/dvb-usb/nova-t-usb2.c
+++ b/drivers/media/dvb/dvb-usb/nova-t-usb2.c
@@ -202,7 +202,6 @@ static struct dvb_usb_properties nova_t_properties = {
 };
 
 static struct usb_driver nova_t_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "dvb_usb_nova_t_usb2",
 	.probe		= nova_t_probe,
 	.disconnect = dvb_usb_device_exit,
diff --git a/drivers/media/dvb/dvb-usb/umt-010.c b/drivers/media/dvb/dvb-usb/umt-010.c
index 6fd67657c269..14f1911c79bb 100644
--- a/drivers/media/dvb/dvb-usb/umt-010.c
+++ b/drivers/media/dvb/dvb-usb/umt-010.c
@@ -128,7 +128,6 @@ static struct dvb_usb_properties umt_properties = {
 };
 
 static struct usb_driver umt_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "dvb_usb_umt_010",
 	.probe		= umt_probe,
 	.disconnect = dvb_usb_device_exit,
diff --git a/drivers/media/dvb/dvb-usb/vp702x.c b/drivers/media/dvb/dvb-usb/vp702x.c
index de13c04e8e64..afa00fdb5ec0 100644
--- a/drivers/media/dvb/dvb-usb/vp702x.c
+++ b/drivers/media/dvb/dvb-usb/vp702x.c
@@ -256,7 +256,6 @@ static struct dvb_usb_properties vp702x_properties = {
 
 /* usb specific object needed to register this driver with the usb subsystem */
 static struct usb_driver vp702x_usb_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "dvb-usb-vp702x",
 	.probe 		= vp702x_usb_probe,
 	.disconnect = dvb_usb_device_exit,
diff --git a/drivers/media/dvb/dvb-usb/vp7045.c b/drivers/media/dvb/dvb-usb/vp7045.c
index 75765e3a569c..3835235b68df 100644
--- a/drivers/media/dvb/dvb-usb/vp7045.c
+++ b/drivers/media/dvb/dvb-usb/vp7045.c
@@ -253,7 +253,6 @@ static struct dvb_usb_properties vp7045_properties = {
 
 /* usb specific object needed to register this driver with the usb subsystem */
 static struct usb_driver vp7045_usb_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "dvb_usb_vp7045",
 	.probe		= vp7045_usb_probe,
 	.disconnect = dvb_usb_device_exit,
diff --git a/drivers/media/dvb/ttpci/budget.h b/drivers/media/dvb/ttpci/budget.h
index fdaa3318ad3a..c8d48cfba277 100644
--- a/drivers/media/dvb/ttpci/budget.h
+++ b/drivers/media/dvb/ttpci/budget.h
@@ -19,7 +19,7 @@ extern int budget_debug;
 #endif
 
 #define dprintk(level,args...) \
-	    do { if ((budget_debug & level)) { printk("%s: %s(): ",__stringify(KBUILD_MODNAME), __FUNCTION__); printk(args); } } while (0)
+	    do { if ((budget_debug & level)) { printk("%s: %s(): ", KBUILD_MODNAME, __FUNCTION__); printk(args); } } while (0)
 
 struct budget_info {
 	char *name;
diff --git a/drivers/media/video/adv7170.c b/drivers/media/video/adv7170.c
index 1ca2b67aedfb..e61003de1d5f 100644
--- a/drivers/media/video/adv7170.c
+++ b/drivers/media/video/adv7170.c
@@ -420,7 +420,6 @@ adv7170_detect_client (struct i2c_adapter *adapter,
 	client->addr = address;
 	client->adapter = adapter;
 	client->driver = &i2c_driver_adv7170;
-	client->flags = I2C_CLIENT_ALLOW_USE;
 	if ((client->addr == I2C_ADV7170 >> 1) ||
 	    (client->addr == (I2C_ADV7170 >> 1) + 1)) {
 		dname = adv7170_name;
@@ -498,11 +497,11 @@ adv7170_detach_client (struct i2c_client *client)
 /* ----------------------------------------------------------------------- */
 
 static struct i2c_driver i2c_driver_adv7170 = {
-	.owner = THIS_MODULE,
-	.name = "adv7170",	/* name */
+	.driver = {
+		.name = "adv7170",	/* name */
+	},
 
 	.id = I2C_DRIVERID_ADV7170,
-	.flags = I2C_DF_NOTIFY,
 
 	.attach_adapter = adv7170_attach_adapter,
 	.detach_client = adv7170_detach_client,
diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c
index 173bca1e0295..6d9536a71ee4 100644
--- a/drivers/media/video/adv7175.c
+++ b/drivers/media/video/adv7175.c
@@ -470,7 +470,6 @@ adv7175_detect_client (struct i2c_adapter *adapter,
 	client->addr = address;
 	client->adapter = adapter;
 	client->driver = &i2c_driver_adv7175;
-	client->flags = I2C_CLIENT_ALLOW_USE;
 	if ((client->addr == I2C_ADV7175 >> 1) ||
 	    (client->addr == (I2C_ADV7175 >> 1) + 1)) {
 		dname = adv7175_name;
@@ -548,11 +547,11 @@ adv7175_detach_client (struct i2c_client *client)
 /* ----------------------------------------------------------------------- */
 
 static struct i2c_driver i2c_driver_adv7175 = {
-	.owner = THIS_MODULE,
-	.name = "adv7175",	/* name */
+	.driver = {
+		.name = "adv7175",	/* name */
+	},
 
 	.id = I2C_DRIVERID_ADV7175,
-	.flags = I2C_DF_NOTIFY,
 
 	.attach_adapter = adv7175_attach_adapter,
 	.detach_client = adv7175_detach_client,
diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c
index 3ee0afca76a7..560b99891753 100644
--- a/drivers/media/video/bt819.c
+++ b/drivers/media/video/bt819.c
@@ -535,7 +535,6 @@ bt819_detect_client (struct i2c_adapter *adapter,
 	client->addr = address;
 	client->adapter = adapter;
 	client->driver = &i2c_driver_bt819;
-	client->flags = I2C_CLIENT_ALLOW_USE;
 
 	decoder = kmalloc(sizeof(struct bt819), GFP_KERNEL);
 	if (decoder == NULL) {
@@ -623,11 +622,11 @@ bt819_detach_client (struct i2c_client *client)
 /* ----------------------------------------------------------------------- */
 
 static struct i2c_driver i2c_driver_bt819 = {
-	.owner = THIS_MODULE,
-	.name = "bt819",
+	.driver = {
+		.name = "bt819",
+	},
 
 	.id = I2C_DRIVERID_BT819,
-	.flags = I2C_DF_NOTIFY,
 
 	.attach_adapter = bt819_attach_adapter,
 	.detach_client = bt819_detach_client,
diff --git a/drivers/media/video/bt832.c b/drivers/media/video/bt832.c
index 3ca1d768bfd3..1c3ff5f38a6d 100644
--- a/drivers/media/video/bt832.c
+++ b/drivers/media/video/bt832.c
@@ -230,10 +230,10 @@ bt832_command(struct i2c_client *client, unsigned int cmd, void *arg)
 /* ----------------------------------------------------------------------- */
 
 static struct i2c_driver driver = {
-	.owner          = THIS_MODULE,
-	.name           = "i2c bt832 driver",
+	.driver = {
+		.name   = "i2c bt832 driver",
+	},
 	.id             = -1, /* FIXME */
-	.flags          = I2C_DF_NOTIFY,
 	.attach_adapter = bt832_probe,
 	.detach_client  = bt832_detach,
 	.command        = bt832_command,
@@ -241,7 +241,6 @@ static struct i2c_driver driver = {
 static struct i2c_client client_template =
 {
 	.name       = "bt832",
-	.flags      = I2C_CLIENT_ALLOW_USE,
 	.driver     = &driver,
 };
 
diff --git a/drivers/media/video/bt856.c b/drivers/media/video/bt856.c
index 8eb871d0e85b..60508069bbed 100644
--- a/drivers/media/video/bt856.c
+++ b/drivers/media/video/bt856.c
@@ -323,7 +323,6 @@ bt856_detect_client (struct i2c_adapter *adapter,
 	client->addr = address;
 	client->adapter = adapter;
 	client->driver = &i2c_driver_bt856;
-	client->flags = I2C_CLIENT_ALLOW_USE;
 	strlcpy(I2C_NAME(client), "bt856", sizeof(I2C_NAME(client)));
 
 	encoder = kmalloc(sizeof(struct bt856), GFP_KERNEL);
@@ -405,11 +404,11 @@ bt856_detach_client (struct i2c_client *client)
 /* ----------------------------------------------------------------------- */
 
 static struct i2c_driver i2c_driver_bt856 = {
-	.owner = THIS_MODULE,
-	.name = "bt856",
+	.driver = {
+		.name = "bt856",
+	},
 
 	.id = I2C_DRIVERID_BT856,
-	.flags = I2C_DF_NOTIFY,
 
 	.attach_adapter = bt856_attach_adapter,
 	.detach_client = bt856_detach_client,
diff --git a/drivers/media/video/bttv-i2c.c b/drivers/media/video/bttv-i2c.c
index 77619eb131f6..d6418c023d39 100644
--- a/drivers/media/video/bttv-i2c.c
+++ b/drivers/media/video/bttv-i2c.c
@@ -300,7 +300,7 @@ static int attach_inform(struct i2c_client *client)
 
 	if (bttv_debug)
 		printk(KERN_DEBUG "bttv%d: %s i2c attach [addr=0x%x,client=%s]\n",
-			btv->c.nr,client->driver->name,client->addr,
+			btv->c.nr, client->driver->driver.name, client->addr,
 			client->name);
 	if (!client->driver->command)
 		return 0;
diff --git a/drivers/media/video/cpia_pp.c b/drivers/media/video/cpia_pp.c
index ddf184f95d80..6861d408f1b3 100644
--- a/drivers/media/video/cpia_pp.c
+++ b/drivers/media/video/cpia_pp.c
@@ -170,16 +170,9 @@ static size_t cpia_read_nibble (struct parport *port,
 		/* Does the error line indicate end of data? */
 		if (((i /*& 1*/) == 0) &&
 		    (parport_read_status(port) & PARPORT_STATUS_ERROR)) {
-			port->physport->ieee1284.phase = IEEE1284_PH_HBUSY_DNA;
-				DBG("%s: No more nibble data (%d bytes)\n",
-				port->name, i/2);
-
-			/* Go to reverse idle phase. */
-			parport_frob_control (port,
-					      PARPORT_CONTROL_AUTOFD,
-					      PARPORT_CONTROL_AUTOFD);
-			port->physport->ieee1284.phase = IEEE1284_PH_REV_IDLE;
-			break;
+			DBG("%s: No more nibble data (%d bytes)\n",
+			    port->name, i/2);
+			goto end_of_data;
 		}
 
 		/* Event 7: Set nAutoFd low. */
@@ -227,18 +220,21 @@ static size_t cpia_read_nibble (struct parport *port,
 			byte = nibble;
 	}
 
-	i /= 2; /* i is now in bytes */
-
 	if (i == len) {
 		/* Read the last nibble without checking data avail. */
-		port = port->physport;
-		if (parport_read_status (port) & PARPORT_STATUS_ERROR)
-			port->ieee1284.phase = IEEE1284_PH_HBUSY_DNA;
+		if (parport_read_status (port) & PARPORT_STATUS_ERROR) {
+		end_of_data:
+			/* Go to reverse idle phase. */
+			parport_frob_control (port,
+					      PARPORT_CONTROL_AUTOFD,
+					      PARPORT_CONTROL_AUTOFD);
+			port->physport->ieee1284.phase = IEEE1284_PH_REV_IDLE;
+		}
 		else
-			port->ieee1284.phase = IEEE1284_PH_HBUSY_DAVAIL;
+			port->physport->ieee1284.phase = IEEE1284_PH_HBUSY_DAVAIL;
 	}
 
-	return i;
+	return i/2;
 }
 
 /* CPiA nonstandard "Nibble Stream" mode (2 nibbles per cycle, instead of 1)
diff --git a/drivers/media/video/cpia_usb.c b/drivers/media/video/cpia_usb.c
index 9774e94d1e7d..1439cb752874 100644
--- a/drivers/media/video/cpia_usb.c
+++ b/drivers/media/video/cpia_usb.c
@@ -582,7 +582,6 @@ MODULE_LICENSE("GPL");
 
 
 static struct usb_driver cpia_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "cpia",
 	.probe		= cpia_probe,
 	.disconnect	= cpia_disconnect,
diff --git a/drivers/media/video/cs53l32a.c b/drivers/media/video/cs53l32a.c
index 780b352ec119..643ead1a87ee 100644
--- a/drivers/media/video/cs53l32a.c
+++ b/drivers/media/video/cs53l32a.c
@@ -42,15 +42,16 @@ MODULE_PARM_DESC(debug, "Debugging messages\n\t\t\t0=Off (default), 1=On");
 #define cs53l32a_dbg(fmt, arg...) \
 	do { \
 		if (debug) \
-			printk(KERN_INFO "%s debug %d-%04x: " fmt, client->driver->name, \
+			printk(KERN_INFO "%s debug %d-%04x: " fmt, \
+			       client->driver->driver.name, \
 			       i2c_adapter_id(client->adapter), client->addr , ## arg); \
 	} while (0)
 
 #define cs53l32a_err(fmt, arg...) do { \
-	printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->name, \
+	printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->driver.name, \
 		i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
 #define cs53l32a_info(fmt, arg...) do { \
-	printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->name, \
+	printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->driver.name, \
 		i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
 
 static unsigned short normal_i2c[] = { 0x22 >> 1, I2C_CLIENT_END };
@@ -154,7 +155,6 @@ static int cs53l32a_attach(struct i2c_adapter *adapter, int address, int kind)
 	client->addr = address;
 	client->adapter = adapter;
 	client->driver = &i2c_driver;
-	client->flags = I2C_CLIENT_ALLOW_USE;
 	snprintf(client->name, sizeof(client->name) - 1, "cs53l32a");
 
 	cs53l32a_info("chip found @ 0x%x (%s)\n", address << 1, adapter->name);
@@ -216,13 +216,13 @@ static int cs53l32a_detach(struct i2c_client *client)
 
 /* i2c implementation */
 static struct i2c_driver i2c_driver = {
-	.name = "cs53l32a",
+	.driver = {
+		.name = "cs53l32a",
+	},
 	.id = I2C_DRIVERID_CS53L32A,
-	.flags = I2C_DF_NOTIFY,
 	.attach_adapter = cs53l32a_probe,
 	.detach_client = cs53l32a_detach,
 	.command = cs53l32a_command,
-	.owner = THIS_MODULE,
 };
 
 
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c
index 5b93723a1768..3b09f46dddf6 100644
--- a/drivers/media/video/cx25840/cx25840-core.c
+++ b/drivers/media/video/cx25840/cx25840-core.c
@@ -773,7 +773,6 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address,
 	client->addr = address;
 	client->adapter = adapter;
 	client->driver = &i2c_driver_cx25840;
-	client->flags = I2C_CLIENT_ALLOW_USE;
 	snprintf(client->name, sizeof(client->name) - 1, "cx25840");
 
 	cx25840_dbg("detecting cx25840 client on address 0x%x\n", address << 1);
@@ -844,15 +843,15 @@ static int cx25840_detach_client(struct i2c_client *client)
 /* ----------------------------------------------------------------------- */
 
 static struct i2c_driver i2c_driver_cx25840 = {
-	.name = "cx25840",
+	.driver = {
+		.name = "cx25840",
+	},
 
 	.id = I2C_DRIVERID_CX25840,
-	.flags = I2C_DF_NOTIFY,
 
 	.attach_adapter = cx25840_attach_adapter,
 	.detach_client = cx25840_detach_client,
 	.command = cx25840_command,
-	.owner = THIS_MODULE,
 };
 
 
diff --git a/drivers/media/video/cx25840/cx25840.h b/drivers/media/video/cx25840/cx25840.h
index 4932ed1c9b19..40aa59f9c525 100644
--- a/drivers/media/video/cx25840/cx25840.h
+++ b/drivers/media/video/cx25840/cx25840.h
@@ -27,15 +27,16 @@
 extern int cx25840_debug;
 
 #define cx25840_dbg(fmt, arg...) do { if (cx25840_debug) \
-	printk(KERN_INFO "%s debug %d-%04x: " fmt, client->driver->name, \
+	printk(KERN_INFO "%s debug %d-%04x: " fmt, \
+	       client->driver->driver.name, \
 	       i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
 
 #define cx25840_err(fmt, arg...) do { \
-	printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->name, \
+	printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->driver.name, \
 	       i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
 
 #define cx25840_info(fmt, arg...) do { \
-	printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->name, \
+	printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->driver.name, \
 	       i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
 
 #define CX25840_CID_CARDTYPE (V4L2_CID_PRIVATE_BASE+0)
diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c
index 9790d412f192..4a8fb161b16a 100644
--- a/drivers/media/video/cx88/cx88-i2c.c
+++ b/drivers/media/video/cx88/cx88-i2c.c
@@ -94,7 +94,7 @@ static int attach_inform(struct i2c_client *client)
 	struct cx88_core *core = i2c_get_adapdata(client->adapter);
 
 	dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n",
-		client->driver->name, client->addr, client->name);
+		client->driver->driver.name, client->addr, client->name);
 	if (!client->driver->command)
 		return 0;
 
diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c
index 7f5603054f02..d14bcf4ceaea 100644
--- a/drivers/media/video/em28xx/em28xx-i2c.c
+++ b/drivers/media/video/em28xx/em28xx-i2c.c
@@ -497,7 +497,6 @@ static struct i2c_adapter em28xx_adap_template = {
 
 static struct i2c_client em28xx_client_template = {
 	.name = "em28xx internal",
-	.flags = I2C_CLIENT_ALLOW_USE,
 };
 
 /* ----------------------------------------------------------- */
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index 06d76879bde2..3a56120397ae 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -1884,7 +1884,6 @@ static void em28xx_usb_disconnect(struct usb_interface *interface)
 }
 
 static struct usb_driver em28xx_usb_driver = {
-	.owner = THIS_MODULE,
 	.name = "em28xx",
 	.probe = em28xx_usb_probe,
 	.disconnect = em28xx_usb_disconnect,
diff --git a/drivers/media/video/indycam.c b/drivers/media/video/indycam.c
index deeef125eb92..bb5cbecffcc3 100644
--- a/drivers/media/video/indycam.c
+++ b/drivers/media/video/indycam.c
@@ -451,10 +451,10 @@ static int indycam_command(struct i2c_client *client, unsigned int cmd,
 }
 
 static struct i2c_driver i2c_driver_indycam = {
-	.owner		= THIS_MODULE,
-	.name		= "indycam",
+	.driver = {
+		.name 	= "indycam",
+	},
 	.id		= I2C_DRIVERID_INDYCAM,
-	.flags		= I2C_DF_NOTIFY,
 	.attach_adapter = indycam_probe,
 	.detach_client	= indycam_detach,
 	.command	= indycam_command,
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c
index 740e543311af..3cc1d6a6019b 100644
--- a/drivers/media/video/ir-kbd-i2c.c
+++ b/drivers/media/video/ir-kbd-i2c.c
@@ -278,9 +278,10 @@ static int ir_detach(struct i2c_client *client);
 static int ir_probe(struct i2c_adapter *adap);
 
 static struct i2c_driver driver = {
-	.name           = "ir remote kbd driver",
+	.driver = {
+		.name   = "ir remote kbd driver",
+	},
 	.id             = I2C_DRIVERID_INFRARED,
-	.flags          = I2C_DF_NOTIFY,
 	.attach_adapter = ir_probe,
 	.detach_client  = ir_detach,
 };
diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c
index d86f8e92e534..183253e2dd91 100644
--- a/drivers/media/video/msp3400.c
+++ b/drivers/media/video/msp3400.c
@@ -59,7 +59,8 @@
 #define msp3400_dbg(fmt, arg...) \
 	do { \
 		if (debug) \
-			printk(KERN_INFO "%s debug %d-%04x: " fmt, client->driver->name, \
+			printk(KERN_INFO "%s debug %d-%04x: " fmt, \
+			       client->driver->driver.name, \
 			       i2c_adapter_id(client->adapter), client->addr , ## arg); \
 	} while (0)
 
@@ -67,7 +68,8 @@
 #define msp3400_dbg_mediumvol(fmt, arg...) \
 	do { \
 		if (debug >= 2) \
-			printk(KERN_INFO "%s debug %d-%04x: " fmt, client->driver->name, \
+			printk(KERN_INFO "%s debug %d-%04x: " fmt, \
+				client->driver->driver.name, \
 				i2c_adapter_id(client->adapter), client->addr , ## arg); \
 	} while (0)
 
@@ -75,18 +77,19 @@
 #define msp3400_dbg_highvol(fmt, arg...) \
 	do { \
 		if (debug >= 16) \
-			printk(KERN_INFO "%s debug %d-%04x: " fmt, client->driver->name, \
+			printk(KERN_INFO "%s debug %d-%04x: " fmt, \
+				client->driver->driver.name, \
 				i2c_adapter_id(client->adapter), client->addr , ## arg); \
 	} while (0)
 
 #define msp3400_err(fmt, arg...) do { \
-	printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->name, \
+	printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->driver.name, \
 		i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
 #define msp3400_warn(fmt, arg...) do { \
-	printk(KERN_WARNING "%s %d-%04x: " fmt, client->driver->name, \
+	printk(KERN_WARNING "%s %d-%04x: " fmt, client->driver->driver.name, \
 		i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
 #define msp3400_info(fmt, arg...) do { \
-	printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->name, \
+	printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->driver.name, \
 		i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
 
 #define OPMODE_AUTO    -1
@@ -1561,14 +1564,12 @@ static int msp_resume(struct device * dev);
 static void msp_wake_thread(struct i2c_client *client);
 
 static struct i2c_driver driver = {
-	.owner          = THIS_MODULE,
-	.name           = "msp3400",
 	.id             = I2C_DRIVERID_MSP3400,
-	.flags          = I2C_DF_NOTIFY,
 	.attach_adapter = msp_probe,
 	.detach_client  = msp_detach,
 	.command        = msp_command,
 	.driver = {
+		.name    = "i2c msp3400 driver",
 		.suspend = msp_suspend,
 		.resume  = msp_resume,
 	},
@@ -1577,7 +1578,6 @@ static struct i2c_driver driver = {
 static struct i2c_client client_template =
 {
 	.name      = "(unset)",
-	.flags     = I2C_CLIENT_ALLOW_USE,
 	.driver    = &driver,
 };
 
diff --git a/drivers/media/video/ovcamchip/ovcamchip_core.c b/drivers/media/video/ovcamchip/ovcamchip_core.c
index 2de34ebf0673..428f1bb75ec3 100644
--- a/drivers/media/video/ovcamchip/ovcamchip_core.c
+++ b/drivers/media/video/ovcamchip/ovcamchip_core.c
@@ -410,11 +410,11 @@ static int ovcamchip_command(struct i2c_client *c, unsigned int cmd, void *arg)
 /* ----------------------------------------------------------------------- */
 
 static struct i2c_driver driver = {
-	.owner =		THIS_MODULE,
-	.name =			"ovcamchip",
+	.driver = {
+		.name =		"ovcamchip",
+	},
 	.id =			I2C_DRIVERID_OVCAMCHIP,
 	.class =		I2C_CLASS_CAM_DIGITAL,
-	.flags =		I2C_DF_NOTIFY,
 	.attach_adapter =	ovcamchip_attach,
 	.detach_client =	ovcamchip_detach,
 	.command =		ovcamchip_command,
diff --git a/drivers/media/video/saa5246a.c b/drivers/media/video/saa5246a.c
index b8054da31ffd..0aa9e72f632c 100644
--- a/drivers/media/video/saa5246a.c
+++ b/drivers/media/video/saa5246a.c
@@ -151,25 +151,18 @@ static int saa5246a_detach(struct i2c_client *client)
 	return 0;
 }
 
-static int saa5246a_command(struct i2c_client *device, unsigned int cmd,
-	void *arg)
-{
-	return -EINVAL;
-}
-
 /*
  *	I2C interfaces
  */
 
 static struct i2c_driver i2c_driver_videotext =
 {
-	.owner 		= THIS_MODULE,
-	.name 		= IF_NAME,		/* name */
+	.driver = {
+		.name 	= IF_NAME,		/* name */
+	},
 	.id 		= I2C_DRIVERID_SAA5249, /* in i2c.h */
-	.flags 		= I2C_DF_NOTIFY,
 	.attach_adapter = saa5246a_probe,
 	.detach_client  = saa5246a_detach,
-	.command 	= saa5246a_command
 };
 
 static struct i2c_client client_template = {
diff --git a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c
index 7ffa2e9a9bf3..a51c7bd96618 100644
--- a/drivers/media/video/saa5249.c
+++ b/drivers/media/video/saa5249.c
@@ -226,23 +226,16 @@ static int saa5249_detach(struct i2c_client *client)
 	return 0;
 }
 
-static int saa5249_command(struct i2c_client *device,
-			     unsigned int cmd, void *arg)
-{
-	return -EINVAL;
-}
-
 /* new I2C driver support */
 
 static struct i2c_driver i2c_driver_videotext = 
 {
-	.owner 		= THIS_MODULE,
-	.name 		= IF_NAME,		/* name */
+	.driver = {
+		.name 	= IF_NAME,		/* name */
+	},
 	.id 		= I2C_DRIVERID_SAA5249, /* in i2c.h */
-	.flags 		= I2C_DF_NOTIFY,
 	.attach_adapter = saa5249_probe,
 	.detach_client  = saa5249_detach,
-	.command 	= saa5249_command
 };
 
 static struct i2c_client client_template = {
diff --git a/drivers/media/video/saa6588.c b/drivers/media/video/saa6588.c
index 923322503e8f..d60a783e0473 100644
--- a/drivers/media/video/saa6588.c
+++ b/drivers/media/video/saa6588.c
@@ -495,10 +495,10 @@ static int saa6588_command(struct i2c_client *client, unsigned int cmd,
 /* ----------------------------------------------------------------------- */
 
 static struct i2c_driver driver = {
-	.owner = THIS_MODULE,
-	.name = "i2c saa6588 driver",
+	.driver = {
+		.name = "i2c saa6588 driver",
+	},
 	.id = -1,		/* FIXME */
-	.flags = I2C_DF_NOTIFY,
 	.attach_adapter = saa6588_probe,
 	.detach_client = saa6588_detach,
 	.command = saa6588_command,
@@ -506,7 +506,6 @@ static struct i2c_driver driver = {
 
 static struct i2c_client client_template = {
 	.name = "saa6588",
-	.flags = I2C_CLIENT_ALLOW_USE,
 	.driver = &driver,
 };
 
diff --git a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c
index e116bdbed310..619ff0b7a1ff 100644
--- a/drivers/media/video/saa7110.c
+++ b/drivers/media/video/saa7110.c
@@ -501,7 +501,6 @@ saa7110_detect_client (struct i2c_adapter *adapter,
 	client->addr = address;
 	client->adapter = adapter;
 	client->driver = &i2c_driver_saa7110;
-	client->flags = I2C_CLIENT_ALLOW_USE;
 	strlcpy(I2C_NAME(client), "saa7110", sizeof(I2C_NAME(client)));
 
 	decoder = kmalloc(sizeof(struct saa7110), GFP_KERNEL);
@@ -587,11 +586,11 @@ saa7110_detach_client (struct i2c_client *client)
 /* ----------------------------------------------------------------------- */
 
 static struct i2c_driver i2c_driver_saa7110 = {
-	.owner = THIS_MODULE,
-	.name = "saa7110",
+	.driver = {
+		.name = "saa7110",
+	},
 
 	.id = I2C_DRIVERID_SAA7110,
-	.flags = I2C_DF_NOTIFY,
 
 	.attach_adapter = saa7110_attach_adapter,
 	.detach_client = saa7110_detach_client,
diff --git a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c
index fe8a5e453969..acaeee592b54 100644
--- a/drivers/media/video/saa7111.c
+++ b/drivers/media/video/saa7111.c
@@ -518,7 +518,6 @@ saa7111_detect_client (struct i2c_adapter *adapter,
 	client->addr = address;
 	client->adapter = adapter;
 	client->driver = &i2c_driver_saa7111;
-	client->flags = I2C_CLIENT_ALLOW_USE;
 	strlcpy(I2C_NAME(client), "saa7111", sizeof(I2C_NAME(client)));
 
 	decoder = kmalloc(sizeof(struct saa7111), GFP_KERNEL);
@@ -590,11 +589,11 @@ saa7111_detach_client (struct i2c_client *client)
 /* ----------------------------------------------------------------------- */
 
 static struct i2c_driver i2c_driver_saa7111 = {
-	.owner = THIS_MODULE,
-	.name = "saa7111",
+	.driver = {
+		.name = "saa7111",
+	},
 
 	.id = I2C_DRIVERID_SAA7111A,
-	.flags = I2C_DF_NOTIFY,
 
 	.attach_adapter = saa7111_attach_adapter,
 	.detach_client = saa7111_detach_client,
diff --git a/drivers/media/video/saa7114.c b/drivers/media/video/saa7114.c
index d9f50e2f7b92..b7ac0122f729 100644
--- a/drivers/media/video/saa7114.c
+++ b/drivers/media/video/saa7114.c
@@ -859,7 +859,6 @@ saa7114_detect_client (struct i2c_adapter *adapter,
 	client->addr = address;
 	client->adapter = adapter;
 	client->driver = &i2c_driver_saa7114;
-	client->flags = I2C_CLIENT_ALLOW_USE;
 	strlcpy(I2C_NAME(client), "saa7114", sizeof(I2C_NAME(client)));
 
 	decoder = kmalloc(sizeof(struct saa7114), GFP_KERNEL);
@@ -1204,11 +1203,11 @@ saa7114_detach_client (struct i2c_client *client)
 /* ----------------------------------------------------------------------- */
 
 static struct i2c_driver i2c_driver_saa7114 = {
-	.owner = THIS_MODULE,
-	.name = "saa7114",
+	.driver = {
+		.name = "saa7114",
+	},
 
 	.id = I2C_DRIVERID_SAA7114,
-	.flags = I2C_DF_NOTIFY,
 
 	.attach_adapter = saa7114_attach_adapter,
 	.detach_client = saa7114_detach_client,
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c
index e717e30d8187..29e28c742cd4 100644
--- a/drivers/media/video/saa7115.c
+++ b/drivers/media/video/saa7115.c
@@ -52,15 +52,16 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)");
 #define saa7115_dbg(fmt,arg...) \
 	do { \
 		if (debug) \
-			printk(KERN_INFO "%s debug %d-%04x: " fmt, client->driver->name, \
+			printk(KERN_INFO "%s debug %d-%04x: " fmt, \
+			       client->driver->driver.name, \
 			       i2c_adapter_id(client->adapter), client->addr , ## arg); \
 	} while (0)
 
 #define saa7115_err(fmt, arg...) do { \
-	printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->name, \
+	printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->driver.name, \
 	       i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
 #define saa7115_info(fmt, arg...) do { \
-	printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->name, \
+	printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->driver.name, \
 	       i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
 
 static unsigned short normal_i2c[] = { 0x42 >> 1, 0x40 >> 1, I2C_CLIENT_END };
@@ -1270,7 +1271,6 @@ static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind)
 	client->addr = address;
 	client->adapter = adapter;
 	client->driver = &i2c_driver_saa7115;
-	client->flags = I2C_CLIENT_ALLOW_USE;
 	snprintf(client->name, sizeof(client->name) - 1, "saa7115");
 
 	saa7115_dbg("detecting saa7115 client on address 0x%x\n", address << 1);
@@ -1354,13 +1354,13 @@ static int saa7115_detach(struct i2c_client *client)
 
 /* i2c implementation */
 static struct i2c_driver i2c_driver_saa7115 = {
-	.name = "saa7115",
+	.driver = {
+		.name = "saa7115",
+	},
 	.id = I2C_DRIVERID_SAA711X,
-	.flags = I2C_DF_NOTIFY,
 	.attach_adapter = saa7115_probe,
 	.detach_client = saa7115_detach,
 	.command = saa7115_command,
-	.owner = THIS_MODULE,
 };
 
 
diff --git a/drivers/media/video/saa711x.c b/drivers/media/video/saa711x.c
index 31f7b950b01c..8008537391b5 100644
--- a/drivers/media/video/saa711x.c
+++ b/drivers/media/video/saa711x.c
@@ -494,7 +494,6 @@ saa711x_detect_client (struct i2c_adapter *adapter,
 	client->addr = address;
 	client->adapter = adapter;
 	client->driver = &i2c_driver_saa711x;
-	client->flags = I2C_CLIENT_ALLOW_USE;
 	strlcpy(I2C_NAME(client), "saa711x", sizeof(I2C_NAME(client)));
 	decoder = kmalloc(sizeof(struct saa711x), GFP_KERNEL);
 	if (decoder == NULL) {
@@ -565,11 +564,11 @@ saa711x_detach_client (struct i2c_client *client)
 /* ----------------------------------------------------------------------- */
 
 static struct i2c_driver i2c_driver_saa711x = {
-	.owner = THIS_MODULE,
-	.name = "saa711x",
+	.driver = {
+		.name = "saa711x",
+	},
 
 	.id = I2C_DRIVERID_SAA711X,
-	.flags = I2C_DF_NOTIFY,
 
 	.attach_adapter = saa711x_attach_adapter,
 	.detach_client = saa711x_detach_client,
diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c
index c36f014f1fdf..bca6ed0e2752 100644
--- a/drivers/media/video/saa7127.c
+++ b/drivers/media/video/saa7127.c
@@ -69,7 +69,8 @@ MODULE_PARM_DESC(test_image, "test_image (0-1)");
 #define saa7127_dbg(fmt, arg...) \
 	do { \
 		if (debug >= 1) \
-			printk(KERN_INFO "%s debug %d-%04x: " fmt, client->driver->name, \
+			printk(KERN_INFO "%s debug %d-%04x: " fmt, \
+			       client->driver->driver.name, \
 			       i2c_adapter_id(client->adapter), client->addr , ## arg); \
 	} while (0)
 
@@ -77,15 +78,16 @@ MODULE_PARM_DESC(test_image, "test_image (0-1)");
 #define saa7127_dbg_highvol(fmt, arg...) \
 	do { \
 		if (debug == 2) \
-			printk(KERN_INFO "%s debug %d-%04x: " fmt, client->driver->name, \
+			printk(KERN_INFO "%s debug %d-%04x: " fmt, \
+			       client->driver->driver.name, \
 			       i2c_adapter_id(client->adapter), client->addr , ## arg); \
 	} while (0)
 
 #define saa7127_err(fmt, arg...) do { \
-	printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->name, \
+	printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->driver.name, \
 	       i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
 #define saa7127_info(fmt, arg...) do { \
-	printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->name, \
+	printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->driver.name, \
 	       i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
 
 static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END };
@@ -719,7 +721,6 @@ static int saa7127_attach(struct i2c_adapter *adapter, int address, int kind)
 	client->addr = address;
 	client->adapter = adapter;
 	client->driver = &i2c_driver_saa7127;
-	client->flags = I2C_CLIENT_ALLOW_USE;
 	snprintf(client->name, sizeof(client->name) - 1, "saa7127");
 
 	saa7127_dbg("detecting saa7127 client on address 0x%x\n", address << 1);
@@ -819,13 +820,13 @@ static int saa7127_detach(struct i2c_client *client)
 /* ----------------------------------------------------------------------- */
 
 static struct i2c_driver i2c_driver_saa7127 = {
-	.name = "saa7127",
+	.driver = {
+		.name = "saa7127",
+	},
 	.id = I2C_DRIVERID_SAA7127,
-	.flags = I2C_DF_NOTIFY,
 	.attach_adapter = saa7127_probe,
 	.detach_client = saa7127_detach,
 	.command = saa7127_command,
-	.owner = THIS_MODULE,
 };
 
 
diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c
index a61d24f588f7..4615a982ac64 100644
--- a/drivers/media/video/saa7134/saa6752hs.c
+++ b/drivers/media/video/saa7134/saa6752hs.c
@@ -597,10 +597,10 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg)
 /* ----------------------------------------------------------------------- */
 
 static struct i2c_driver driver = {
-	.owner          = THIS_MODULE,
-	.name           = "i2c saa6752hs MPEG encoder",
+	.driver = {
+		.name   = "i2c saa6752hs MPEG encoder",
+	},
 	.id             = I2C_DRIVERID_SAA6752HS,
-	.flags          = I2C_DF_NOTIFY,
 	.attach_adapter = saa6752hs_probe,
 	.detach_client  = saa6752hs_detach,
 	.command        = saa6752hs_command,
@@ -609,7 +609,6 @@ static struct i2c_driver driver = {
 static struct i2c_client client_template =
 {
 	.name       = "saa6752hs",
-	.flags      = I2C_CLIENT_ALLOW_USE,
 	.driver     = &driver,
 };
 
diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c
index df9dd36721e0..1792d03d621d 100644
--- a/drivers/media/video/saa7134/saa7134-i2c.c
+++ b/drivers/media/video/saa7134/saa7134-i2c.c
@@ -333,7 +333,7 @@ static int attach_inform(struct i2c_client *client)
 	struct tuner_setup tun_setup;
 
 	d1printk( "%s i2c attach [addr=0x%x,client=%s]\n",
-		client->driver->name, client->addr, client->name);
+		client->driver->driver.name, client->addr, client->name);
 
 	/* Am I an i2c remote control? */
 
@@ -343,7 +343,7 @@ static int attach_inform(struct i2c_client *client)
 		{
 			struct IR_i2c *ir = i2c_get_clientdata(client);
 			d1printk("%s i2c IR detected (%s).\n",
-				 client->driver->name,ir->phys);
+				 client->driver->driver.name, ir->phys);
 			saa7134_set_i2c_ir(dev,ir);
 			break;
 		}
diff --git a/drivers/media/video/saa7185.c b/drivers/media/video/saa7185.c
index 132aa7943c16..f72a9f796209 100644
--- a/drivers/media/video/saa7185.c
+++ b/drivers/media/video/saa7185.c
@@ -415,7 +415,6 @@ saa7185_detect_client (struct i2c_adapter *adapter,
 	client->addr = address;
 	client->adapter = adapter;
 	client->driver = &i2c_driver_saa7185;
-	client->flags = I2C_CLIENT_ALLOW_USE;
 	strlcpy(I2C_NAME(client), "saa7185", sizeof(I2C_NAME(client)));
 
 	encoder = kmalloc(sizeof(struct saa7185), GFP_KERNEL);
@@ -487,11 +486,11 @@ saa7185_detach_client (struct i2c_client *client)
 /* ----------------------------------------------------------------------- */
 
 static struct i2c_driver i2c_driver_saa7185 = {
-	.owner = THIS_MODULE,
-	.name = "saa7185",	/* name */
+	.driver = {
+		.name = "saa7185",	/* name */
+	},
 
 	.id = I2C_DRIVERID_SAA7185B,
-	.flags = I2C_DF_NOTIFY,
 
 	.attach_adapter = saa7185_attach_adapter,
 	.detach_client = saa7185_detach_client,
diff --git a/drivers/media/video/saa7191.c b/drivers/media/video/saa7191.c
index cbca896e8cfa..41f6f05a0436 100644
--- a/drivers/media/video/saa7191.c
+++ b/drivers/media/video/saa7191.c
@@ -788,10 +788,10 @@ static int saa7191_command(struct i2c_client *client, unsigned int cmd,
 }
 
 static struct i2c_driver i2c_driver_saa7191 = {
-	.owner		= THIS_MODULE,
-	.name		= "saa7191",
+	.driver = {
+		.name 	= "saa7191",
+	},
 	.id		= I2C_DRIVERID_SAA7191,
-	.flags		= I2C_DF_NOTIFY,
 	.attach_adapter = saa7191_probe,
 	.detach_client	= saa7191_detach,
 	.command	= saa7191_command
diff --git a/drivers/media/video/tda7432.c b/drivers/media/video/tda7432.c
index d32737dd2142..549c9929f107 100644
--- a/drivers/media/video/tda7432.c
+++ b/drivers/media/video/tda7432.c
@@ -501,10 +501,10 @@ static int tda7432_command(struct i2c_client *client,
 }
 
 static struct i2c_driver driver = {
-	.owner           = THIS_MODULE,
-	.name            = "i2c tda7432 driver",
+	.driver = {
+		.name    = "i2c tda7432 driver",
+	},
 	.id              = I2C_DRIVERID_TDA7432,
-	.flags           = I2C_DF_NOTIFY,
 	.attach_adapter  = tda7432_probe,
 	.detach_client   = tda7432_detach,
 	.command         = tda7432_command,
diff --git a/drivers/media/video/tda9840.c b/drivers/media/video/tda9840.c
index 1794686612c6..ed4c04119ccc 100644
--- a/drivers/media/video/tda9840.c
+++ b/drivers/media/video/tda9840.c
@@ -34,7 +34,7 @@ static int debug = 0;		/* insmod parameter */
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
 #define dprintk(args...) \
-            do { if (debug) { printk("%s: %s()[%d]: ",__stringify(KBUILD_MODNAME), __FUNCTION__, __LINE__); printk(args); } } while (0)
+            do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __FUNCTION__, __LINE__); printk(args); } } while (0)
 
 #define	SWITCH		0x00
 #define	LEVEL_ADJUST	0x02
@@ -221,10 +221,10 @@ static int detach(struct i2c_client *client)
 }
 
 static struct i2c_driver driver = {
-	.owner	= THIS_MODULE,
-	.name	= "tda9840",
+	.driver = {
+		.name	= "tda9840",
+	},
 	.id	= I2C_DRIVERID_TDA9840,
-	.flags	= I2C_DF_NOTIFY,
 	.attach_adapter	= attach,
 	.detach_client	= detach,
 	.command	= command,
diff --git a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c
index a5e37dc91f39..9c3ecf7a0fed 100644
--- a/drivers/media/video/tda9875.c
+++ b/drivers/media/video/tda9875.c
@@ -372,10 +372,10 @@ static int tda9875_command(struct i2c_client *client,
 
 
 static struct i2c_driver driver = {
-	.owner          = THIS_MODULE,
-	.name           = "i2c tda9875 driver",
+	.driver = {
+		.name   = "i2c tda9875 driver",
+	},
 	.id             = I2C_DRIVERID_TDA9875,
-	.flags          = I2C_DF_NOTIFY,
 	.attach_adapter = tda9875_probe,
 	.detach_client  = tda9875_detach,
 	.command        = tda9875_command,
diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c
index 2f2414e90e8b..7165a1b9625a 100644
--- a/drivers/media/video/tda9887.c
+++ b/drivers/media/video/tda9887.c
@@ -819,14 +819,12 @@ static int tda9887_resume(struct device * dev)
 /* ----------------------------------------------------------------------- */
 
 static struct i2c_driver driver = {
-	.owner          = THIS_MODULE,
-	.name           = "i2c tda9887 driver",
 	.id             = -1, /* FIXME */
-	.flags          = I2C_DF_NOTIFY,
 	.attach_adapter = tda9887_probe,
 	.detach_client  = tda9887_detach,
 	.command        = tda9887_command,
 	.driver = {
+		.name    = "i2c tda9887 driver",
 		.suspend = tda9887_suspend,
 		.resume  = tda9887_resume,
 	},
@@ -834,7 +832,6 @@ static struct i2c_driver driver = {
 static struct i2c_client client_template =
 {
 	.name      = "tda9887",
-	.flags     = I2C_CLIENT_ALLOW_USE,
 	.driver    = &driver,
 };
 
diff --git a/drivers/media/video/tea6415c.c b/drivers/media/video/tea6415c.c
index ee3688348b66..bb35844e3842 100644
--- a/drivers/media/video/tea6415c.c
+++ b/drivers/media/video/tea6415c.c
@@ -36,7 +36,7 @@ static int debug = 0;		/* insmod parameter */
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
 #define dprintk(args...) \
-            do { if (debug) { printk("%s: %s()[%d]: ",__stringify(KBUILD_MODNAME), __FUNCTION__, __LINE__); printk(args); } } while (0)
+            do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __FUNCTION__, __LINE__); printk(args); } } while (0)
 
 #define TEA6415C_NUM_INPUTS	8
 #define TEA6415C_NUM_OUTPUTS	6
@@ -190,10 +190,10 @@ static int command(struct i2c_client *client, unsigned int cmd, void *arg)
 }
 
 static struct i2c_driver driver = {
-	.owner	= THIS_MODULE,
-	.name 	= "tea6415c",
+	.driver = {
+		.name 	= "tea6415c",
+	},
 	.id 	= I2C_DRIVERID_TEA6415C,
-	.flags 	= I2C_DF_NOTIFY,
 	.attach_adapter	= attach,
 	.detach_client	= detach,
 	.command	= command,
diff --git a/drivers/media/video/tea6420.c b/drivers/media/video/tea6420.c
index 17975c19da5e..c4ba3742f5c7 100644
--- a/drivers/media/video/tea6420.c
+++ b/drivers/media/video/tea6420.c
@@ -36,7 +36,7 @@ static int debug = 0;		/* insmod parameter */
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
 #define dprintk(args...) \
-            do { if (debug) { printk("%s: %s()[%d]: ",__stringify(KBUILD_MODNAME), __FUNCTION__, __LINE__); printk(args); } } while (0)
+            do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __FUNCTION__, __LINE__); printk(args); } } while (0)
 
 /* addresses to scan, found only at 0x4c and/or 0x4d (7-Bit) */
 static unsigned short normal_i2c[] = { I2C_TEA6420_1, I2C_TEA6420_2, I2C_CLIENT_END };
@@ -167,10 +167,10 @@ static int command(struct i2c_client *client, unsigned int cmd, void *arg)
 }
 
 static struct i2c_driver driver = {
-	.owner	= THIS_MODULE,
-	.name	= "tea6420",
+	.driver = {
+		.name	= "tea6420",
+	},
 	.id	= I2C_DRIVERID_TEA6420,
-	.flags	= I2C_DF_NOTIFY,
 	.attach_adapter	= attach,
 	.detach_client	= detach,
 	.command	= command,
diff --git a/drivers/media/video/tuner-3036.c b/drivers/media/video/tuner-3036.c
index 79203595b9c1..d97f66804c37 100644
--- a/drivers/media/video/tuner-3036.c
+++ b/drivers/media/video/tuner-3036.c
@@ -175,10 +175,10 @@ tuner_probe(struct i2c_adapter *adap)
 static struct i2c_driver 
 i2c_driver_tuner = 
 {
-	.owner		=	THIS_MODULE,
-	.name		=	"sab3036",
+	.driver = {
+		.name	=	"sab3036",
+	},
 	.id		=	I2C_DRIVERID_SAB3036,
-        .flags		=	I2C_DF_NOTIFY,
 	.attach_adapter =	tuner_probe,
 	.detach_client  =	tuner_detach,
 	.command	=	tuner_command
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c
index e58abdfcaab8..c13c7b95ef35 100644
--- a/drivers/media/video/tuner-core.c
+++ b/drivers/media/video/tuner-core.c
@@ -206,7 +206,7 @@ static void set_type(struct i2c_client *c, unsigned int type,
 
 	set_freq(c, t->freq);
 	tuner_dbg("%s %s I2C addr 0x%02x with type %d used for 0x%02x\n",
-		  c->adapter->name, c->driver->name, c->addr << 1, type,
+		  c->adapter->name, c->driver->driver.name, c->addr << 1, type,
 		  t->mode_mask);
 }
 
@@ -742,21 +742,18 @@ static int tuner_resume(struct device *dev)
 /* ----------------------------------------------------------------------- */
 
 static struct i2c_driver driver = {
-	.owner = THIS_MODULE,
-	.name = "tuner",
 	.id = I2C_DRIVERID_TUNER,
-	.flags = I2C_DF_NOTIFY,
 	.attach_adapter = tuner_probe,
 	.detach_client = tuner_detach,
 	.command = tuner_command,
 	.driver = {
+		   .name = "tuner",
 		   .suspend = tuner_suspend,
 		   .resume = tuner_resume,
 		   },
 };
 static struct i2c_client client_template = {
 	.name = "(tuner unset)",
-	.flags = I2C_CLIENT_ALLOW_USE,
 	.driver = &driver,
 };
 
diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c
index 5b20e8177cad..0292c5abf14a 100644
--- a/drivers/media/video/tvaudio.c
+++ b/drivers/media/video/tvaudio.c
@@ -1702,10 +1702,10 @@ static int chip_command(struct i2c_client *client,
 
 
 static struct i2c_driver driver = {
-	.owner           = THIS_MODULE,
-	.name            = "generic i2c audio driver",
+	.driver = {
+		.name    = "generic i2c audio driver",
+	},
 	.id              = I2C_DRIVERID_TVAUDIO,
-	.flags           = I2C_DF_NOTIFY,
 	.attach_adapter  = chip_probe,
 	.detach_client   = chip_detach,
 	.command         = chip_command,
@@ -1714,7 +1714,6 @@ static struct i2c_driver driver = {
 static struct i2c_client client_template =
 {
 	.name       = "(unset)",
-	.flags      = I2C_CLIENT_ALLOW_USE,
 	.driver     = &driver,
 };
 
diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c
index 5ac235365dd8..8ac4cb82a459 100644
--- a/drivers/media/video/tveeprom.c
+++ b/drivers/media/video/tveeprom.c
@@ -751,7 +751,6 @@ tveeprom_detect_client(struct i2c_adapter *adapter,
 	client->addr = address;
 	client->adapter = adapter;
 	client->driver = &i2c_driver_tveeprom;
-	client->flags = I2C_CLIENT_ALLOW_USE;
 	snprintf(client->name, sizeof(client->name), "tveeprom");
 	i2c_attach_client(client);
 
@@ -779,10 +778,10 @@ tveeprom_detach_client (struct i2c_client *client)
 }
 
 static struct i2c_driver i2c_driver_tveeprom = {
-	.owner          = THIS_MODULE,
-	.name           = "tveeprom",
+	.driver = {
+		.name   = "tveeprom",
+	},
 	.id             = I2C_DRIVERID_TVEEPROM,
-	.flags          = I2C_DF_NOTIFY,
 	.attach_adapter = tveeprom_attach_adapter,
 	.detach_client  = tveeprom_detach_client,
 	.command        = tveeprom_command,
diff --git a/drivers/media/video/tvmixer.c b/drivers/media/video/tvmixer.c
index 8318bd1aad00..e837f9f7fed6 100644
--- a/drivers/media/video/tvmixer.c
+++ b/drivers/media/video/tvmixer.c
@@ -228,16 +228,14 @@ static int tvmixer_release(struct inode *inode, struct file *file)
 
 static struct i2c_driver driver = {
 #ifdef I2C_PEC
-	.owner           = THIS_MODULE,
-#endif
+	.driver = {
+		.name    = "tv card mixer driver",
+	},
+#else
 	.name            = "tv card mixer driver",
+#endif
 	.id              = I2C_DRIVERID_TVMIXER,
-#ifdef I2C_DF_DUMMY
-	.flags           = I2C_DF_DUMMY,
-#else
-	.flags           = I2C_DF_NOTIFY,
 	.detach_adapter  = tvmixer_adapters,
-#endif
 	.attach_adapter  = tvmixer_adapters,
 	.detach_client   = tvmixer_clients,
 };
diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c
index 97431e26d229..a60442ea4f94 100644
--- a/drivers/media/video/tvp5150.c
+++ b/drivers/media/video/tvp5150.c
@@ -714,7 +714,6 @@ static struct i2c_driver driver;
 
 static struct i2c_client client_template = {
 	.name = "(unset)",
-	.flags = I2C_CLIENT_ALLOW_USE,
 	.driver = &driver,
 };
 
@@ -801,12 +800,12 @@ static int tvp5150_detach_client(struct i2c_client *client)
 /* ----------------------------------------------------------------------- */
 
 static struct i2c_driver driver = {
-	.owner = THIS_MODULE,
-	.name = "tvp5150",
+	.driver = {
+		.name = "tvp5150",
+	},
 
 	/* FIXME */
 	.id = I2C_DRIVERID_SAA7110,
-	.flags = I2C_DF_NOTIFY,
 
 	.attach_adapter = tvp5150_attach_adapter,
 	.detach_client = tvp5150_detach_client,
diff --git a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c
index 137b58f2c666..8dcee8b60e21 100644
--- a/drivers/media/video/vpx3220.c
+++ b/drivers/media/video/vpx3220.c
@@ -631,7 +631,6 @@ vpx3220_detect_client (struct i2c_adapter *adapter,
 	client->addr = address;
 	client->adapter = adapter;
 	client->driver = &vpx3220_i2c_driver;
-	client->flags = I2C_CLIENT_ALLOW_USE;
 
 	/* Check for manufacture ID and part number */
 	if (kind < 0) {
@@ -722,11 +721,11 @@ vpx3220_attach_adapter (struct i2c_adapter *adapter)
  */
 
 static struct i2c_driver vpx3220_i2c_driver = {
-	.owner = THIS_MODULE,
-	.name = "vpx3220",
+	.driver = {
+		.name = "vpx3220",
+	},
 
 	.id = I2C_DRIVERID_VPX3220,
-	.flags = I2C_DF_NOTIFY,
 
 	.attach_adapter = vpx3220_attach_adapter,
 	.detach_client = vpx3220_detach_client,
diff --git a/drivers/media/video/wm8775.c b/drivers/media/video/wm8775.c
index a6936ad74fcf..bbfd55cd9948 100644
--- a/drivers/media/video/wm8775.c
+++ b/drivers/media/video/wm8775.c
@@ -40,10 +40,10 @@ MODULE_AUTHOR("Ulf Eklund, Hans Verkuil");
 MODULE_LICENSE("GPL");
 
 #define wm8775_err(fmt, arg...) do { \
-	printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->name, \
+	printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->driver.name, \
 	       i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
 #define wm8775_info(fmt, arg...) do { \
-	printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->name, \
+	printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->driver.name, \
 	       i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
 
 
@@ -168,7 +168,6 @@ static int wm8775_attach(struct i2c_adapter *adapter, int address, int kind)
 	client->addr = address;
 	client->adapter = adapter;
 	client->driver = &i2c_driver;
-	client->flags = I2C_CLIENT_ALLOW_USE;
 	snprintf(client->name, sizeof(client->name) - 1, "wm8775");
 
 	wm8775_info("chip found @ 0x%x (%s)\n", address << 1, adapter->name);
@@ -233,15 +232,15 @@ static int wm8775_detach(struct i2c_client *client)
 
 /* i2c implementation */
 static struct i2c_driver i2c_driver = {
-	.name = "wm8775",
+	.driver = {
+		.name = "wm8775",
+	},
 
 	.id = I2C_DRIVERID_WM8775,
-	.flags = I2C_DF_NOTIFY,
 
 	.attach_adapter = wm8775_probe,
 	.detach_client = wm8775_detach,
 	.command = wm8775_command,
-	.owner = THIS_MODULE,
 };
 
 
diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c
index 07bde9acd672..4034f1b45366 100644
--- a/drivers/media/video/zoran_driver.c
+++ b/drivers/media/video/zoran_driver.c
@@ -1311,7 +1311,7 @@ zoran_open (struct inode *inode,
 		res = -ENODEV;
 		goto open_unlock_and_return;
 	}
-	if (!try_module_get(zr->decoder->driver->owner)) {
+	if (!try_module_get(zr->decoder->driver->driver.owner)) {
 		dprintk(1,
 			KERN_ERR
 			"%s: failed to grab ownership of i2c decoder\n",
@@ -1321,13 +1321,13 @@ zoran_open (struct inode *inode,
 		goto open_unlock_and_return;
 	}
 	if (zr->encoder &&
-	    !try_module_get(zr->encoder->driver->owner)) {
+	    !try_module_get(zr->encoder->driver->driver.owner)) {
 		dprintk(1,
 			KERN_ERR
 			"%s: failed to grab ownership of i2c encoder\n",
 			ZR_DEVNAME(zr));
 		res = -EIO;
-		module_put(zr->decoder->driver->owner);
+		module_put(zr->decoder->driver->driver.owner);
 		module_put(THIS_MODULE);
 		goto open_unlock_and_return;
 	}
@@ -1393,9 +1393,9 @@ zoran_open (struct inode *inode,
 open_unlock_and_return:
 	/* if we grabbed locks, release them accordingly */
 	if (have_module_locks) {
-		module_put(zr->decoder->driver->owner);
+		module_put(zr->decoder->driver->driver.owner);
 		if (zr->encoder) {
-			module_put(zr->encoder->driver->owner);
+			module_put(zr->encoder->driver->driver.owner);
 		}
 		module_put(THIS_MODULE);
 	}
@@ -1461,9 +1461,9 @@ zoran_close (struct inode *inode,
 	kfree(fh);
 
 	/* release locks on the i2c modules */
-	module_put(zr->decoder->driver->owner);
+	module_put(zr->decoder->driver->driver.owner);
 	if (zr->encoder) {
-		 module_put(zr->encoder->driver->owner);
+		 module_put(zr->encoder->driver->driver.owner);
 	}
 	module_put(THIS_MODULE);
 
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index 4262a22adc22..537836068c49 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -313,13 +313,13 @@ mpt_reply(MPT_ADAPTER *ioc, u32 pa)
 		u32	 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
 		if (ioc->bus_type == FC)
 			mpt_fc_log_info(ioc, log_info);
-		else if (ioc->bus_type == SCSI)
+		else if (ioc->bus_type == SPI)
 			mpt_sp_log_info(ioc, log_info);
 		else if (ioc->bus_type == SAS)
 			mpt_sas_log_info(ioc, log_info);
 	}
 	if (ioc_stat & MPI_IOCSTATUS_MASK) {
-		if (ioc->bus_type == SCSI &&
+		if (ioc->bus_type == SPI &&
 		    cb_idx != mpt_stm_index &&
 		    cb_idx != mpt_lan_index)
 			mpt_sp_ioc_info(ioc, (u32)ioc_stat, mf);
@@ -1376,7 +1376,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
 	}
 	else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) {
 		ioc->prod_name = "LSI53C1030";
-		ioc->bus_type = SCSI;
+		ioc->bus_type = SPI;
 		/* 1030 Chip Fix. Disable Split transactions
 		 * for PCIX. Set MOST bits to zero if Rev < C0( = 8).
 		 */
@@ -1389,7 +1389,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
 	}
 	else if (pdev->device == MPI_MANUFACTPAGE_DEVID_1030_53C1035) {
 		ioc->prod_name = "LSI53C1035";
-		ioc->bus_type = SCSI;
+		ioc->bus_type = SPI;
 	}
 	else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064) {
 		ioc->prod_name = "LSISAS1064";
@@ -3042,7 +3042,7 @@ mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag)
 	/* Clear the internal flash bad bit - autoincrementing register,
 	 * so must do two writes.
 	 */
-	if (ioc->bus_type == SCSI) {
+	if (ioc->bus_type == SPI) {
 		/*
 		 * 1030 and 1035 H/W errata, workaround to access
 		 * the ClearFlashBadSignatureBit
@@ -3152,7 +3152,7 @@ KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
 	int cnt,cntdn;
 
 	dinitprintk((KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name));
-	if (ioc->bus_type == SCSI) {
+	if (ioc->bus_type == SPI) {
 		/* Always issue a Msg Unit Reset first. This will clear some
 		 * SCSI bus hang conditions.
 		 */
@@ -3580,7 +3580,7 @@ initChainBuffers(MPT_ADAPTER *ioc)
 	dinitprintk((KERN_INFO MYNAM ": %s Now numSGE=%d num_sge=%d num_chain=%d\n",
 		ioc->name, numSGE, num_sge, num_chain));
 
-	if (ioc->bus_type == SCSI)
+	if (ioc->bus_type == SPI)
 		num_chain *= MPT_SCSI_CAN_QUEUE;
 	else
 		num_chain *= MPT_FC_CAN_QUEUE;
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index bac8eb4186d2..6c48d1f54ac9 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -76,8 +76,8 @@
 #define COPYRIGHT	"Copyright (c) 1999-2005 " MODULEAUTHOR
 #endif
 
-#define MPT_LINUX_VERSION_COMMON	"3.03.04"
-#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.03.04"
+#define MPT_LINUX_VERSION_COMMON	"3.03.05"
+#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.03.05"
 #define WHAT_MAGIC_STRING		"@" "(" "#" ")"
 
 #define show_mptmod_ver(s,ver)  \
@@ -321,7 +321,7 @@ typedef struct _SYSIF_REGS
  *	Dynamic Multi-Pathing specific stuff...
  */
 
-/* VirtDevice negoFlags field */
+/* VirtTarget negoFlags field */
 #define MPT_TARGET_NO_NEGO_WIDE		0x01
 #define MPT_TARGET_NO_NEGO_SYNC		0x02
 #define MPT_TARGET_NO_NEGO_QAS		0x04
@@ -330,8 +330,7 @@ typedef struct _SYSIF_REGS
 /*
  *	VirtDevice - FC LUN device or SCSI target device
  */
-typedef struct _VirtDevice {
-	struct scsi_device	*device;
+typedef struct _VirtTarget {
 	u8			 tflags;
 	u8			 ioc_id;
 	u8			 target_id;
@@ -342,21 +341,18 @@ typedef struct _VirtDevice {
 	u8			 negoFlags;	/* bit field, see above */
 	u8			 raidVolume;	/* set, if RAID Volume */
 	u8			 type;		/* byte 0 of Inquiry data */
-	u8			 cflags;	/* controller flags */
-	u8			 rsvd1raid;
-	u16			 fc_phys_lun;
-	u16			 fc_xlat_lun;
 	u32			 num_luns;
 	u32			 luns[8];		/* Max LUNs is 256 */
-	u8			 pad[4];
 	u8			 inq_data[8];
-		/* IEEE Registered Extended Identifier
-		   obtained via INQUIRY VPD page 0x83 */
-		/* NOTE: Do not separate uniq_prepad and uniq_data
-		   as they are treateed as a single entity in the code */
-	u8			 uniq_prepad[8];
-	u8			 uniq_data[20];
-	u8			 pad2[4];
+} VirtTarget;
+
+typedef struct _VirtDevice {
+	VirtTarget	 	*vtarget;
+	u8			 ioc_id;
+	u8			 bus_id;
+	u8			 target_id;
+	u8			 configured_lun;
+	u32			 lun;
 } VirtDevice;
 
 /*
@@ -903,7 +899,7 @@ typedef struct _MPT_LOCAL_REPLY {
 
 typedef enum {
 	FC,
-	SCSI,
+	SPI,
 	SAS
 } BUS_TYPE;
 
@@ -912,7 +908,7 @@ typedef struct _MPT_SCSI_HOST {
 	int			  port;
 	u32			  pad0;
 	struct scsi_cmnd	**ScsiLookup;
-	VirtDevice		**Targets;
+	VirtTarget		**Targets;
 	MPT_LOCAL_REPLY		 *pLocal;		/* used for internal commands */
 	struct timer_list	  timer;
 		/* Pool of memory for holding SCpnts before doing
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
index 602138f8544d..959d2c5951b8 100644
--- a/drivers/message/fusion/mptctl.c
+++ b/drivers/message/fusion/mptctl.c
@@ -1245,7 +1245,7 @@ mptctl_gettargetinfo (unsigned long arg)
 	MPT_ADAPTER		*ioc;
 	struct Scsi_Host	*sh;
 	MPT_SCSI_HOST		*hd;
-	VirtDevice		*vdev;
+	VirtTarget		*vdev;
 	char			*pmem;
 	int			*pdata;
 	IOCPage2_t		*pIoc2;
@@ -1822,7 +1822,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
 	case MPI_FUNCTION_SCSI_IO_REQUEST:
 		if (ioc->sh) {
 			SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf;
-			VirtDevice	*pTarget = NULL;
+			VirtTarget	*pTarget = NULL;
 			MPT_SCSI_HOST	*hd = NULL;
 			int qtag = MPI_SCSIIO_CONTROL_UNTAGGED;
 			int scsidir = 0;
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index a628be9bbbad..ba61e1828858 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -84,13 +84,16 @@ static int	mptfcTaskCtx = -1;
 static int	mptfcInternalCtx = -1; /* Used only for internal commands */
 
 static struct scsi_host_template mptfc_driver_template = {
+	.module				= THIS_MODULE,
 	.proc_name			= "mptfc",
 	.proc_info			= mptscsih_proc_info,
 	.name				= "MPT FC Host",
 	.info				= mptscsih_info,
 	.queuecommand			= mptscsih_qcmd,
+	.target_alloc			= mptscsih_target_alloc,
 	.slave_alloc			= mptscsih_slave_alloc,
 	.slave_configure		= mptscsih_slave_configure,
+	.target_destroy			= mptscsih_target_destroy,
 	.slave_destroy			= mptscsih_slave_destroy,
 	.change_queue_depth 		= mptscsih_change_queue_depth,
 	.eh_abort_handler		= mptscsih_abort,
@@ -167,13 +170,15 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 		printk(MYIOC_s_WARN_FMT
 		  "Skipping because it's not operational!\n",
 		  ioc->name);
-		return -ENODEV;
+		error = -ENODEV;
+		goto out_mptfc_probe;
 	}
 
 	if (!ioc->active) {
 		printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
 		  ioc->name);
-		return -ENODEV;
+		error = -ENODEV;
+		goto out_mptfc_probe;
 	}
 
 	/*  Sanity check - ensure at least 1 port is INITIATOR capable
@@ -198,7 +203,8 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 		printk(MYIOC_s_WARN_FMT
 			"Unable to register controller with SCSI subsystem\n",
 			ioc->name);
-                return -1;
+		error = -1;
+		goto out_mptfc_probe;
         }
 
 	spin_lock_irqsave(&ioc->FreeQlock, flags);
@@ -266,7 +272,7 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	mem = kmalloc(sz, GFP_ATOMIC);
 	if (mem == NULL) {
 		error = -ENOMEM;
-		goto mptfc_probe_failed;
+		goto out_mptfc_probe;
 	}
 
 	memset(mem, 0, sz);
@@ -284,14 +290,14 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	mem = kmalloc(sz, GFP_ATOMIC);
 	if (mem == NULL) {
 		error = -ENOMEM;
-		goto mptfc_probe_failed;
+		goto out_mptfc_probe;
 	}
 
 	memset(mem, 0, sz);
-	hd->Targets = (VirtDevice **) mem;
+	hd->Targets = (VirtTarget **) mem;
 
 	dprintk((KERN_INFO
-	  "  Targets @ %p, sz=%d\n", hd->Targets, sz));
+	  "  vdev @ %p, sz=%d\n", hd->Targets, sz));
 
 	/* Clear the TM flags
 	 */
@@ -330,13 +336,13 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	if(error) {
 		dprintk((KERN_ERR MYNAM
 		  "scsi_add_host failed\n"));
-		goto mptfc_probe_failed;
+		goto out_mptfc_probe;
 	}
 
 	scsi_scan_host(sh);
 	return 0;
 
-mptfc_probe_failed:
+out_mptfc_probe:
 
 	mptscsih_remove(pdev);
 	return error;
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index e0a8bb8ba7d8..17e9757e728b 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -228,31 +228,35 @@ static void mptsas_print_expander_pg1(SasExpanderPage1_t *pg1)
  * implement ->target_alloc.
  */
 static int
-mptsas_slave_alloc(struct scsi_device *device)
+mptsas_slave_alloc(struct scsi_device *sdev)
 {
-	struct Scsi_Host	*host = device->host;
+	struct Scsi_Host	*host = sdev->host;
 	MPT_SCSI_HOST		*hd = (MPT_SCSI_HOST *)host->hostdata;
 	struct sas_rphy		*rphy;
 	struct mptsas_portinfo	*p;
+	VirtTarget		*vtarget;
 	VirtDevice		*vdev;
-	uint			target = device->id;
+	struct scsi_target 	*starget;
 	int i;
 
-	if ((vdev = hd->Targets[target]) != NULL)
-		goto out;
-
 	vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL);
 	if (!vdev) {
 		printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
 				hd->ioc->name, sizeof(VirtDevice));
 		return -ENOMEM;
 	}
-
 	memset(vdev, 0, sizeof(VirtDevice));
-	vdev->tflags = MPT_TARGET_FLAGS_Q_YES|MPT_TARGET_FLAGS_VALID_INQUIRY;
 	vdev->ioc_id = hd->ioc->id;
+	sdev->hostdata = vdev;
+	starget = scsi_target(sdev);
+	vtarget = starget->hostdata;
+	vdev->vtarget = vtarget;
+	if (vtarget->num_luns == 0) {
+		vtarget->tflags = MPT_TARGET_FLAGS_Q_YES|MPT_TARGET_FLAGS_VALID_INQUIRY;
+		hd->Targets[sdev->id] = vtarget;
+	}
 
-	rphy = dev_to_rphy(device->sdev_target->dev.parent);
+	rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
 	list_for_each_entry(p, &hd->ioc->sas_topology, list) {
 		for (i = 0; i < p->num_phys; i++) {
 			if (p->phy_info[i].attached.sas_address ==
@@ -260,7 +264,7 @@ mptsas_slave_alloc(struct scsi_device *device)
 				vdev->target_id =
 					p->phy_info[i].attached.target;
 				vdev->bus_id = p->phy_info[i].attached.bus;
-				hd->Targets[device->id] = vdev;
+				vdev->lun = sdev->lun;
 				goto out;
 			}
 		}
@@ -271,19 +275,24 @@ mptsas_slave_alloc(struct scsi_device *device)
 	return -ENODEV;
 
  out:
-	vdev->num_luns++;
-	device->hostdata = vdev;
+	vtarget->ioc_id = vdev->ioc_id;
+	vtarget->target_id = vdev->target_id;
+	vtarget->bus_id = vdev->bus_id;
+	vtarget->num_luns++;
 	return 0;
 }
 
 static struct scsi_host_template mptsas_driver_template = {
+	.module				= THIS_MODULE,
 	.proc_name			= "mptsas",
 	.proc_info			= mptscsih_proc_info,
 	.name				= "MPT SPI Host",
 	.info				= mptscsih_info,
 	.queuecommand			= mptscsih_qcmd,
+	.target_alloc			= mptscsih_target_alloc,
 	.slave_alloc			= mptsas_slave_alloc,
 	.slave_configure		= mptscsih_slave_configure,
+	.target_destroy			= mptscsih_target_destroy,
 	.slave_destroy			= mptscsih_slave_destroy,
 	.change_queue_depth 		= mptscsih_change_queue_depth,
 	.eh_abort_handler		= mptscsih_abort,
@@ -986,7 +995,6 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc, int *index)
 		goto out_free_port_info;
 
 	list_add_tail(&port_info->list, &ioc->sas_topology);
-
 	for (i = 0; i < port_info->num_phys; i++) {
 		mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
 			(MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
@@ -1133,13 +1141,15 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 		printk(MYIOC_s_WARN_FMT
 		  "Skipping because it's not operational!\n",
 		  ioc->name);
-		return -ENODEV;
+		error = -ENODEV;
+		goto out_mptsas_probe;
 	}
 
 	if (!ioc->active) {
 		printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
 		  ioc->name);
-		return -ENODEV;
+		error = -ENODEV;
+		goto out_mptsas_probe;
 	}
 
 	/*  Sanity check - ensure at least 1 port is INITIATOR capable
@@ -1163,7 +1173,8 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 		printk(MYIOC_s_WARN_FMT
 			"Unable to register controller with SCSI subsystem\n",
 			ioc->name);
-                return -1;
+		error = -1;
+		goto out_mptsas_probe;
         }
 
 	spin_lock_irqsave(&ioc->FreeQlock, flags);
@@ -1237,7 +1248,7 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	mem = kmalloc(sz, GFP_ATOMIC);
 	if (mem == NULL) {
 		error = -ENOMEM;
-		goto mptsas_probe_failed;
+		goto out_mptsas_probe;
 	}
 
 	memset(mem, 0, sz);
@@ -1255,14 +1266,14 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	mem = kmalloc(sz, GFP_ATOMIC);
 	if (mem == NULL) {
 		error = -ENOMEM;
-		goto mptsas_probe_failed;
+		goto out_mptsas_probe;
 	}
 
 	memset(mem, 0, sz);
-	hd->Targets = (VirtDevice **) mem;
+	hd->Targets = (VirtTarget **) mem;
 
 	dprintk((KERN_INFO
-	  "  Targets @ %p, sz=%d\n", hd->Targets, sz));
+	  "  vtarget @ %p, sz=%d\n", hd->Targets, sz));
 
 	/* Clear the TM flags
 	 */
@@ -1308,14 +1319,14 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	if (error) {
 		dprintk((KERN_ERR MYNAM
 		  "scsi_add_host failed\n"));
-		goto mptsas_probe_failed;
+		goto out_mptsas_probe;
 	}
 
 	mptsas_scan_sas_topology(ioc);
 
 	return 0;
 
-mptsas_probe_failed:
+out_mptsas_probe:
 
 	mptscsih_remove(pdev);
 	return error;
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index b7b9846ff3fd..93a16fa3c4ba 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -150,28 +150,29 @@ static int	mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 tar
 int		mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
 int		mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
 
-static void	mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen);
-static void	mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56);
-static void	mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq);
+static void	mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, u8 lun, char *data, int dlen);
+static void	mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *vtarget, char byte56);
 static void	mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags);
-static void	mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id);
+static void	mptscsih_no_negotiate(MPT_SCSI_HOST *hd, struct scsi_cmnd *sc);
 static int	mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target, int flags);
 static int	mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus);
 int		mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
 static int	mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
-static int	mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum);
+static void	mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice);
+static void	mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtTarget *vtarget);
+static int	mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id);
 
 static struct work_struct   mptscsih_persistTask;
 
 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
 static int	mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io);
 static void	mptscsih_domainValidation(void *hd);
-static int	mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id);
 static void	mptscsih_qas_check(MPT_SCSI_HOST *hd, int id);
 static int	mptscsih_doDv(MPT_SCSI_HOST *hd, int channel, int target);
 static void	mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage);
 static void	mptscsih_fillbuf(char *buffer, int size, int index, int width);
 static void	mptscsih_set_dvflags_raid(MPT_SCSI_HOST *hd, int id);
+static void	mptscsih_set_dvflags(MPT_SCSI_HOST *hd, struct scsi_cmnd *sc);
 #endif
 
 void 		mptscsih_remove(struct pci_dev *);
@@ -627,7 +628,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 		dreplyprintk((KERN_NOTICE "Reply ha=%d id=%d lun=%d:\n"
 			"IOCStatus=%04xh SCSIState=%02xh SCSIStatus=%02xh\n"
 			"resid=%d bufflen=%d xfer_cnt=%d\n",
-			ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1],
+			ioc->id, sc->device->id, sc->device->lun,
 			status, scsi_state, scsi_status, sc->resid,
 			sc->request_bufflen, xfer_cnt));
 
@@ -641,7 +642,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 		    pScsiReply->ResponseInfo) {
 			printk(KERN_NOTICE "ha=%d id=%d lun=%d: "
 			"FCP_ResponseInfo=%08xh\n",
-			ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1],
+			ioc->id, sc->device->id, sc->device->lun,
 			le32_to_cpu(pScsiReply->ResponseInfo));
 		}
 
@@ -677,8 +678,8 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 			sc->result = DID_RESET << 16;
 
 			/* GEM Workaround. */
-			if (ioc->bus_type == SCSI)
-				mptscsih_no_negotiate(hd, sc->device->id);
+			if (ioc->bus_type == SPI)
+				mptscsih_no_negotiate(hd, sc);
 			break;
 
 		case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:	/* 0x0049 */
@@ -892,16 +893,15 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
  *		when a lun is disable by mid-layer.
  *		Do NOT access the referenced scsi_cmnd structure or
  *		members. Will cause either a paging or NULL ptr error.
- *	@hd: Pointer to a SCSI HOST structure
- *	@target: target id
- *	@lun: lun
+ *      @hd: Pointer to a SCSI HOST structure
+ *	@vdevice: per device private data
  *
  *	Returns: None.
  *
  *	Called from slave_destroy.
  */
 static void
-mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, uint target, uint lun)
+mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
 {
 	SCSIIORequest_t	*mf = NULL;
 	int		 ii;
@@ -909,7 +909,7 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, uint target, uint lun)
 	struct scsi_cmnd *sc;
 
 	dsprintk((KERN_INFO MYNAM ": search_running target %d lun %d max %d\n",
-			target, lun, max));
+			vdevice->target_id, vdevice->lun, max));
 
 	for (ii=0; ii < max; ii++) {
 		if ((sc = hd->ScsiLookup[ii]) != NULL) {
@@ -919,7 +919,7 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, uint target, uint lun)
 			dsprintk(( "search_running: found (sc=%p, mf = %p) target %d, lun %d \n",
 					hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1]));
 
-			if ((mf->TargetID != ((u8)target)) || (mf->LUN[1] != ((u8) lun)))
+			if ((mf->TargetID != ((u8)vdevice->target_id)) || (mf->LUN[1] != ((u8) vdevice->lun)))
 				continue;
 
 			/* Cleanup
@@ -993,8 +993,10 @@ mptscsih_remove(struct pci_dev *pdev)
 	MPT_ADAPTER 		*ioc = pci_get_drvdata(pdev);
 	struct Scsi_Host 	*host = ioc->sh;
 	MPT_SCSI_HOST		*hd;
+#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
 	int 		 	count;
 	unsigned long	 	flags;
+#endif	
 	int sz1;
 
 	if(!host) {
@@ -1075,11 +1077,6 @@ mptscsih_shutdown(struct pci_dev *pdev)
 
 	hd = (MPT_SCSI_HOST *)host->hostdata;
 
-	/* Flush the cache of this adapter
-	 */
-	if(hd != NULL)
-		mptscsih_synchronize_cache(hd, 0);
-
 }
 
 #ifdef CONFIG_PM
@@ -1286,7 +1283,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 	MPT_SCSI_HOST		*hd;
 	MPT_FRAME_HDR		*mf;
 	SCSIIORequest_t		*pScsiReq;
-	VirtDevice		*pTarget = SCpnt->device->hostdata;
+	VirtDevice		*vdev = SCpnt->device->hostdata;
 	int	 lun;
 	u32	 datalen;
 	u32	 scsictl;
@@ -1341,8 +1338,8 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 	/* Default to untagged. Once a target structure has been allocated,
 	 * use the Inquiry data to determine if device supports tagged.
 	 */
-	if (pTarget
-	    && (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)
+	if (vdev
+	    && (vdev->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)
 	    && (SCpnt->device->tagged_supported)) {
 		scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ;
 	} else {
@@ -1351,8 +1348,8 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 
 	/* Use the above information to set up the message frame
 	 */
-	pScsiReq->TargetID = (u8) pTarget->target_id;
-	pScsiReq->Bus = pTarget->bus_id;
+	pScsiReq->TargetID = (u8) vdev->target_id;
+	pScsiReq->Bus = vdev->bus_id;
 	pScsiReq->ChainOffset = 0;
 	pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
 	pScsiReq->CDBLength = SCpnt->cmd_len;
@@ -1403,8 +1400,8 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 	SCpnt->host_scribble = NULL;
 
 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
-	if (hd->ioc->bus_type == SCSI) {
-		int dvStatus = hd->ioc->spi_data.dvStatus[pTarget->target_id];
+	if (hd->ioc->bus_type == SPI) {
+		int dvStatus = hd->ioc->spi_data.dvStatus[vdev->target_id];
 		int issueCmd = 1;
 
 		if (dvStatus || hd->ioc->spi_data.forceDv) {
@@ -1437,7 +1434,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 			/* Set the DV flags.
 			 */
 			if (dvStatus & MPT_SCSICFG_DV_NOT_DONE)
-				mptscsih_set_dvflags(hd, pScsiReq);
+				mptscsih_set_dvflags(hd, SCpnt);
 
 			if (!issueCmd)
 				goto fail;
@@ -1741,6 +1738,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
 	u32		 ctx2abort;
 	int		 scpnt_idx;
 	int		 retval;
+	VirtDevice	 *vdev;
 
 	/* If we can't locate our host adapter structure, return FAILED status.
 	 */
@@ -1790,8 +1788,9 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
 
 	hd->abortSCpnt = SCpnt;
 
+	vdev = SCpnt->device->hostdata;
 	retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
-		SCpnt->device->channel, SCpnt->device->id, SCpnt->device->lun,
+		vdev->bus_id, vdev->target_id, vdev->lun,
 		ctx2abort, 2 /* 2 second timeout */);
 
 	printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n",
@@ -1822,6 +1821,7 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
 {
 	MPT_SCSI_HOST	*hd;
 	int		 retval;
+	VirtDevice	 *vdev;
 
 	/* If we can't locate our host adapter structure, return FAILED status.
 	 */
@@ -1839,8 +1839,9 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
 	       hd->ioc->name, SCpnt);
 	scsi_print_command(SCpnt);
 
+	vdev = SCpnt->device->hostdata;
 	retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
-		SCpnt->device->channel, SCpnt->device->id,
+		vdev->bus_id, vdev->target_id,
 		0, 0, 5 /* 5 second timeout */);
 
 	printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n",
@@ -1871,6 +1872,7 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
 {
 	MPT_SCSI_HOST	*hd;
 	int		 retval;
+	VirtDevice	 *vdev;
 
 	/* If we can't locate our host adapter structure, return FAILED status.
 	 */
@@ -1888,8 +1890,9 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
 	if (hd->timeouts < -1)
 		hd->timeouts++;
 
+	vdev = SCpnt->device->hostdata;
 	retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
-		SCpnt->device->channel, 0, 0, 0, 5 /* 5 second timeout */);
+		vdev->bus_id, 0, 0, 0, 5 /* 5 second timeout */);
 
 	printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n",
 		hd->ioc->name,
@@ -2151,23 +2154,36 @@ mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  *	OS entry point to allow host driver to alloc memory
+ *	for each scsi target. Called once per device the bus scan.
+ *	Return non-zero if allocation fails.
+ */
+int
+mptscsih_target_alloc(struct scsi_target *starget)
+{
+	VirtTarget		*vtarget;
+
+	vtarget = kmalloc(sizeof(VirtTarget), GFP_KERNEL);
+	if (!vtarget)
+		return -ENOMEM;
+	memset(vtarget, 0, sizeof(VirtTarget));
+	starget->hostdata = vtarget;
+	return 0;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	OS entry point to allow host driver to alloc memory
  *	for each scsi device. Called once per device the bus scan.
  *	Return non-zero if allocation fails.
- *	Init memory once per id (not LUN).
  */
 int
-mptscsih_slave_alloc(struct scsi_device *device)
+mptscsih_slave_alloc(struct scsi_device *sdev)
 {
-	struct Scsi_Host	*host = device->host;
+	struct Scsi_Host	*host = sdev->host;
 	MPT_SCSI_HOST		*hd = (MPT_SCSI_HOST *)host->hostdata;
+	VirtTarget		*vtarget;
 	VirtDevice		*vdev;
-	uint			target = device->id;
-
-	if (hd == NULL)
-		return -ENODEV;
-
-	if ((vdev = hd->Targets[target]) != NULL)
-		goto out;
+	struct scsi_target 	*starget;
 
 	vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL);
 	if (!vdev) {
@@ -2177,25 +2193,33 @@ mptscsih_slave_alloc(struct scsi_device *device)
 	}
 
 	memset(vdev, 0, sizeof(VirtDevice));
-	vdev->tflags = MPT_TARGET_FLAGS_Q_YES;
 	vdev->ioc_id = hd->ioc->id;
-	vdev->target_id = device->id;
-	vdev->bus_id = device->channel;
-	vdev->raidVolume = 0;
-	hd->Targets[device->id] = vdev;
-	if (hd->ioc->bus_type == SCSI) {
-		if (hd->ioc->raid_data.isRaid & (1 << device->id)) {
-			vdev->raidVolume = 1;
-			ddvtprintk((KERN_INFO
-			    "RAID Volume @ id %d\n", device->id));
+	vdev->target_id = sdev->id;
+	vdev->bus_id = sdev->channel;
+	vdev->lun = sdev->lun;
+	sdev->hostdata = vdev;
+
+	starget = scsi_target(sdev);
+	vtarget = starget->hostdata;
+	vdev->vtarget = vtarget;
+
+	if (vtarget->num_luns == 0) {
+		hd->Targets[sdev->id] = vtarget;
+		vtarget->ioc_id = hd->ioc->id;
+		vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
+		vtarget->target_id = sdev->id;
+		vtarget->bus_id = sdev->channel;
+		if (hd->ioc->bus_type == SPI) {
+			if (hd->ioc->raid_data.isRaid & (1 << sdev->id)) {
+				vtarget->raidVolume = 1;
+				ddvtprintk((KERN_INFO
+				    "RAID Volume @ id %d\n", sdev->id));
+			}
+		} else {
+			vtarget->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
 		}
-	} else {
-		vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
 	}
-
- out:
-	vdev->num_luns++;
-	device->hostdata = vdev;
+	vtarget->num_luns++;
 	return 0;
 }
 
@@ -2204,40 +2228,52 @@ mptscsih_slave_alloc(struct scsi_device *device)
  *	Called if no device present or device being unloaded
  */
 void
-mptscsih_slave_destroy(struct scsi_device *device)
+mptscsih_target_destroy(struct scsi_target *starget)
 {
-	struct Scsi_Host	*host = device->host;
-	MPT_SCSI_HOST		*hd = (MPT_SCSI_HOST *)host->hostdata;
-	VirtDevice		*vdev;
-	uint			target = device->id;
-	uint			lun = device->lun;
-
-	if (hd == NULL)
-		return;
-
-	mptscsih_search_running_cmds(hd, target, lun);
-
-	vdev = hd->Targets[target];
-	vdev->luns[0] &= ~(1 << lun);
-	if (--vdev->num_luns)
-		return;
-
-	kfree(hd->Targets[target]);
-	hd->Targets[target] = NULL;
-
-	if (hd->ioc->bus_type == SCSI) {
-		if (mptscsih_is_phys_disk(hd->ioc, target)) {
-			hd->ioc->spi_data.forceDv |= MPT_SCSICFG_RELOAD_IOC_PG3;
-		} else {
-			hd->ioc->spi_data.dvStatus[target] =
-				MPT_SCSICFG_NEGOTIATE;
+	if (starget->hostdata)
+		kfree(starget->hostdata);
+	starget->hostdata = NULL;
+}
 
-			if (!hd->negoNvram) {
-				hd->ioc->spi_data.dvStatus[target] |=
-					MPT_SCSICFG_DV_NOT_DONE;
+/*
+ *	OS entry point to allow for host driver to free allocated memory
+ *	Called if no device present or device being unloaded
+ */
+void
+mptscsih_slave_destroy(struct scsi_device *sdev)
+{
+	struct Scsi_Host	*host = sdev->host;
+	MPT_SCSI_HOST		*hd = (MPT_SCSI_HOST *)host->hostdata;
+	VirtTarget		*vtarget;
+	VirtDevice		*vdevice;
+	struct scsi_target 	*starget;
+
+	starget = scsi_target(sdev);
+	vtarget = starget->hostdata;
+	vdevice = sdev->hostdata;
+
+	mptscsih_search_running_cmds(hd, vdevice);
+	vtarget->luns[0] &= ~(1 << vdevice->lun);
+	vtarget->num_luns--;
+	if (vtarget->num_luns == 0) {
+		mptscsih_negotiate_to_asyn_narrow(hd, vtarget);
+		if (hd->ioc->bus_type == SPI) {
+			if (mptscsih_is_phys_disk(hd->ioc, vtarget->target_id)) {
+				hd->ioc->spi_data.forceDv |= MPT_SCSICFG_RELOAD_IOC_PG3;
+			} else {
+				hd->ioc->spi_data.dvStatus[vtarget->target_id] =
+					MPT_SCSICFG_NEGOTIATE;
+				if (!hd->negoNvram) {
+					hd->ioc->spi_data.dvStatus[vtarget->target_id] |=
+						MPT_SCSICFG_DV_NOT_DONE;
+				}
 			}
 		}
+		hd->Targets[sdev->id] = NULL;
 	}
+	mptscsih_synchronize_cache(hd, vdevice);
+	kfree(vdevice);
+	sdev->hostdata = NULL;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -2251,22 +2287,21 @@ mptscsih_slave_destroy(struct scsi_device *device)
 int
 mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
 {
-	MPT_SCSI_HOST	*hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
-	VirtDevice *pTarget;
-	int	max_depth;
-	int	tagged;
-
-	if (hd == NULL)
-		return 0;
-	if (!(pTarget = hd->Targets[sdev->id]))
-		return 0;
-
-	if (hd->ioc->bus_type == SCSI) {
-		if (pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
-			if (!(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES))
+	MPT_SCSI_HOST		*hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
+	VirtTarget 		*vtarget;
+	struct scsi_target 	*starget;
+	int			max_depth;
+	int			tagged;
+
+	starget = scsi_target(sdev);
+	vtarget = starget->hostdata;
+
+	if (hd->ioc->bus_type == SPI) {
+		if (vtarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
+			if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES))
 				max_depth = 1;
-			else if (((pTarget->inq_data[0] & 0x1f) == 0x00) &&
-			         (pTarget->minSyncFactor <= MPT_ULTRA160 ))
+			else if (((vtarget->inq_data[0] & 0x1f) == 0x00) &&
+			         (vtarget->minSyncFactor <= MPT_ULTRA160 ))
 				max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
 			else
 				max_depth = MPT_SCSI_CMD_PER_DEV_LOW;
@@ -2295,64 +2330,58 @@ mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
  *	Return non-zero if fails.
  */
 int
-mptscsih_slave_configure(struct scsi_device *device)
+mptscsih_slave_configure(struct scsi_device *sdev)
 {
-	struct Scsi_Host	*sh = device->host;
-	VirtDevice		*pTarget;
+	struct Scsi_Host	*sh = sdev->host;
+	VirtTarget		*vtarget;
+	VirtDevice		*vdevice;
+	struct scsi_target 	*starget;
 	MPT_SCSI_HOST		*hd = (MPT_SCSI_HOST *)sh->hostdata;
+	int			indexed_lun, lun_index;
 
-	if ((hd == NULL) || (hd->Targets == NULL)) {
-		return 0;
-	}
+	starget = scsi_target(sdev);
+	vtarget = starget->hostdata;
+	vdevice = sdev->hostdata;
 
 	dsprintk((MYIOC_s_INFO_FMT
 		"device @ %p, id=%d, LUN=%d, channel=%d\n",
-		hd->ioc->name, device, device->id, device->lun, device->channel));
-	dsprintk((MYIOC_s_INFO_FMT
-		"sdtr %d wdtr %d ppr %d inq length=%d\n",
-		hd->ioc->name, device->sdtr, device->wdtr,
-		device->ppr, device->inquiry_len));
-
-	if (device->id > sh->max_id) {
+		hd->ioc->name, sdev, sdev->id, sdev->lun, sdev->channel));
+	if (hd->ioc->bus_type == SPI)
+		dsprintk((MYIOC_s_INFO_FMT
+		    "sdtr %d wdtr %d ppr %d inq length=%d\n",
+		    hd->ioc->name, sdev->sdtr, sdev->wdtr,
+		    sdev->ppr, sdev->inquiry_len));
+
+	if (sdev->id > sh->max_id) {
 		/* error case, should never happen */
-		scsi_adjust_queue_depth(device, 0, 1);
-		goto slave_configure_exit;
-	}
-
-	pTarget = hd->Targets[device->id];
-
-	if (pTarget == NULL) {
-		/* Driver doesn't know about this device.
-		 * Kernel may generate a "Dummy Lun 0" which
-		 * may become a real Lun if a
-		 * "scsi add-single-device" command is executed
-		 * while the driver is active (hot-plug a
-		 * device).  LSI Raid controllers need
-		 * queue_depth set to DEV_HIGH for this reason.
-		 */
-		scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG,
-			MPT_SCSI_CMD_PER_DEV_HIGH);
+		scsi_adjust_queue_depth(sdev, 0, 1);
 		goto slave_configure_exit;
 	}
 
-	mptscsih_initTarget(hd, device->channel, device->id, device->lun,
-		device->inquiry, device->inquiry_len );
-	mptscsih_change_queue_depth(device, MPT_SCSI_CMD_PER_DEV_HIGH);
+	vdevice->configured_lun=1;
+	lun_index = (vdevice->lun >> 5);  /* 32 luns per lun_index */
+	indexed_lun = (vdevice->lun % 32);
+	vtarget->luns[lun_index] |= (1 << indexed_lun);
+	mptscsih_initTarget(hd, vtarget, sdev->lun, sdev->inquiry,
+	    sdev->inquiry_len );
+	mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH);
 
 	dsprintk((MYIOC_s_INFO_FMT
 		"Queue depth=%d, tflags=%x\n",
-		hd->ioc->name, device->queue_depth, pTarget->tflags));
+		hd->ioc->name, sdev->queue_depth, vtarget->tflags));
 
-	dsprintk((MYIOC_s_INFO_FMT
-		"negoFlags=%x, maxOffset=%x, SyncFactor=%x\n",
-		hd->ioc->name, pTarget->negoFlags, pTarget->maxOffset, pTarget->minSyncFactor));
+	if (hd->ioc->bus_type == SPI)
+		dsprintk((MYIOC_s_INFO_FMT
+		    "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n",
+		    hd->ioc->name, vtarget->negoFlags, vtarget->maxOffset,
+		    vtarget->minSyncFactor));
 
 slave_configure_exit:
 
 	dsprintk((MYIOC_s_INFO_FMT
 		"tagged %d, simple %d, ordered %d\n",
-		hd->ioc->name,device->tagged_supported, device->simple_tags,
-		device->ordered_tags));
+		hd->ioc->name,sdev->tagged_supported, sdev->simple_tags,
+		sdev->ordered_tags));
 
 	return 0;
 }
@@ -2370,16 +2399,14 @@ slave_configure_exit:
 static void
 mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
 {
-	VirtDevice	*target;
+	VirtDevice	*vdev;
 	SCSIIORequest_t	*pReq;
 	u32		 sense_count = le32_to_cpu(pScsiReply->SenseCount);
-	int		 index;
 
 	/* Get target structure
 	 */
 	pReq = (SCSIIORequest_t *) mf;
-	index = (int) pReq->TargetID;
-	target = hd->Targets[index];
+	vdev = sc->device->hostdata;
 
 	if (sense_count) {
 		u8 *sense_data;
@@ -2393,7 +2420,7 @@ mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR
 		/* Log SMART data (asc = 0x5D, non-IM case only) if required.
 		 */
 		if ((hd->ioc->events) && (hd->ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) {
-			if ((sense_data[12] == 0x5D) && (target->raidVolume == 0)) {
+			if ((sense_data[12] == 0x5D) && (vdev->vtarget->raidVolume == 0)) {
 				int idx;
 				MPT_ADAPTER *ioc = hd->ioc;
 
@@ -2403,7 +2430,7 @@ mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR
 
 				ioc->events[idx].data[0] = (pReq->LUN[1] << 24) ||
 					(MPI_EVENT_SCSI_DEV_STAT_RC_SMART_DATA << 16) ||
-					(pReq->Bus << 8) || pReq->TargetID;
+					(sc->device->channel << 8) || sc->device->id;
 
 				ioc->events[idx].data[1] = (sense_data[13] << 8) || sense_data[12];
 
@@ -2503,9 +2530,9 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
 		/* 2. Chain Buffer initialization
 		 */
 
-		/* 4. Renegotiate to all devices, if SCSI
+		/* 4. Renegotiate to all devices, if SPI
 		 */
-		if (ioc->bus_type == SCSI) {
+		if (ioc->bus_type == SPI) {
 			dnegoprintk(("writeSDP1: ALL_IDS USE_NVRAM\n"));
 			mptscsih_writeSDP1(hd, 0, 0, MPT_SCSICFG_ALL_IDS | MPT_SCSICFG_USE_NVRAM);
 		}
@@ -2534,7 +2561,7 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
 
 		/* 7. Set flag to force DV and re-read IOC Page 3
 		 */
-		if (ioc->bus_type == SCSI) {
+		if (ioc->bus_type == SPI) {
 			ioc->spi_data.forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
 			ddvtprintk(("Set reload IOC Pg3 Flag\n"));
 		}
@@ -2576,7 +2603,7 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
 		break;
 	case MPI_EVENT_IOC_BUS_RESET:			/* 04 */
 	case MPI_EVENT_EXT_BUS_RESET:			/* 05 */
-		if (hd && (ioc->bus_type == SCSI) && (hd->soft_resets < -1))
+		if (hd && (ioc->bus_type == SPI) && (hd->soft_resets < -1))
 			hd->soft_resets++;
 		break;
 	case MPI_EVENT_LOGOUT:				/* 09 */
@@ -2597,11 +2624,11 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
 
 	case MPI_EVENT_INTEGRATED_RAID:			/* 0B */
 	{
+#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
 		pMpiEventDataRaid_t pRaidEventData =
 		    (pMpiEventDataRaid_t) pEvReply->Data;
-#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
 		/* Domain Validation Needed */
-		if (ioc->bus_type == SCSI &&
+		if (ioc->bus_type == SPI &&
 		    pRaidEventData->ReasonCode ==
 		    MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED)
 			mptscsih_set_dvflags_raid(hd, pRaidEventData->PhysDiskNum);
@@ -2632,8 +2659,7 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
 /*
  *	mptscsih_initTarget - Target, LUN alloc/free functionality.
  *	@hd: Pointer to MPT_SCSI_HOST structure
- *	@bus_id: Bus number (?)
- *	@target_id: SCSI target id
+ *	@vtarget: per target private data
  *	@lun: SCSI LUN id
  *	@data: Pointer to data
  *	@dlen: Number of INQUIRY bytes
@@ -2646,15 +2672,14 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
  *
  */
 static void
-mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen)
+mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, u8 lun, char *data, int dlen)
 {
-	int		indexed_lun, lun_index;
-	VirtDevice	*vdev;
 	SpiCfgData	*pSpi;
 	char		data_56;
+	int		inq_len;
 
 	dinitprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n",
-			hd->ioc->name, bus_id, target_id, lun, hd));
+		hd->ioc->name, vtarget->bus_id, vtarget->target_id, lun, hd));
 
 	/*
 	 * If the peripheral qualifier filter is enabled then if the target reports a 0x1
@@ -2674,75 +2699,68 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *
 	if (data[0] & 0xe0)
 		return;
 
-	if ((vdev = hd->Targets[target_id]) == NULL) {
+	if (vtarget == NULL)
 		return;
-	}
 
-	lun_index = (lun >> 5);  /* 32 luns per lun_index */
-	indexed_lun = (lun % 32);
-	vdev->luns[lun_index] |= (1 << indexed_lun);
-
-	if (hd->ioc->bus_type == SCSI) {
-		if ((data[0] == TYPE_PROCESSOR) && (hd->ioc->spi_data.Saf_Te)) {
-			/* Treat all Processors as SAF-TE if
-			 * command line option is set */
-			vdev->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
-			mptscsih_writeIOCPage4(hd, target_id, bus_id);
-		}else if ((data[0] == TYPE_PROCESSOR) &&
-			!(vdev->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) {
-			if ( dlen > 49 ) {
-				vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
-				if ( data[44] == 'S' &&
-				     data[45] == 'A' &&
-				     data[46] == 'F' &&
-				     data[47] == '-' &&
-				     data[48] == 'T' &&
-				     data[49] == 'E' ) {
-					vdev->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
-					mptscsih_writeIOCPage4(hd, target_id, bus_id);
-				}
+	if (data)
+		vtarget->type = data[0];
+
+	if (hd->ioc->bus_type != SPI)
+		return;
+
+	if ((data[0] == TYPE_PROCESSOR) && (hd->ioc->spi_data.Saf_Te)) {
+		/* Treat all Processors as SAF-TE if
+		 * command line option is set */
+		vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
+		mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id);
+	}else if ((data[0] == TYPE_PROCESSOR) &&
+		!(vtarget->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) {
+		if ( dlen > 49 ) {
+			vtarget->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
+			if ( data[44] == 'S' &&
+			     data[45] == 'A' &&
+			     data[46] == 'F' &&
+			     data[47] == '-' &&
+			     data[48] == 'T' &&
+			     data[49] == 'E' ) {
+				vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
+				mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id);
 			}
 		}
-		if (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) {
-			if ( dlen > 8 ) {
-				memcpy (vdev->inq_data, data, 8);
-			} else {
-				memcpy (vdev->inq_data, data, dlen);
-			}
+	}
+	if (!(vtarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) {
+		inq_len = dlen < 8 ? dlen : 8;
+		memcpy (vtarget->inq_data, data, inq_len);
+		/* If have not done DV, set the DV flag.
+		 */
+		pSpi = &hd->ioc->spi_data;
+		if ((data[0] == TYPE_TAPE) || (data[0] == TYPE_PROCESSOR)) {
+			if (pSpi->dvStatus[vtarget->target_id] & MPT_SCSICFG_DV_NOT_DONE)
+				pSpi->dvStatus[vtarget->target_id] |= MPT_SCSICFG_NEED_DV;
+		}
+		vtarget->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
 
-			/* If have not done DV, set the DV flag.
+		data_56 = 0x0F;  /* Default to full capabilities if Inq data length is < 57 */
+		if (dlen > 56) {
+			if ( (!(vtarget->tflags & MPT_TARGET_FLAGS_VALID_56))) {
+			/* Update the target capabilities
 			 */
-			pSpi = &hd->ioc->spi_data;
-			if ((data[0] == TYPE_TAPE) || (data[0] == TYPE_PROCESSOR)) {
-				if (pSpi->dvStatus[target_id] & MPT_SCSICFG_DV_NOT_DONE)
-					pSpi->dvStatus[target_id] |= MPT_SCSICFG_NEED_DV;
-			}
-
-			vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
-
-
-			data_56 = 0x0F;  /* Default to full capabilities if Inq data length is < 57 */
-			if (dlen > 56) {
-				if ( (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_56))) {
-				/* Update the target capabilities
-				 */
-					data_56 = data[56];
-					vdev->tflags |= MPT_TARGET_FLAGS_VALID_56;
-				}
+				data_56 = data[56];
+				vtarget->tflags |= MPT_TARGET_FLAGS_VALID_56;
 			}
-			mptscsih_setTargetNegoParms(hd, vdev, data_56);
-		} else {
-			/* Initial Inquiry may not request enough data bytes to
-			 * obtain byte 57.  DV will; if target doesn't return
-			 * at least 57 bytes, data[56] will be zero. */
-			if (dlen > 56) {
-				if ( (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_56))) {
-				/* Update the target capabilities
-				 */
-					data_56 = data[56];
-					vdev->tflags |= MPT_TARGET_FLAGS_VALID_56;
-					mptscsih_setTargetNegoParms(hd, vdev, data_56);
-				}
+		}
+		mptscsih_setTargetNegoParms(hd, vtarget, data_56);
+	} else {
+		/* Initial Inquiry may not request enough data bytes to
+		 * obtain byte 57.  DV will; if target doesn't return
+		 * at least 57 bytes, data[56] will be zero. */
+		if (dlen > 56) {
+			if ( (!(vtarget->tflags & MPT_TARGET_FLAGS_VALID_56))) {
+			/* Update the target capabilities
+			 */
+				data_56 = data[56];
+				vtarget->tflags |= MPT_TARGET_FLAGS_VALID_56;
+				mptscsih_setTargetNegoParms(hd, vtarget, data_56);
 			}
 		}
 	}
@@ -2755,12 +2773,12 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *
  *
  */
 static void
-mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56)
+mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target, char byte56)
 {
 	SpiCfgData *pspi_data = &hd->ioc->spi_data;
 	int  id = (int) target->target_id;
 	int  nvram;
-	VirtDevice	*vdev;
+	VirtTarget	*vtarget;
 	int ii;
 	u8 width = MPT_NARROW;
 	u8 factor = MPT_ASYNC;
@@ -2905,9 +2923,9 @@ mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56)
 
 			ddvtprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id));
 			for (ii = 0; ii < id; ii++) {
-				if ( (vdev = hd->Targets[ii]) ) {
-					vdev->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
-					mptscsih_writeSDP1(hd, 0, ii, vdev->negoFlags);
+				if ( (vtarget = hd->Targets[ii]) ) {
+					vtarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
+					mptscsih_writeSDP1(hd, 0, ii, vtarget->negoFlags);
 				}
 			}
 		}
@@ -2926,105 +2944,17 @@ mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56)
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/* If DV disabled (negoNvram set to USE_NVARM) or if not LUN 0, return.
- * Else set the NEED_DV flag after Read Capacity Issued (disks)
- * or Mode Sense (cdroms).
- *
- * Tapes, initTarget will set this flag on completion of Inquiry command.
- * Called only if DV_NOT_DONE flag is set
- */
-static void
-mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq)
-{
-	MPT_ADAPTER	*ioc = hd->ioc;
-	u8 cmd;
-	SpiCfgData	*pSpi;
-
-	ddvtprintk((MYIOC_s_NOTE_FMT
-		" set_dvflags: id=%d lun=%d negoNvram=%x cmd=%x\n",
-		hd->ioc->name, pReq->TargetID, pReq->LUN[1], hd->negoNvram, pReq->CDB[0]));
-
-	if ((pReq->LUN[1] != 0) || (hd->negoNvram != 0))
-		return;
-
-	cmd = pReq->CDB[0];
-
-	if ((cmd == READ_CAPACITY) || (cmd == MODE_SENSE)) {
-		pSpi = &ioc->spi_data;
-		if ((ioc->raid_data.isRaid & (1 << pReq->TargetID)) && ioc->raid_data.pIocPg3) {
-			/* Set NEED_DV for all hidden disks
-			 */
-			Ioc3PhysDisk_t *pPDisk =  ioc->raid_data.pIocPg3->PhysDisk;
-			int		numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
-
-			while (numPDisk) {
-				pSpi->dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV;
-				ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk->PhysDiskID));
-				pPDisk++;
-				numPDisk--;
-			}
-		}
-		pSpi->dvStatus[pReq->TargetID] |= MPT_SCSICFG_NEED_DV;
-		ddvtprintk(("NEED_DV set for visible disk id %d\n", pReq->TargetID));
-	}
-}
-
-/* mptscsih_raid_set_dv_flags()
- *
- * New or replaced disk. Set DV flag and schedule DV.
- */
-static void
-mptscsih_set_dvflags_raid(MPT_SCSI_HOST *hd, int id)
-{
-	MPT_ADAPTER	*ioc = hd->ioc;
-	SpiCfgData	*pSpi = &ioc->spi_data;
-	Ioc3PhysDisk_t	*pPDisk;
-	int		 numPDisk;
-
-	if (hd->negoNvram != 0)
-		return;
-
-	ddvtprintk(("DV requested for phys disk id %d\n", id));
-	if (ioc->raid_data.pIocPg3) {
-		pPDisk =  ioc->raid_data.pIocPg3->PhysDisk;
-		numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
-		while (numPDisk) {
-			if (id == pPDisk->PhysDiskNum) {
-				pSpi->dvStatus[pPDisk->PhysDiskID] =
-				    (MPT_SCSICFG_NEED_DV | MPT_SCSICFG_DV_NOT_DONE);
-				pSpi->forceDv = MPT_SCSICFG_NEED_DV;
-				ddvtprintk(("NEED_DV set for phys disk id %d\n",
-				    pPDisk->PhysDiskID));
-				break;
-			}
-			pPDisk++;
-			numPDisk--;
-		}
-
-		if (numPDisk == 0) {
-			/* The physical disk that needs DV was not found
-			 * in the stored IOC Page 3. The driver must reload
-			 * this page. DV routine will set the NEED_DV flag for
-			 * all phys disks that have DV_NOT_DONE set.
-			 */
-			pSpi->forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
-			ddvtprintk(("phys disk %d not found. Setting reload IOC Pg3 Flag\n",id));
-		}
-	}
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  * If no Target, bus reset on 1st I/O. Set the flag to
  * prevent any future negotiations to this device.
  */
 static void
-mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id)
+mptscsih_no_negotiate(MPT_SCSI_HOST *hd, struct scsi_cmnd *sc)
 {
+	VirtDevice	*vdev;
 
-	if ((hd->Targets) && (hd->Targets[target_id] == NULL))
-		hd->ioc->spi_data.dvStatus[target_id] |= MPT_SCSICFG_BLK_NEGO;
-
+	if ((vdev = sc->device->hostdata) != NULL)
+		hd->ioc->spi_data.dvStatus[vdev->target_id] |= MPT_SCSICFG_BLK_NEGO;
 	return;
 }
 
@@ -3100,7 +3030,7 @@ mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags)
 	MPT_ADAPTER		*ioc = hd->ioc;
 	Config_t		*pReq;
 	SCSIDevicePage1_t	*pData;
-	VirtDevice		*pTarget=NULL;
+	VirtTarget		*vtarget=NULL;
 	MPT_FRAME_HDR		*mf;
 	dma_addr_t		 dataDma;
 	u16			 req_idx;
@@ -3180,11 +3110,11 @@ mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags)
 		/* If id is not a raid volume, get the updated
 		 * transmission settings from the target structure.
 		 */
-		if (hd->Targets && (pTarget = hd->Targets[id]) && !pTarget->raidVolume) {
-			width = pTarget->maxWidth;
-			factor = pTarget->minSyncFactor;
-			offset = pTarget->maxOffset;
-			negoFlags = pTarget->negoFlags;
+		if (hd->Targets && (vtarget = hd->Targets[id]) && !vtarget->raidVolume) {
+			width = vtarget->maxWidth;
+			factor = vtarget->minSyncFactor;
+			offset = vtarget->maxOffset;
+			negoFlags = vtarget->negoFlags;
 		}
 
 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
@@ -3904,149 +3834,139 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
- *	mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks.
- *	@hd: Pointer to MPT_SCSI_HOST structure
- *	@portnum: IOC port number
+ *	mptscsih_negotiate_to_asyn_narrow - Restore devices to default state
+ *	@hd: Pointer to a SCSI HOST structure
+ *	@vtarget: per device private data
  *
  *	Uses the ISR, but with special processing.
  *	MUST be single-threaded.
  *
- *	Return: 0 on completion
  */
-static int
-mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum)
+static void
+mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtTarget *vtarget)
 {
 	MPT_ADAPTER		*ioc= hd->ioc;
-	VirtDevice		*pTarget;
-	SCSIDevicePage1_t	*pcfg1Data = NULL;
-	INTERNAL_CMD		 iocmd;
+	SCSIDevicePage1_t	*pcfg1Data;
 	CONFIGPARMS		 cfg;
-	dma_addr_t		 cfg1_dma_addr = -1;
-	ConfigPageHeader_t	 header1;
-	int			 bus = 0;
-	int			 id = 0;
-	int			 lun;
-	int			 indexed_lun, lun_index;
-	int			 hostId = ioc->pfacts[portnum].PortSCSIID;
-	int			 max_id;
-	int			 requested, configuration, data;
-	int			 doConfig = 0;
+	dma_addr_t		 cfg1_dma_addr;
+	ConfigPageHeader_t	 header;
+	int			 id;
+	int			 requested, configuration, data,i;
 	u8			 flags, factor;
 
-	max_id = ioc->sh->max_id - 1;
-
-	/* Following parameters will not change
-	 * in this routine.
-	 */
-	iocmd.cmd = SYNCHRONIZE_CACHE;
-	iocmd.flags = 0;
-	iocmd.physDiskNum = -1;
-	iocmd.data = NULL;
-	iocmd.data_dma = -1;
-	iocmd.size = 0;
-	iocmd.rsvd = iocmd.rsvd2 = 0;
-
-	/* No SCSI hosts
-	 */
-	if (hd->Targets == NULL)
-		return 0;
-
-	/* Skip the host
-	 */
-	if (id == hostId)
-		id++;
-
-	/* Write SDP1 for all SCSI devices
-	 * Alloc memory and set up config buffer
-	 */
-	if (ioc->bus_type == SCSI) {
-		if (ioc->spi_data.sdp1length > 0) {
-			pcfg1Data = (SCSIDevicePage1_t *)pci_alloc_consistent(ioc->pcidev,
-					 ioc->spi_data.sdp1length * 4, &cfg1_dma_addr);
-
-			if (pcfg1Data != NULL) {
-				doConfig = 1;
-				header1.PageVersion = ioc->spi_data.sdp1version;
-				header1.PageLength = ioc->spi_data.sdp1length;
-				header1.PageNumber = 1;
-				header1.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
-				cfg.cfghdr.hdr = &header1;
-				cfg.physAddr = cfg1_dma_addr;
-				cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
-				cfg.dir = 1;
-				cfg.timeout = 0;
-			}
-		}
-	}
+	if (ioc->bus_type != SPI)
+		return;
 
-	/* loop through all devices on this port
-	 */
-	while (bus < MPT_MAX_BUS) {
-		iocmd.bus = bus;
-		iocmd.id = id;
-		pTarget = hd->Targets[(int)id];
+	if (!ioc->spi_data.sdp1length)
+		return;
 
-		if (doConfig) {
+	pcfg1Data = (SCSIDevicePage1_t *)pci_alloc_consistent(ioc->pcidev,
+		 ioc->spi_data.sdp1length * 4, &cfg1_dma_addr);
 
-			/* Set the negotiation flags */
-			if (pTarget && (pTarget = hd->Targets[id]) && !pTarget->raidVolume) {
-				flags = pTarget->negoFlags;
-			} else {
-				flags = hd->ioc->spi_data.noQas;
-				if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
-					data = hd->ioc->spi_data.nvram[id];
+	if (pcfg1Data == NULL)
+		return;
 
-					if (data & MPT_NVRAM_WIDE_DISABLE)
-						flags |= MPT_TARGET_NO_NEGO_WIDE;
+	header.PageVersion = ioc->spi_data.sdp1version;
+	header.PageLength = ioc->spi_data.sdp1length;
+	header.PageNumber = 1;
+	header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
+	cfg.cfghdr.hdr = &header;
+	cfg.physAddr = cfg1_dma_addr;
+	cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
+	cfg.dir = 1;
+	cfg.timeout = 0;
 
-					factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
-					if ((factor == 0) || (factor == MPT_ASYNC))
-						flags |= MPT_TARGET_NO_NEGO_SYNC;
-				}
+	if (vtarget->raidVolume && ioc->raid_data.pIocPg3) {
+		for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
+			id = ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID;
+			flags = hd->ioc->spi_data.noQas;
+			if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
+				data = hd->ioc->spi_data.nvram[id];
+				if (data & MPT_NVRAM_WIDE_DISABLE)
+					flags |= MPT_TARGET_NO_NEGO_WIDE;
+				factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
+				if ((factor == 0) || (factor == MPT_ASYNC))
+					flags |= MPT_TARGET_NO_NEGO_SYNC;
 			}
-
-			/* Force to async, narrow */
 			mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested,
-					&configuration, flags);
+				&configuration, flags);
 			dnegoprintk(("syncronize cache: id=%d width=0 factor=MPT_ASYNC "
 				"offset=0 negoFlags=%x request=%x config=%x\n",
 				id, flags, requested, configuration));
 			pcfg1Data->RequestedParameters = cpu_to_le32(requested);
 			pcfg1Data->Reserved = 0;
 			pcfg1Data->Configuration = cpu_to_le32(configuration);
-			cfg.pageAddr = (bus<<8) | id;
+			cfg.pageAddr = (vtarget->bus_id<<8) | id;
 			mpt_config(hd->ioc, &cfg);
 		}
+	} else {
+		flags = vtarget->negoFlags;
+		mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested,
+				&configuration, flags);
+		dnegoprintk(("syncronize cache: id=%d width=0 factor=MPT_ASYNC "
+			"offset=0 negoFlags=%x request=%x config=%x\n",
+			vtarget->target_id, flags, requested, configuration));
+		pcfg1Data->RequestedParameters = cpu_to_le32(requested);
+		pcfg1Data->Reserved = 0;
+		pcfg1Data->Configuration = cpu_to_le32(configuration);
+		cfg.pageAddr = (vtarget->bus_id<<8) | vtarget->target_id;
+		mpt_config(hd->ioc, &cfg);
+	}
 
-		/* If target Ptr NULL or if this target is NOT a disk, skip.
-		 */
-		if ((pTarget) && (pTarget->inq_data[0] == TYPE_DISK)){
-			for (lun=0; lun <= MPT_LAST_LUN; lun++) {
-				/* If LUN present, issue the command
-				 */
-				lun_index = (lun >> 5);  /* 32 luns per lun_index */
-				indexed_lun = (lun % 32);
-				if (pTarget->luns[lun_index] & (1<<indexed_lun)) {
-					iocmd.lun = lun;
-					(void) mptscsih_do_cmd(hd, &iocmd);
-				}
-			}
-		}
+	if (pcfg1Data)
+		pci_free_consistent(ioc->pcidev, header.PageLength * 4, pcfg1Data, cfg1_dma_addr);
+}
 
-		/* get next relevant device */
-		id++;
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks.
+ *	@hd: Pointer to a SCSI HOST structure
+ *	@vtarget: per device private data
+ *	@lun: lun
+ *
+ *	Uses the ISR, but with special processing.
+ *	MUST be single-threaded.
+ *
+ */
+static void
+mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
+{
+	INTERNAL_CMD		 iocmd;
 
-		if (id == hostId)
-			id++;
+	/* Following parameters will not change
+	 * in this routine.
+	 */
+	iocmd.cmd = SYNCHRONIZE_CACHE;
+	iocmd.flags = 0;
+	iocmd.physDiskNum = -1;
+	iocmd.data = NULL;
+	iocmd.data_dma = -1;
+	iocmd.size = 0;
+	iocmd.rsvd = iocmd.rsvd2 = 0;
+	iocmd.bus = vdevice->bus_id;
+	iocmd.id = vdevice->target_id;
+	iocmd.lun = (u8)vdevice->lun;
 
-		if (id > max_id) {
-			id = 0;
-			bus++;
-		}
-	}
+	if ((vdevice->vtarget->type & TYPE_DISK) &&
+	    (vdevice->configured_lun))
+		mptscsih_do_cmd(hd, &iocmd);
+}
 
-	if (pcfg1Data) {
-		pci_free_consistent(ioc->pcidev, header1.PageLength * 4, pcfg1Data, cfg1_dma_addr);
+/* Search IOC page 3 to determine if this is hidden physical disk
+ */
+/* Search IOC page 3 to determine if this is hidden physical disk
+ */
+static int
+mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id)
+{
+	int i;
+
+	if (!ioc->raid_data.isRaid || !ioc->raid_data.pIocPg3)
+		return 0;
+
+	for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
+		if (id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID)
+			return 1;
 	}
 
 	return 0;
@@ -4101,8 +4021,8 @@ mptscsih_domainValidation(void *arg)
 
 			msleep(250);
 
-			/* DV only to SCSI adapters */
-			if (ioc->bus_type != SCSI)
+			/* DV only to SPI adapters */
+			if (ioc->bus_type != SPI)
 				continue;
 
 			/* Make sure everything looks ok */
@@ -4205,32 +4125,12 @@ mptscsih_domainValidation(void *arg)
 	return;
 }
 
-/* Search IOC page 3 to determine if this is hidden physical disk
- */
-/* Search IOC page 3 to determine if this is hidden physical disk
- */
-static int
-mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id)
-{
-	int i;
-
-	if (!ioc->raid_data.isRaid || !ioc->raid_data.pIocPg3)
-		return 0;
-
-	for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
-		if (id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID)
-			return 1;
-	}
-
-	return 0;
-}
-
 /* Write SDP1 if no QAS has been enabled
  */
 static void
 mptscsih_qas_check(MPT_SCSI_HOST *hd, int id)
 {
-	VirtDevice *pTarget;
+	VirtTarget *vtarget;
 	int ii;
 
 	if (hd->Targets == NULL)
@@ -4243,11 +4143,11 @@ mptscsih_qas_check(MPT_SCSI_HOST *hd, int id)
 		if ((hd->ioc->spi_data.dvStatus[ii] & MPT_SCSICFG_DV_NOT_DONE) != 0)
 			continue;
 
-		pTarget = hd->Targets[ii];
+		vtarget = hd->Targets[ii];
 
-		if ((pTarget != NULL) && (!pTarget->raidVolume)) {
-			if ((pTarget->negoFlags & hd->ioc->spi_data.noQas) == 0) {
-				pTarget->negoFlags |= hd->ioc->spi_data.noQas;
+		if ((vtarget != NULL) && (!vtarget->raidVolume)) {
+			if ((vtarget->negoFlags & hd->ioc->spi_data.noQas) == 0) {
+				vtarget->negoFlags |= hd->ioc->spi_data.noQas;
 				dnegoprintk(("writeSDP1: id=%d flags=0\n", id));
 				mptscsih_writeSDP1(hd, 0, ii, 0);
 			}
@@ -4287,7 +4187,7 @@ static int
 mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
 {
 	MPT_ADAPTER		*ioc = hd->ioc;
-	VirtDevice		*pTarget;
+	VirtTarget		*vtarget;
 	SCSIDevicePage1_t	*pcfg1Data;
 	SCSIDevicePage0_t	*pcfg0Data;
 	u8			*pbuf1;
@@ -4358,12 +4258,12 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
 	iocmd.physDiskNum = -1;
 	iocmd.rsvd = iocmd.rsvd2 = 0;
 
-	pTarget = hd->Targets[id];
+	vtarget = hd->Targets[id];
 
 	/* Use tagged commands if possible.
 	 */
-	if (pTarget) {
-		if (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)
+	if (vtarget) {
+		if (vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)
 			iocmd.flags |= MPT_ICFLAG_TAGGED_CMD;
 		else {
 			if (hd->ioc->facts.FWVersion.Word < 0x01000600)
@@ -4579,7 +4479,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
 		/* Reset the size for disks
 		 */
 		inq0 = (*pbuf1) & 0x1F;
-		if ((inq0 == 0) && pTarget && !pTarget->raidVolume) {
+		if ((inq0 == 0) && vtarget && !vtarget->raidVolume) {
 			sz = 0x40;
 			iocmd.size = sz;
 		}
@@ -4589,8 +4489,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
 		 */
 		if (inq0 == TYPE_PROCESSOR) {
 			mptscsih_initTarget(hd,
-				bus,
-				id,
+				vtarget,
 				lun,
 				pbuf1,
 				sz);
@@ -4604,22 +4503,22 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
 			goto target_done;
 
 		if (sz == 0x40) {
-			if ((pTarget->maxWidth == 1) && (pTarget->maxOffset) && (nfactor < 0x0A)
-				&& (pTarget->minSyncFactor > 0x09)) {
+			if ((vtarget->maxWidth == 1) && (vtarget->maxOffset) && (nfactor < 0x0A)
+				&& (vtarget->minSyncFactor > 0x09)) {
 				if ((pbuf1[56] & 0x04) == 0)
 					;
 				else if ((pbuf1[56] & 0x01) == 1) {
-					pTarget->minSyncFactor =
+					vtarget->minSyncFactor =
 					    nfactor > MPT_ULTRA320 ? nfactor : MPT_ULTRA320;
 				} else {
-					pTarget->minSyncFactor =
+					vtarget->minSyncFactor =
 					    nfactor > MPT_ULTRA160 ? nfactor : MPT_ULTRA160;
 				}
 
-				dv.max.factor = pTarget->minSyncFactor;
+				dv.max.factor = vtarget->minSyncFactor;
 
 				if ((pbuf1[56] & 0x02) == 0) {
-					pTarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
+					vtarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
 					hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
 					ddvprintk((MYIOC_s_NOTE_FMT
 					    "DV: Start Basic noQas on id=%d due to pbuf1[56]=%x\n",
@@ -4702,8 +4601,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
 						    "DV:Inquiry compared id=%d, calling initTarget\n", ioc->name, id));
 						hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_NOT_DONE;
 						mptscsih_initTarget(hd,
-							bus,
-							id,
+							vtarget,
 							lun,
 							pbuf1,
 							sz);
@@ -5204,7 +5102,7 @@ target_done:
 static void
 mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
 {
-	VirtDevice		*pTarget;
+	VirtTarget		*vtarget;
 	SCSIDevicePage0_t	*pPage0;
 	SCSIDevicePage1_t	*pPage1;
 	int			val = 0, data, configuration;
@@ -5224,11 +5122,11 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
 		 * already throttled back.
 		 */
 		negoFlags = hd->ioc->spi_data.noQas;
-		if ((hd->Targets)&&((pTarget = hd->Targets[(int)id]) != NULL) && !pTarget->raidVolume) {
-			width = pTarget->maxWidth;
-			offset = pTarget->maxOffset;
-			factor = pTarget->minSyncFactor;
-			negoFlags |= pTarget->negoFlags;
+		if ((hd->Targets)&&((vtarget = hd->Targets[(int)id]) != NULL) && !vtarget->raidVolume) {
+			width = vtarget->maxWidth;
+			offset = vtarget->maxOffset;
+			factor = vtarget->minSyncFactor;
+			negoFlags |= vtarget->negoFlags;
 		} else {
 			if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
 				data = hd->ioc->spi_data.nvram[id];
@@ -5430,11 +5328,11 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
 		 * or overwrite nvram (phys disks only).
 		 */
 
-		if ((hd->Targets)&&((pTarget = hd->Targets[(int)id]) != NULL) && !pTarget->raidVolume ) {
-			pTarget->maxWidth = dv->now.width;
-			pTarget->maxOffset = dv->now.offset;
-			pTarget->minSyncFactor = dv->now.factor;
-			pTarget->negoFlags = dv->now.flags;
+		if ((hd->Targets)&&((vtarget = hd->Targets[(int)id]) != NULL) && !vtarget->raidVolume ) {
+			vtarget->maxWidth = dv->now.width;
+			vtarget->maxOffset = dv->now.offset;
+			vtarget->minSyncFactor = dv->now.factor;
+			vtarget->negoFlags = dv->now.flags;
 		} else {
 			/* Preserv all flags, use
 			 * read-modify-write algorithm
@@ -5588,6 +5486,94 @@ mptscsih_fillbuf(char *buffer, int size, int index, int width)
 		break;
 	}
 }
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/* If DV disabled (negoNvram set to USE_NVARM) or if not LUN 0, return.
+ * Else set the NEED_DV flag after Read Capacity Issued (disks)
+ * or Mode Sense (cdroms).
+ *
+ * Tapes, initTarget will set this flag on completion of Inquiry command.
+ * Called only if DV_NOT_DONE flag is set
+ */
+static void
+mptscsih_set_dvflags(MPT_SCSI_HOST *hd, struct scsi_cmnd *sc)
+{
+	MPT_ADAPTER	*ioc = hd->ioc;
+	u8 cmd;
+	SpiCfgData	*pSpi;
+
+	ddvtprintk((MYIOC_s_NOTE_FMT
+		" set_dvflags: id=%d lun=%d negoNvram=%x cmd=%x\n",
+		hd->ioc->name, sc->device->id, sc->device->lun , hd->negoNvram, sc->cmnd[0]));
+
+	if ((sc->device->lun != 0) || (hd->negoNvram != 0))
+		return;
+
+	cmd = sc->cmnd[0];
+
+	if ((cmd == READ_CAPACITY) || (cmd == MODE_SENSE)) {
+		pSpi = &ioc->spi_data;
+		if ((ioc->raid_data.isRaid & (1 << sc->device->id)) && ioc->raid_data.pIocPg3) {
+			/* Set NEED_DV for all hidden disks
+			 */
+			Ioc3PhysDisk_t *pPDisk =  ioc->raid_data.pIocPg3->PhysDisk;
+			int		numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
+
+			while (numPDisk) {
+				pSpi->dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV;
+				ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk->PhysDiskID));
+				pPDisk++;
+				numPDisk--;
+			}
+		}
+		pSpi->dvStatus[sc->device->id] |= MPT_SCSICFG_NEED_DV;
+		ddvtprintk(("NEED_DV set for visible disk id %d\n", sc->device->id));
+	}
+}
+
+/* mptscsih_raid_set_dv_flags()
+ *
+ * New or replaced disk. Set DV flag and schedule DV.
+ */
+static void
+mptscsih_set_dvflags_raid(MPT_SCSI_HOST *hd, int id)
+{
+	MPT_ADAPTER	*ioc = hd->ioc;
+	SpiCfgData	*pSpi = &ioc->spi_data;
+	Ioc3PhysDisk_t	*pPDisk;
+	int		 numPDisk;
+
+	if (hd->negoNvram != 0)
+		return;
+
+	ddvtprintk(("DV requested for phys disk id %d\n", id));
+	if (ioc->raid_data.pIocPg3) {
+		pPDisk =  ioc->raid_data.pIocPg3->PhysDisk;
+		numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
+		while (numPDisk) {
+			if (id == pPDisk->PhysDiskNum) {
+				pSpi->dvStatus[pPDisk->PhysDiskID] =
+				    (MPT_SCSICFG_NEED_DV | MPT_SCSICFG_DV_NOT_DONE);
+				pSpi->forceDv = MPT_SCSICFG_NEED_DV;
+				ddvtprintk(("NEED_DV set for phys disk id %d\n",
+				    pPDisk->PhysDiskID));
+				break;
+			}
+			pPDisk++;
+			numPDisk--;
+		}
+
+		if (numPDisk == 0) {
+			/* The physical disk that needs DV was not found
+			 * in the stored IOC Page 3. The driver must reload
+			 * this page. DV routine will set the NEED_DV flag for
+			 * all phys disks that have DV_NOT_DONE set.
+			 */
+			pSpi->forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
+			ddvtprintk(("phys disk %d not found. Setting reload IOC Pg3 Flag\n",id));
+		}
+	}
+}
 #endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */
 
 EXPORT_SYMBOL(mptscsih_remove);
@@ -5599,7 +5585,9 @@ EXPORT_SYMBOL(mptscsih_resume);
 EXPORT_SYMBOL(mptscsih_proc_info);
 EXPORT_SYMBOL(mptscsih_info);
 EXPORT_SYMBOL(mptscsih_qcmd);
+EXPORT_SYMBOL(mptscsih_target_alloc);
 EXPORT_SYMBOL(mptscsih_slave_alloc);
+EXPORT_SYMBOL(mptscsih_target_destroy);
 EXPORT_SYMBOL(mptscsih_slave_destroy);
 EXPORT_SYMBOL(mptscsih_slave_configure);
 EXPORT_SYMBOL(mptscsih_abort);
diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h
index 971fda4b8b57..d3cba12f4bd9 100644
--- a/drivers/message/fusion/mptscsih.h
+++ b/drivers/message/fusion/mptscsih.h
@@ -91,7 +91,9 @@ extern int mptscsih_resume(struct pci_dev *pdev);
 extern int mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int func);
 extern const char * mptscsih_info(struct Scsi_Host *SChost);
 extern int mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *));
+extern int mptscsih_target_alloc(struct scsi_target *starget);
 extern int mptscsih_slave_alloc(struct scsi_device *device);
+extern void mptscsih_target_destroy(struct scsi_target *starget);
 extern void mptscsih_slave_destroy(struct scsi_device *device);
 extern int mptscsih_slave_configure(struct scsi_device *device);
 extern int mptscsih_abort(struct scsi_cmnd * SCpnt);
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c
index 5c0e307d1d5d..ce332a6085e5 100644
--- a/drivers/message/fusion/mptspi.c
+++ b/drivers/message/fusion/mptspi.c
@@ -103,13 +103,16 @@ static int	mptspiTaskCtx = -1;
 static int	mptspiInternalCtx = -1; /* Used only for internal commands */
 
 static struct scsi_host_template mptspi_driver_template = {
+	.module				= THIS_MODULE,
 	.proc_name			= "mptspi",
 	.proc_info			= mptscsih_proc_info,
 	.name				= "MPT SPI Host",
 	.info				= mptscsih_info,
 	.queuecommand			= mptscsih_qcmd,
+	.target_alloc			= mptscsih_target_alloc,
 	.slave_alloc			= mptscsih_slave_alloc,
 	.slave_configure		= mptscsih_slave_configure,
+	.target_destroy			= mptscsih_target_destroy,
 	.slave_destroy			= mptscsih_slave_destroy,
 	.change_queue_depth 		= mptscsih_change_queue_depth,
 	.eh_abort_handler		= mptscsih_abort,
@@ -177,13 +180,15 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 		printk(MYIOC_s_WARN_FMT
 		  "Skipping because it's not operational!\n",
 		  ioc->name);
-		return -ENODEV;
+		error = -ENODEV;
+		goto out_mptspi_probe;
 	}
 
 	if (!ioc->active) {
 		printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
 		  ioc->name);
-		return -ENODEV;
+		error = -ENODEV;
+		goto out_mptspi_probe;
 	}
 
 	/*  Sanity check - ensure at least 1 port is INITIATOR capable
@@ -208,7 +213,8 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 		printk(MYIOC_s_WARN_FMT
 			"Unable to register controller with SCSI subsystem\n",
 			ioc->name);
-                return -1;
+		error = -1;
+		goto out_mptspi_probe;
         }
 
 	spin_lock_irqsave(&ioc->FreeQlock, flags);
@@ -286,7 +292,7 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	mem = kmalloc(sz, GFP_ATOMIC);
 	if (mem == NULL) {
 		error = -ENOMEM;
-		goto mptspi_probe_failed;
+		goto out_mptspi_probe;
 	}
 
 	memset(mem, 0, sz);
@@ -304,14 +310,14 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	mem = kmalloc(sz, GFP_ATOMIC);
 	if (mem == NULL) {
 		error = -ENOMEM;
-		goto mptspi_probe_failed;
+		goto out_mptspi_probe;
 	}
 
 	memset(mem, 0, sz);
-	hd->Targets = (VirtDevice **) mem;
+	hd->Targets = (VirtTarget **) mem;
 
 	dprintk((KERN_INFO
-	  "  Targets @ %p, sz=%d\n", hd->Targets, sz));
+	  "  vdev @ %p, sz=%d\n", hd->Targets, sz));
 
 	/* Clear the TM flags
 	 */
@@ -385,13 +391,13 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	if(error) {
 		dprintk((KERN_ERR MYNAM
 		  "scsi_add_host failed\n"));
-		goto mptspi_probe_failed;
+		goto out_mptspi_probe;
 	}
 
 	scsi_scan_host(sh);
 	return 0;
 
-mptspi_probe_failed:
+out_mptspi_probe:
 
 	mptscsih_remove(pdev);
 	return error;
diff --git a/drivers/message/i2o/Kconfig b/drivers/message/i2o/Kconfig
index 43a942a29c2e..fef677103880 100644
--- a/drivers/message/i2o/Kconfig
+++ b/drivers/message/i2o/Kconfig
@@ -24,6 +24,18 @@ config I2O
 
 	  If unsure, say N.
 
+config I2O_LCT_NOTIFY_ON_CHANGES
+	bool "Enable LCT notification"
+	depends on I2O
+	default y
+	---help---
+	  Only say N here if you have a I2O controller from SUN. The SUN
+	  firmware doesn't support LCT notification on changes. If this option
+	  is enabled on such a controller the driver will hang up in a endless
+	  loop. On all other controllers say Y.
+
+	  If unsure, say Y.
+
 config I2O_EXT_ADAPTEC
 	bool "Enable Adaptec extensions"
 	depends on I2O
diff --git a/drivers/message/i2o/bus-osm.c b/drivers/message/i2o/bus-osm.c
index 151b228e1cb3..ac06f10c54ec 100644
--- a/drivers/message/i2o/bus-osm.c
+++ b/drivers/message/i2o/bus-osm.c
@@ -17,7 +17,7 @@
 #include <linux/i2o.h>
 
 #define OSM_NAME	"bus-osm"
-#define OSM_VERSION	"$Rev$"
+#define OSM_VERSION	"1.317"
 #define OSM_DESCRIPTION	"I2O Bus Adapter OSM"
 
 static struct i2o_driver i2o_bus_driver;
@@ -39,18 +39,18 @@ static struct i2o_class_id i2o_bus_class_id[] = {
  */
 static int i2o_bus_scan(struct i2o_device *dev)
 {
-	struct i2o_message __iomem *msg;
-	u32 m;
+	struct i2o_message *msg;
 
-	m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET);
-	if (m == I2O_QUEUE_EMPTY)
+	msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET);
+	if (IS_ERR(msg))
 		return -ETIMEDOUT;
 
-	writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
-	writel(I2O_CMD_BUS_SCAN << 24 | HOST_TID << 12 | dev->lct_data.tid,
-	       &msg->u.head[1]);
+	msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0);
+	msg->u.head[1] =
+	    cpu_to_le32(I2O_CMD_BUS_SCAN << 24 | HOST_TID << 12 | dev->lct_data.
+			tid);
 
-	return i2o_msg_post_wait(dev->iop, m, 60);
+	return i2o_msg_post_wait(dev->iop, msg, 60);
 };
 
 /**
@@ -59,8 +59,9 @@ static int i2o_bus_scan(struct i2o_device *dev)
  *
  *	Returns count.
  */
-static ssize_t i2o_bus_store_scan(struct device *d, struct device_attribute *attr, const char *buf,
-				  size_t count)
+static ssize_t i2o_bus_store_scan(struct device *d,
+				  struct device_attribute *attr,
+				  const char *buf, size_t count)
 {
 	struct i2o_device *i2o_dev = to_i2o_device(d);
 	int rc;
diff --git a/drivers/message/i2o/config-osm.c b/drivers/message/i2o/config-osm.c
index 10432f665201..3bba7aa82e58 100644
--- a/drivers/message/i2o/config-osm.c
+++ b/drivers/message/i2o/config-osm.c
@@ -22,7 +22,7 @@
 #include <asm/uaccess.h>
 
 #define OSM_NAME	"config-osm"
-#define OSM_VERSION	"1.248"
+#define OSM_VERSION	"1.323"
 #define OSM_DESCRIPTION	"I2O Configuration OSM"
 
 /* access mode user rw */
diff --git a/drivers/message/i2o/core.h b/drivers/message/i2o/core.h
index 9eefedb16211..90628562851e 100644
--- a/drivers/message/i2o/core.h
+++ b/drivers/message/i2o/core.h
@@ -14,8 +14,6 @@
  */
 
 /* Exec-OSM */
-extern struct bus_type i2o_bus_type;
-
 extern struct i2o_driver i2o_exec_driver;
 extern int i2o_exec_lct_get(struct i2o_controller *);
 
@@ -23,6 +21,8 @@ extern int __init i2o_exec_init(void);
 extern void __exit i2o_exec_exit(void);
 
 /* driver */
+extern struct bus_type i2o_bus_type;
+
 extern int i2o_driver_dispatch(struct i2o_controller *, u32);
 
 extern int __init i2o_driver_init(void);
@@ -33,19 +33,27 @@ extern int __init i2o_pci_init(void);
 extern void __exit i2o_pci_exit(void);
 
 /* device */
+extern struct device_attribute i2o_device_attrs[];
+
 extern void i2o_device_remove(struct i2o_device *);
 extern int i2o_device_parse_lct(struct i2o_controller *);
 
 /* IOP */
 extern struct i2o_controller *i2o_iop_alloc(void);
-extern void i2o_iop_free(struct i2o_controller *);
+
+/**
+ *	i2o_iop_free - Free the i2o_controller struct
+ *	@c: I2O controller to free
+ */
+static inline void i2o_iop_free(struct i2o_controller *c)
+{
+	i2o_pool_free(&c->in_msg);
+	kfree(c);
+}
 
 extern int i2o_iop_add(struct i2o_controller *);
 extern void i2o_iop_remove(struct i2o_controller *);
 
-/* config */
-extern int i2o_parm_issue(struct i2o_device *, int, void *, int, void *, int);
-
 /* control registers relative to c->base */
 #define I2O_IRQ_STATUS	0x30
 #define I2O_IRQ_MASK	0x34
diff --git a/drivers/message/i2o/device.c b/drivers/message/i2o/device.c
index 8eb50cdb8ae1..ee183053fa23 100644
--- a/drivers/message/i2o/device.c
+++ b/drivers/message/i2o/device.c
@@ -35,18 +35,18 @@
 static inline int i2o_device_issue_claim(struct i2o_device *dev, u32 cmd,
 					 u32 type)
 {
-	struct i2o_message __iomem *msg;
-	u32 m;
+	struct i2o_message *msg;
 
-	m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET);
-	if (m == I2O_QUEUE_EMPTY)
-		return -ETIMEDOUT;
+	msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET);
+	if (IS_ERR(msg))
+		return PTR_ERR(msg);
 
-	writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
-	writel(cmd << 24 | HOST_TID << 12 | dev->lct_data.tid, &msg->u.head[1]);
-	writel(type, &msg->body[0]);
+	msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0);
+	msg->u.head[1] =
+	    cpu_to_le32(cmd << 24 | HOST_TID << 12 | dev->lct_data.tid);
+	msg->body[0] = cpu_to_le32(type);
 
-	return i2o_msg_post_wait(dev->iop, m, 60);
+	return i2o_msg_post_wait(dev->iop, msg, 60);
 }
 
 /**
@@ -123,7 +123,6 @@ int i2o_device_claim_release(struct i2o_device *dev)
 	return rc;
 }
 
-
 /**
  *	i2o_device_release - release the memory for a I2O device
  *	@dev: I2O device which should be released
@@ -140,10 +139,10 @@ static void i2o_device_release(struct device *dev)
 	kfree(i2o_dev);
 }
 
-
 /**
- *	i2o_device_class_show_class_id - Displays class id of I2O device
- *	@cd: class device of which the class id should be displayed
+ *	i2o_device_show_class_id - Displays class id of I2O device
+ *	@dev: device of which the class id should be displayed
+ *	@attr: pointer to device attribute
  *	@buf: buffer into which the class id should be printed
  *
  *	Returns the number of bytes which are printed into the buffer.
@@ -159,15 +158,15 @@ static ssize_t i2o_device_show_class_id(struct device *dev,
 }
 
 /**
- *	i2o_device_class_show_tid - Displays TID of I2O device
- *	@cd: class device of which the TID should be displayed
- *	@buf: buffer into which the class id should be printed
+ *	i2o_device_show_tid - Displays TID of I2O device
+ *	@dev: device of which the TID should be displayed
+ *	@attr: pointer to device attribute
+ *	@buf: buffer into which the TID should be printed
  *
  *	Returns the number of bytes which are printed into the buffer.
  */
 static ssize_t i2o_device_show_tid(struct device *dev,
-				   struct device_attribute *attr,
-				   char *buf)
+				   struct device_attribute *attr, char *buf)
 {
 	struct i2o_device *i2o_dev = to_i2o_device(dev);
 
@@ -175,6 +174,7 @@ static ssize_t i2o_device_show_tid(struct device *dev,
 	return strlen(buf) + 1;
 }
 
+/* I2O device attributes */
 struct device_attribute i2o_device_attrs[] = {
 	__ATTR(class_id, S_IRUGO, i2o_device_show_class_id, NULL),
 	__ATTR(tid, S_IRUGO, i2o_device_show_tid, NULL),
@@ -193,12 +193,10 @@ static struct i2o_device *i2o_device_alloc(void)
 {
 	struct i2o_device *dev;
 
-	dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 	if (!dev)
 		return ERR_PTR(-ENOMEM);
 
-	memset(dev, 0, sizeof(*dev));
-
 	INIT_LIST_HEAD(&dev->list);
 	init_MUTEX(&dev->lock);
 
@@ -209,66 +207,6 @@ static struct i2o_device *i2o_device_alloc(void)
 }
 
 /**
- *	i2o_setup_sysfs_links - Adds attributes to the I2O device
- *	@cd: I2O class device which is added to the I2O device class
- *
- *	This function get called when a I2O device is added to the class. It
- *	creates the attributes for each device and creates user/parent symlink
- *	if necessary.
- *
- *	Returns 0 on success or negative error code on failure.
- */
-static void i2o_setup_sysfs_links(struct i2o_device *i2o_dev)
-{
-	struct i2o_controller *c = i2o_dev->iop;
-	struct i2o_device *tmp;
-
-	/* create user entries for this device */
-	tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.user_tid);
-	if (tmp && tmp != i2o_dev)
-		sysfs_create_link(&i2o_dev->device.kobj,
-				  &tmp->device.kobj, "user");
-
-	/* create user entries refering to this device */
-	list_for_each_entry(tmp, &c->devices, list)
-		if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid &&
-		    tmp != i2o_dev)
-			sysfs_create_link(&tmp->device.kobj,
-					  &i2o_dev->device.kobj, "user");
-
-	/* create parent entries for this device */
-	tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.parent_tid);
-	if (tmp && tmp != i2o_dev)
-		sysfs_create_link(&i2o_dev->device.kobj,
-				  &tmp->device.kobj, "parent");
-
-	/* create parent entries refering to this device */
-	list_for_each_entry(tmp, &c->devices, list)
-		if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid &&
-		    tmp != i2o_dev)
-		sysfs_create_link(&tmp->device.kobj,
-				  &i2o_dev->device.kobj, "parent");
-}
-
-static void i2o_remove_sysfs_links(struct i2o_device *i2o_dev)
-{
-	struct i2o_controller *c = i2o_dev->iop;
-	struct i2o_device *tmp;
-
-	sysfs_remove_link(&i2o_dev->device.kobj, "parent");
-	sysfs_remove_link(&i2o_dev->device.kobj, "user");
-
-	list_for_each_entry(tmp, &c->devices, list) {
-		if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid)
-			sysfs_remove_link(&tmp->device.kobj, "parent");
-		if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid)
-			sysfs_remove_link(&tmp->device.kobj, "user");
-	}
-}
-
-
-
-/**
  *	i2o_device_add - allocate a new I2O device and add it to the IOP
  *	@iop: I2O controller where the device is on
  *	@entry: LCT entry of the I2O device
@@ -282,33 +220,57 @@ static void i2o_remove_sysfs_links(struct i2o_device *i2o_dev)
 static struct i2o_device *i2o_device_add(struct i2o_controller *c,
 					 i2o_lct_entry * entry)
 {
-	struct i2o_device *dev;
+	struct i2o_device *i2o_dev, *tmp;
 
-	dev = i2o_device_alloc();
-	if (IS_ERR(dev)) {
+	i2o_dev = i2o_device_alloc();
+	if (IS_ERR(i2o_dev)) {
 		printk(KERN_ERR "i2o: unable to allocate i2o device\n");
-		return dev;
+		return i2o_dev;
 	}
 
-	dev->lct_data = *entry;
-	dev->iop = c;
+	i2o_dev->lct_data = *entry;
 
-	snprintf(dev->device.bus_id, BUS_ID_SIZE, "%d:%03x", c->unit,
-		 dev->lct_data.tid);
+	snprintf(i2o_dev->device.bus_id, BUS_ID_SIZE, "%d:%03x", c->unit,
+		 i2o_dev->lct_data.tid);
 
-	dev->device.parent = &c->device;
+	i2o_dev->iop = c;
+	i2o_dev->device.parent = &c->device;
 
-	device_register(&dev->device);
+	device_register(&i2o_dev->device);
 
-	list_add_tail(&dev->list, &c->devices);
+	list_add_tail(&i2o_dev->list, &c->devices);
 
-	i2o_setup_sysfs_links(dev);
+	/* create user entries for this device */
+	tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.user_tid);
+	if (tmp && (tmp != i2o_dev))
+		sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj,
+				  "user");
 
-	i2o_driver_notify_device_add_all(dev);
+	/* create user entries refering to this device */
+	list_for_each_entry(tmp, &c->devices, list)
+	    if ((tmp->lct_data.user_tid == i2o_dev->lct_data.tid)
+		&& (tmp != i2o_dev))
+		sysfs_create_link(&tmp->device.kobj,
+				  &i2o_dev->device.kobj, "user");
 
-	pr_debug("i2o: device %s added\n", dev->device.bus_id);
+	/* create parent entries for this device */
+	tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.parent_tid);
+	if (tmp && (tmp != i2o_dev))
+		sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj,
+				  "parent");
 
-	return dev;
+	/* create parent entries refering to this device */
+	list_for_each_entry(tmp, &c->devices, list)
+	    if ((tmp->lct_data.parent_tid == i2o_dev->lct_data.tid)
+		&& (tmp != i2o_dev))
+		sysfs_create_link(&tmp->device.kobj,
+				  &i2o_dev->device.kobj, "parent");
+
+	i2o_driver_notify_device_add_all(i2o_dev);
+
+	pr_debug("i2o: device %s added\n", i2o_dev->device.bus_id);
+
+	return i2o_dev;
 }
 
 /**
@@ -321,9 +283,22 @@ static struct i2o_device *i2o_device_add(struct i2o_controller *c,
  */
 void i2o_device_remove(struct i2o_device *i2o_dev)
 {
+	struct i2o_device *tmp;
+	struct i2o_controller *c = i2o_dev->iop;
+
 	i2o_driver_notify_device_remove_all(i2o_dev);
-	i2o_remove_sysfs_links(i2o_dev);
+
+	sysfs_remove_link(&i2o_dev->device.kobj, "parent");
+	sysfs_remove_link(&i2o_dev->device.kobj, "user");
+
+	list_for_each_entry(tmp, &c->devices, list) {
+		if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid)
+			sysfs_remove_link(&tmp->device.kobj, "parent");
+		if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid)
+			sysfs_remove_link(&tmp->device.kobj, "user");
+	}
 	list_del(&i2o_dev->list);
+
 	device_unregister(&i2o_dev->device);
 }
 
@@ -341,56 +316,83 @@ int i2o_device_parse_lct(struct i2o_controller *c)
 {
 	struct i2o_device *dev, *tmp;
 	i2o_lct *lct;
-	int i;
-	int max;
+	u32 *dlct = c->dlct.virt;
+	int max = 0, i = 0;
+	u16 table_size;
+	u32 buf;
 
 	down(&c->lct_lock);
 
 	kfree(c->lct);
 
-	lct = c->dlct.virt;
+	buf = le32_to_cpu(*dlct++);
+	table_size = buf & 0xffff;
 
-	c->lct = kmalloc(lct->table_size * 4, GFP_KERNEL);
-	if (!c->lct) {
+	lct = c->lct = kmalloc(table_size * 4, GFP_KERNEL);
+	if (!lct) {
 		up(&c->lct_lock);
 		return -ENOMEM;
 	}
 
-	if (lct->table_size * 4 > c->dlct.len) {
-		memcpy(c->lct, c->dlct.virt, c->dlct.len);
-		up(&c->lct_lock);
-		return -EAGAIN;
-	}
+	lct->lct_ver = buf >> 28;
+	lct->boot_tid = buf >> 16 & 0xfff;
+	lct->table_size = table_size;
+	lct->change_ind = le32_to_cpu(*dlct++);
+	lct->iop_flags = le32_to_cpu(*dlct++);
 
-	memcpy(c->lct, c->dlct.virt, lct->table_size * 4);
-
-	lct = c->lct;
-
-	max = (lct->table_size - 3) / 9;
+	table_size -= 3;
 
 	pr_debug("%s: LCT has %d entries (LCT size: %d)\n", c->name, max,
 		 lct->table_size);
 
-	/* remove devices, which are not in the LCT anymore */
-	list_for_each_entry_safe(dev, tmp, &c->devices, list) {
+	while (table_size > 0) {
+		i2o_lct_entry *entry = &lct->lct_entry[max];
 		int found = 0;
 
-		for (i = 0; i < max; i++) {
-			if (lct->lct_entry[i].tid == dev->lct_data.tid) {
+		buf = le32_to_cpu(*dlct++);
+		entry->entry_size = buf & 0xffff;
+		entry->tid = buf >> 16 & 0xfff;
+
+		entry->change_ind = le32_to_cpu(*dlct++);
+		entry->device_flags = le32_to_cpu(*dlct++);
+
+		buf = le32_to_cpu(*dlct++);
+		entry->class_id = buf & 0xfff;
+		entry->version = buf >> 12 & 0xf;
+		entry->vendor_id = buf >> 16;
+
+		entry->sub_class = le32_to_cpu(*dlct++);
+
+		buf = le32_to_cpu(*dlct++);
+		entry->user_tid = buf & 0xfff;
+		entry->parent_tid = buf >> 12 & 0xfff;
+		entry->bios_info = buf >> 24;
+
+		memcpy(&entry->identity_tag, dlct, 8);
+		dlct += 2;
+
+		entry->event_capabilities = le32_to_cpu(*dlct++);
+
+		/* add new devices, which are new in the LCT */
+		list_for_each_entry_safe(dev, tmp, &c->devices, list) {
+			if (entry->tid == dev->lct_data.tid) {
 				found = 1;
 				break;
 			}
 		}
 
 		if (!found)
-			i2o_device_remove(dev);
+			i2o_device_add(c, entry);
+
+		table_size -= 9;
+		max++;
 	}
 
-	/* add new devices, which are new in the LCT */
-	for (i = 0; i < max; i++) {
+	/* remove devices, which are not in the LCT anymore */
+	list_for_each_entry_safe(dev, tmp, &c->devices, list) {
 		int found = 0;
 
-		list_for_each_entry_safe(dev, tmp, &c->devices, list) {
+		for (i = 0; i < max; i++) {
 			if (lct->lct_entry[i].tid == dev->lct_data.tid) {
 				found = 1;
 				break;
@@ -398,14 +400,14 @@ int i2o_device_parse_lct(struct i2o_controller *c)
 		}
 
 		if (!found)
-			i2o_device_add(c, &lct->lct_entry[i]);
+			i2o_device_remove(dev);
 	}
+
 	up(&c->lct_lock);
 
 	return 0;
 }
 
-
 /*
  *	Run time support routines
  */
@@ -419,13 +421,9 @@ int i2o_device_parse_lct(struct i2o_controller *c)
  *	ResultCount, ErrorInfoSize, BlockStatus and BlockSize.
  */
 int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist,
-			  int oplen, void *reslist, int reslen)
+		   int oplen, void *reslist, int reslen)
 {
-	struct i2o_message __iomem *msg;
-	u32 m;
-	u32 *res32 = (u32 *) reslist;
-	u32 *restmp = (u32 *) reslist;
-	int len = 0;
+	struct i2o_message *msg;
 	int i = 0;
 	int rc;
 	struct i2o_dma res;
@@ -437,26 +435,27 @@ int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist,
 	if (i2o_dma_alloc(dev, &res, reslen, GFP_KERNEL))
 		return -ENOMEM;
 
-	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
-	if (m == I2O_QUEUE_EMPTY) {
+	msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+	if (IS_ERR(msg)) {
 		i2o_dma_free(dev, &res);
-		return -ETIMEDOUT;
+		return PTR_ERR(msg);
 	}
 
 	i = 0;
-	writel(cmd << 24 | HOST_TID << 12 | i2o_dev->lct_data.tid,
-	       &msg->u.head[1]);
-	writel(0, &msg->body[i++]);
-	writel(0x4C000000 | oplen, &msg->body[i++]);	/* OperationList */
-	memcpy_toio(&msg->body[i], oplist, oplen);
+	msg->u.head[1] =
+	    cpu_to_le32(cmd << 24 | HOST_TID << 12 | i2o_dev->lct_data.tid);
+	msg->body[i++] = cpu_to_le32(0x00000000);
+	msg->body[i++] = cpu_to_le32(0x4C000000 | oplen);	/* OperationList */
+	memcpy(&msg->body[i], oplist, oplen);
 	i += (oplen / 4 + (oplen % 4 ? 1 : 0));
-	writel(0xD0000000 | res.len, &msg->body[i++]);	/* ResultList */
-	writel(res.phys, &msg->body[i++]);
+	msg->body[i++] = cpu_to_le32(0xD0000000 | res.len);	/* ResultList */
+	msg->body[i++] = cpu_to_le32(res.phys);
 
-	writel(I2O_MESSAGE_SIZE(i + sizeof(struct i2o_message) / 4) |
-	       SGL_OFFSET_5, &msg->u.head[0]);
+	msg->u.head[0] =
+	    cpu_to_le32(I2O_MESSAGE_SIZE(i + sizeof(struct i2o_message) / 4) |
+			SGL_OFFSET_5);
 
-	rc = i2o_msg_post_wait_mem(c, m, 10, &res);
+	rc = i2o_msg_post_wait_mem(c, msg, 10, &res);
 
 	/* This only looks like a memory leak - don't "fix" it. */
 	if (rc == -ETIMEDOUT)
@@ -465,36 +464,7 @@ int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist,
 	memcpy(reslist, res.virt, res.len);
 	i2o_dma_free(dev, &res);
 
-	/* Query failed */
-	if (rc)
-		return rc;
-	/*
-	 * Calculate number of bytes of Result LIST
-	 * We need to loop through each Result BLOCK and grab the length
-	 */
-	restmp = res32 + 1;
-	len = 1;
-	for (i = 0; i < (res32[0] & 0X0000FFFF); i++) {
-		if (restmp[0] & 0x00FF0000) {	/* BlockStatus != SUCCESS */
-			printk(KERN_WARNING
-			       "%s - Error:\n  ErrorInfoSize = 0x%02x, "
-			       "BlockStatus = 0x%02x, BlockSize = 0x%04x\n",
-			       (cmd ==
-				I2O_CMD_UTIL_PARAMS_SET) ? "PARAMS_SET" :
-			       "PARAMS_GET", res32[1] >> 24,
-			       (res32[1] >> 16) & 0xFF, res32[1] & 0xFFFF);
-
-			/*
-			 *      If this is the only request,than we return an error
-			 */
-			if ((res32[0] & 0x0000FFFF) == 1) {
-				return -((res32[1] >> 16) & 0xFF);	/* -BlockStatus */
-			}
-		}
-		len += restmp[0] & 0x0000FFFF;	/* Length of res BLOCK */
-		restmp += restmp[0] & 0x0000FFFF;	/* Skip to next BLOCK */
-	}
-	return (len << 2);	/* bytes used by result list */
+	return rc;
 }
 
 /*
@@ -503,28 +473,25 @@ int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist,
 int i2o_parm_field_get(struct i2o_device *i2o_dev, int group, int field,
 		       void *buf, int buflen)
 {
-	u16 opblk[] = { 1, 0, I2O_PARAMS_FIELD_GET, group, 1, field };
+	u32 opblk[] = { cpu_to_le32(0x00000001),
+		cpu_to_le32((u16) group << 16 | I2O_PARAMS_FIELD_GET),
+		cpu_to_le32((s16) field << 16 | 0x00000001)
+	};
 	u8 *resblk;		/* 8 bytes for header */
-	int size;
-
-	if (field == -1)	/* whole group */
-		opblk[4] = -1;
+	int rc;
 
 	resblk = kmalloc(buflen + 8, GFP_KERNEL | GFP_ATOMIC);
 	if (!resblk)
 		return -ENOMEM;
 
-	size = i2o_parm_issue(i2o_dev, I2O_CMD_UTIL_PARAMS_GET, opblk,
-			      sizeof(opblk), resblk, buflen + 8);
+	rc = i2o_parm_issue(i2o_dev, I2O_CMD_UTIL_PARAMS_GET, opblk,
+			    sizeof(opblk), resblk, buflen + 8);
 
 	memcpy(buf, resblk + 8, buflen);	/* cut off header */
 
 	kfree(resblk);
 
-	if (size > buflen)
-		return buflen;
-
-	return size;
+	return rc;
 }
 
 /*
@@ -534,12 +501,12 @@ int i2o_parm_field_get(struct i2o_device *i2o_dev, int group, int field,
  *		else return specific fields
  *			ibuf contains fieldindexes
  *
- * 	if oper == I2O_PARAMS_LIST_GET, get from specific rows
- * 		if fieldcount == -1 return all fields
+ *	if oper == I2O_PARAMS_LIST_GET, get from specific rows
+ *		if fieldcount == -1 return all fields
  *			ibuf contains rowcount, keyvalues
- * 		else return specific fields
+ *		else return specific fields
  *			fieldcount is # of fieldindexes
- *  			ibuf contains fieldindexes, rowcount, keyvalues
+ *			ibuf contains fieldindexes, rowcount, keyvalues
  *
  *	You could also use directly function i2o_issue_params().
  */
diff --git a/drivers/message/i2o/driver.c b/drivers/message/i2o/driver.c
index 0fb9c4e2ad4c..64130227574f 100644
--- a/drivers/message/i2o/driver.c
+++ b/drivers/message/i2o/driver.c
@@ -61,12 +61,10 @@ static int i2o_bus_match(struct device *dev, struct device_driver *drv)
 };
 
 /* I2O bus type */
-extern struct device_attribute i2o_device_attrs[];
-
 struct bus_type i2o_bus_type = {
 	.name = "i2o",
 	.match = i2o_bus_match,
-	.dev_attrs = i2o_device_attrs,
+	.dev_attrs = i2o_device_attrs
 };
 
 /**
@@ -219,14 +217,14 @@ int i2o_driver_dispatch(struct i2o_controller *c, u32 m)
 		/* cut of header from message size (in 32-bit words) */
 		size = (le32_to_cpu(msg->u.head[0]) >> 16) - 5;
 
-		evt = kmalloc(size * 4 + sizeof(*evt), GFP_ATOMIC | __GFP_ZERO);
+		evt = kzalloc(size * 4 + sizeof(*evt), GFP_ATOMIC);
 		if (!evt)
 			return -ENOMEM;
 
 		evt->size = size;
 		evt->tcntxt = le32_to_cpu(msg->u.s.tcntxt);
 		evt->event_indicator = le32_to_cpu(msg->body[0]);
-		memcpy(&evt->tcntxt, &msg->u.s.tcntxt, size * 4);
+		memcpy(&evt->data, &msg->body[1], size * 4);
 
 		list_for_each_entry_safe(dev, tmp, &c->devices, list)
 		    if (dev->lct_data.tid == tid) {
@@ -349,12 +347,10 @@ int __init i2o_driver_init(void)
 	osm_info("max drivers = %d\n", i2o_max_drivers);
 
 	i2o_drivers =
-	    kmalloc(i2o_max_drivers * sizeof(*i2o_drivers), GFP_KERNEL);
+	    kzalloc(i2o_max_drivers * sizeof(*i2o_drivers), GFP_KERNEL);
 	if (!i2o_drivers)
 		return -ENOMEM;
 
-	memset(i2o_drivers, 0, i2o_max_drivers * sizeof(*i2o_drivers));
-
 	rc = bus_register(&i2o_bus_type);
 
 	if (rc < 0)
diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c
index 9c339a2505b0..9bb9859f6dfe 100644
--- a/drivers/message/i2o/exec-osm.c
+++ b/drivers/message/i2o/exec-osm.c
@@ -33,7 +33,7 @@
 #include <linux/workqueue.h>
 #include <linux/string.h>
 #include <linux/slab.h>
-#include <linux/sched.h>   /* wait_event_interruptible_timeout() needs this */
+#include <linux/sched.h>	/* wait_event_interruptible_timeout() needs this */
 #include <asm/param.h>		/* HZ */
 #include "core.h"
 
@@ -75,11 +75,9 @@ static struct i2o_exec_wait *i2o_exec_wait_alloc(void)
 {
 	struct i2o_exec_wait *wait;
 
-	wait = kmalloc(sizeof(*wait), GFP_KERNEL);
+	wait = kzalloc(sizeof(*wait), GFP_KERNEL);
 	if (!wait)
-		return ERR_PTR(-ENOMEM);
-
-	memset(wait, 0, sizeof(*wait));
+		return NULL;
 
 	INIT_LIST_HEAD(&wait->list);
 
@@ -114,13 +112,12 @@ static void i2o_exec_wait_free(struct i2o_exec_wait *wait)
  *	Returns 0 on success, negative error code on timeout or positive error
  *	code from reply.
  */
-int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long
-			  timeout, struct i2o_dma *dma)
+int i2o_msg_post_wait_mem(struct i2o_controller *c, struct i2o_message *msg,
+			  unsigned long timeout, struct i2o_dma *dma)
 {
 	DECLARE_WAIT_QUEUE_HEAD(wq);
 	struct i2o_exec_wait *wait;
 	static u32 tcntxt = 0x80000000;
-	struct i2o_message __iomem *msg = i2o_msg_in_to_virt(c, m);
 	int rc = 0;
 
 	wait = i2o_exec_wait_alloc();
@@ -138,15 +135,15 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long
 	 * We will only use transaction contexts >= 0x80000000 for POST WAIT,
 	 * so we could find a POST WAIT reply easier in the reply handler.
 	 */
-	writel(i2o_exec_driver.context, &msg->u.s.icntxt);
+	msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context);
 	wait->tcntxt = tcntxt++;
-	writel(wait->tcntxt, &msg->u.s.tcntxt);
+	msg->u.s.tcntxt = cpu_to_le32(wait->tcntxt);
 
 	/*
 	 * Post the message to the controller. At some point later it will
 	 * return. If we time out before it returns then complete will be zero.
 	 */
-	i2o_msg_post(c, m);
+	i2o_msg_post(c, msg);
 
 	if (!wait->complete) {
 		wait->wq = &wq;
@@ -266,13 +263,14 @@ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m,
  *
  *	Returns number of bytes printed into buffer.
  */
-static ssize_t i2o_exec_show_vendor_id(struct device *d, struct device_attribute *attr, char *buf)
+static ssize_t i2o_exec_show_vendor_id(struct device *d,
+				       struct device_attribute *attr, char *buf)
 {
 	struct i2o_device *dev = to_i2o_device(d);
 	u16 id;
 
-	if (i2o_parm_field_get(dev, 0x0000, 0, &id, 2)) {
-		sprintf(buf, "0x%04x", id);
+	if (!i2o_parm_field_get(dev, 0x0000, 0, &id, 2)) {
+		sprintf(buf, "0x%04x", le16_to_cpu(id));
 		return strlen(buf) + 1;
 	}
 
@@ -286,13 +284,15 @@ static ssize_t i2o_exec_show_vendor_id(struct device *d, struct device_attribute
  *
  *	Returns number of bytes printed into buffer.
  */
-static ssize_t i2o_exec_show_product_id(struct device *d, struct device_attribute *attr, char *buf)
+static ssize_t i2o_exec_show_product_id(struct device *d,
+					struct device_attribute *attr,
+					char *buf)
 {
 	struct i2o_device *dev = to_i2o_device(d);
 	u16 id;
 
-	if (i2o_parm_field_get(dev, 0x0000, 1, &id, 2)) {
-		sprintf(buf, "0x%04x", id);
+	if (!i2o_parm_field_get(dev, 0x0000, 1, &id, 2)) {
+		sprintf(buf, "0x%04x", le16_to_cpu(id));
 		return strlen(buf) + 1;
 	}
 
@@ -362,7 +362,9 @@ static void i2o_exec_lct_modified(struct i2o_controller *c)
 	if (i2o_device_parse_lct(c) != -EAGAIN)
 		change_ind = c->lct->change_ind + 1;
 
+#ifdef CONFIG_I2O_LCT_NOTIFY_ON_CHANGES
 	i2o_exec_lct_notify(c, change_ind);
+#endif
 };
 
 /**
@@ -385,23 +387,22 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m,
 	u32 context;
 
 	if (le32_to_cpu(msg->u.head[0]) & MSG_FAIL) {
+		struct i2o_message __iomem *pmsg;
+		u32 pm;
+
 		/*
 		 * If Fail bit is set we must take the transaction context of
 		 * the preserved message to find the right request again.
 		 */
-		struct i2o_message __iomem *pmsg;
-		u32 pm;
 
 		pm = le32_to_cpu(msg->body[3]);
-
 		pmsg = i2o_msg_in_to_virt(c, pm);
+		context = readl(&pmsg->u.s.tcntxt);
 
 		i2o_report_status(KERN_INFO, "i2o_core", msg);
 
-		context = readl(&pmsg->u.s.tcntxt);
-
 		/* Release the preserved msg */
-		i2o_msg_nop(c, pm);
+		i2o_msg_nop_mfa(c, pm);
 	} else
 		context = le32_to_cpu(msg->u.s.tcntxt);
 
@@ -462,25 +463,26 @@ static void i2o_exec_event(struct i2o_event *evt)
  */
 int i2o_exec_lct_get(struct i2o_controller *c)
 {
-	struct i2o_message __iomem *msg;
-	u32 m;
+	struct i2o_message *msg;
 	int i = 0;
 	int rc = -EAGAIN;
 
 	for (i = 1; i <= I2O_LCT_GET_TRIES; i++) {
-		m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
-		if (m == I2O_QUEUE_EMPTY)
-			return -ETIMEDOUT;
-
-		writel(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6, &msg->u.head[0]);
-		writel(I2O_CMD_LCT_NOTIFY << 24 | HOST_TID << 12 | ADAPTER_TID,
-		       &msg->u.head[1]);
-		writel(0xffffffff, &msg->body[0]);
-		writel(0x00000000, &msg->body[1]);
-		writel(0xd0000000 | c->dlct.len, &msg->body[2]);
-		writel(c->dlct.phys, &msg->body[3]);
-
-		rc = i2o_msg_post_wait(c, m, I2O_TIMEOUT_LCT_GET);
+		msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+		if (IS_ERR(msg))
+			return PTR_ERR(msg);
+
+		msg->u.head[0] =
+		    cpu_to_le32(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6);
+		msg->u.head[1] =
+		    cpu_to_le32(I2O_CMD_LCT_NOTIFY << 24 | HOST_TID << 12 |
+				ADAPTER_TID);
+		msg->body[0] = cpu_to_le32(0xffffffff);
+		msg->body[1] = cpu_to_le32(0x00000000);
+		msg->body[2] = cpu_to_le32(0xd0000000 | c->dlct.len);
+		msg->body[3] = cpu_to_le32(c->dlct.phys);
+
+		rc = i2o_msg_post_wait(c, msg, I2O_TIMEOUT_LCT_GET);
 		if (rc < 0)
 			break;
 
@@ -506,29 +508,29 @@ static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind)
 {
 	i2o_status_block *sb = c->status_block.virt;
 	struct device *dev;
-	struct i2o_message __iomem *msg;
-	u32 m;
+	struct i2o_message *msg;
 
 	dev = &c->pdev->dev;
 
-	if (i2o_dma_realloc(dev, &c->dlct, sb->expected_lct_size, GFP_KERNEL))
+	if (i2o_dma_realloc
+	    (dev, &c->dlct, le32_to_cpu(sb->expected_lct_size), GFP_KERNEL))
 		return -ENOMEM;
 
-	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
-	if (m == I2O_QUEUE_EMPTY)
-		return -ETIMEDOUT;
-
-	writel(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6, &msg->u.head[0]);
-	writel(I2O_CMD_LCT_NOTIFY << 24 | HOST_TID << 12 | ADAPTER_TID,
-	       &msg->u.head[1]);
-	writel(i2o_exec_driver.context, &msg->u.s.icntxt);
-	writel(0, &msg->u.s.tcntxt);	/* FIXME */
-	writel(0xffffffff, &msg->body[0]);
-	writel(change_ind, &msg->body[1]);
-	writel(0xd0000000 | c->dlct.len, &msg->body[2]);
-	writel(c->dlct.phys, &msg->body[3]);
-
-	i2o_msg_post(c, m);
+	msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+	if (IS_ERR(msg))
+		return PTR_ERR(msg);
+
+	msg->u.head[0] = cpu_to_le32(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6);
+	msg->u.head[1] = cpu_to_le32(I2O_CMD_LCT_NOTIFY << 24 | HOST_TID << 12 |
+				     ADAPTER_TID);
+	msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context);
+	msg->u.s.tcntxt = cpu_to_le32(0x00000000);
+	msg->body[0] = cpu_to_le32(0xffffffff);
+	msg->body[1] = cpu_to_le32(change_ind);
+	msg->body[2] = cpu_to_le32(0xd0000000 | c->dlct.len);
+	msg->body[3] = cpu_to_le32(c->dlct.phys);
+
+	i2o_msg_post(c, msg);
 
 	return 0;
 };
diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c
index f283b5bafdd3..5b1febed3133 100644
--- a/drivers/message/i2o/i2o_block.c
+++ b/drivers/message/i2o/i2o_block.c
@@ -59,10 +59,12 @@
 #include <linux/blkdev.h>
 #include <linux/hdreg.h>
 
+#include <scsi/scsi.h>
+
 #include "i2o_block.h"
 
 #define OSM_NAME	"block-osm"
-#define OSM_VERSION	"1.287"
+#define OSM_VERSION	"1.325"
 #define OSM_DESCRIPTION	"I2O Block Device OSM"
 
 static struct i2o_driver i2o_block_driver;
@@ -130,20 +132,20 @@ static int i2o_block_remove(struct device *dev)
  */
 static int i2o_block_device_flush(struct i2o_device *dev)
 {
-	struct i2o_message __iomem *msg;
-	u32 m;
+	struct i2o_message *msg;
 
-	m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET);
-	if (m == I2O_QUEUE_EMPTY)
-		return -ETIMEDOUT;
+	msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET);
+	if (IS_ERR(msg))
+		return PTR_ERR(msg);
 
-	writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
-	writel(I2O_CMD_BLOCK_CFLUSH << 24 | HOST_TID << 12 | dev->lct_data.tid,
-	       &msg->u.head[1]);
-	writel(60 << 16, &msg->body[0]);
+	msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0);
+	msg->u.head[1] =
+	    cpu_to_le32(I2O_CMD_BLOCK_CFLUSH << 24 | HOST_TID << 12 | dev->
+			lct_data.tid);
+	msg->body[0] = cpu_to_le32(60 << 16);
 	osm_debug("Flushing...\n");
 
-	return i2o_msg_post_wait(dev->iop, m, 60);
+	return i2o_msg_post_wait(dev->iop, msg, 60);
 };
 
 /**
@@ -181,21 +183,21 @@ static int i2o_block_issue_flush(request_queue_t * queue, struct gendisk *disk,
  */
 static int i2o_block_device_mount(struct i2o_device *dev, u32 media_id)
 {
-	struct i2o_message __iomem *msg;
-	u32 m;
-
-	m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET);
-	if (m == I2O_QUEUE_EMPTY)
-		return -ETIMEDOUT;
-
-	writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
-	writel(I2O_CMD_BLOCK_MMOUNT << 24 | HOST_TID << 12 | dev->lct_data.tid,
-	       &msg->u.head[1]);
-	writel(-1, &msg->body[0]);
-	writel(0, &msg->body[1]);
+	struct i2o_message *msg;
+
+	msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET);
+	if (IS_ERR(msg))
+		return PTR_ERR(msg);
+
+	msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0);
+	msg->u.head[1] =
+	    cpu_to_le32(I2O_CMD_BLOCK_MMOUNT << 24 | HOST_TID << 12 | dev->
+			lct_data.tid);
+	msg->body[0] = cpu_to_le32(-1);
+	msg->body[1] = cpu_to_le32(0x00000000);
 	osm_debug("Mounting...\n");
 
-	return i2o_msg_post_wait(dev->iop, m, 2);
+	return i2o_msg_post_wait(dev->iop, msg, 2);
 };
 
 /**
@@ -210,20 +212,20 @@ static int i2o_block_device_mount(struct i2o_device *dev, u32 media_id)
  */
 static int i2o_block_device_lock(struct i2o_device *dev, u32 media_id)
 {
-	struct i2o_message __iomem *msg;
-	u32 m;
+	struct i2o_message *msg;
 
-	m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET);
-	if (m == I2O_QUEUE_EMPTY)
-		return -ETIMEDOUT;
+	msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET);
+	if (IS_ERR(msg) == I2O_QUEUE_EMPTY)
+		return PTR_ERR(msg);
 
-	writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
-	writel(I2O_CMD_BLOCK_MLOCK << 24 | HOST_TID << 12 | dev->lct_data.tid,
-	       &msg->u.head[1]);
-	writel(-1, &msg->body[0]);
+	msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0);
+	msg->u.head[1] =
+	    cpu_to_le32(I2O_CMD_BLOCK_MLOCK << 24 | HOST_TID << 12 | dev->
+			lct_data.tid);
+	msg->body[0] = cpu_to_le32(-1);
 	osm_debug("Locking...\n");
 
-	return i2o_msg_post_wait(dev->iop, m, 2);
+	return i2o_msg_post_wait(dev->iop, msg, 2);
 };
 
 /**
@@ -238,20 +240,20 @@ static int i2o_block_device_lock(struct i2o_device *dev, u32 media_id)
  */
 static int i2o_block_device_unlock(struct i2o_device *dev, u32 media_id)
 {
-	struct i2o_message __iomem *msg;
-	u32 m;
+	struct i2o_message *msg;
 
-	m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET);
-	if (m == I2O_QUEUE_EMPTY)
-		return -ETIMEDOUT;
+	msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET);
+	if (IS_ERR(msg))
+		return PTR_ERR(msg);
 
-	writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
-	writel(I2O_CMD_BLOCK_MUNLOCK << 24 | HOST_TID << 12 | dev->lct_data.tid,
-	       &msg->u.head[1]);
-	writel(media_id, &msg->body[0]);
+	msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0);
+	msg->u.head[1] =
+	    cpu_to_le32(I2O_CMD_BLOCK_MUNLOCK << 24 | HOST_TID << 12 | dev->
+			lct_data.tid);
+	msg->body[0] = cpu_to_le32(media_id);
 	osm_debug("Unlocking...\n");
 
-	return i2o_msg_post_wait(dev->iop, m, 2);
+	return i2o_msg_post_wait(dev->iop, msg, 2);
 };
 
 /**
@@ -267,21 +269,21 @@ static int i2o_block_device_power(struct i2o_block_device *dev, u8 op)
 {
 	struct i2o_device *i2o_dev = dev->i2o_dev;
 	struct i2o_controller *c = i2o_dev->iop;
-	struct i2o_message __iomem *msg;
-	u32 m;
+	struct i2o_message *msg;
 	int rc;
 
-	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
-	if (m == I2O_QUEUE_EMPTY)
-		return -ETIMEDOUT;
+	msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+	if (IS_ERR(msg))
+		return PTR_ERR(msg);
 
-	writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
-	writel(I2O_CMD_BLOCK_POWER << 24 | HOST_TID << 12 | i2o_dev->lct_data.
-	       tid, &msg->u.head[1]);
-	writel(op << 24, &msg->body[0]);
+	msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0);
+	msg->u.head[1] =
+	    cpu_to_le32(I2O_CMD_BLOCK_POWER << 24 | HOST_TID << 12 | i2o_dev->
+			lct_data.tid);
+	msg->body[0] = cpu_to_le32(op << 24);
 	osm_debug("Power...\n");
 
-	rc = i2o_msg_post_wait(c, m, 60);
+	rc = i2o_msg_post_wait(c, msg, 60);
 	if (!rc)
 		dev->power = op;
 
@@ -331,7 +333,7 @@ static inline void i2o_block_request_free(struct i2o_block_request *ireq)
  */
 static inline int i2o_block_sglist_alloc(struct i2o_controller *c,
 					 struct i2o_block_request *ireq,
-					 u32 __iomem ** mptr)
+					 u32 ** mptr)
 {
 	int nents;
 	enum dma_data_direction direction;
@@ -466,7 +468,7 @@ static void i2o_block_end_request(struct request *req, int uptodate,
 
 	spin_lock_irqsave(q->queue_lock, flags);
 
-	end_that_request_last(req);
+	end_that_request_last(req, uptodate);
 
 	if (likely(dev)) {
 		dev->open_queue_depth--;
@@ -745,10 +747,9 @@ static int i2o_block_transfer(struct request *req)
 	struct i2o_block_device *dev = req->rq_disk->private_data;
 	struct i2o_controller *c;
 	int tid = dev->i2o_dev->lct_data.tid;
-	struct i2o_message __iomem *msg;
-	u32 __iomem *mptr;
+	struct i2o_message *msg;
+	u32 *mptr;
 	struct i2o_block_request *ireq = req->special;
-	u32 m;
 	u32 tcntxt;
 	u32 sgl_offset = SGL_OFFSET_8;
 	u32 ctl_flags = 0x00000000;
@@ -763,9 +764,9 @@ static int i2o_block_transfer(struct request *req)
 
 	c = dev->i2o_dev->iop;
 
-	m = i2o_msg_get(c, &msg);
-	if (m == I2O_QUEUE_EMPTY) {
-		rc = -EBUSY;
+	msg = i2o_msg_get(c);
+	if (IS_ERR(msg)) {
+		rc = PTR_ERR(msg);
 		goto exit;
 	}
 
@@ -775,8 +776,8 @@ static int i2o_block_transfer(struct request *req)
 		goto nop_msg;
 	}
 
-	writel(i2o_block_driver.context, &msg->u.s.icntxt);
-	writel(tcntxt, &msg->u.s.tcntxt);
+	msg->u.s.icntxt = cpu_to_le32(i2o_block_driver.context);
+	msg->u.s.tcntxt = cpu_to_le32(tcntxt);
 
 	mptr = &msg->body[0];
 
@@ -834,11 +835,11 @@ static int i2o_block_transfer(struct request *req)
 
 		sgl_offset = SGL_OFFSET_12;
 
-		writel(I2O_CMD_PRIVATE << 24 | HOST_TID << 12 | tid,
-		       &msg->u.head[1]);
+		msg->u.head[1] =
+		    cpu_to_le32(I2O_CMD_PRIVATE << 24 | HOST_TID << 12 | tid);
 
-		writel(I2O_VENDOR_DPT << 16 | I2O_CMD_SCSI_EXEC, mptr++);
-		writel(tid, mptr++);
+		*mptr++ = cpu_to_le32(I2O_VENDOR_DPT << 16 | I2O_CMD_SCSI_EXEC);
+		*mptr++ = cpu_to_le32(tid);
 
 		/*
 		 * ENABLE_DISCONNECT
@@ -846,29 +847,31 @@ static int i2o_block_transfer(struct request *req)
 		 * RETURN_SENSE_DATA_IN_REPLY_MESSAGE_FRAME
 		 */
 		if (rq_data_dir(req) == READ) {
-			cmd[0] = 0x28;
+			cmd[0] = READ_10;
 			scsi_flags = 0x60a0000a;
 		} else {
-			cmd[0] = 0x2A;
+			cmd[0] = WRITE_10;
 			scsi_flags = 0xa0a0000a;
 		}
 
-		writel(scsi_flags, mptr++);
+		*mptr++ = cpu_to_le32(scsi_flags);
 
 		*((u32 *) & cmd[2]) = cpu_to_be32(req->sector * hwsec);
 		*((u16 *) & cmd[7]) = cpu_to_be16(req->nr_sectors * hwsec);
 
-		memcpy_toio(mptr, cmd, 10);
+		memcpy(mptr, cmd, 10);
 		mptr += 4;
-		writel(req->nr_sectors << KERNEL_SECTOR_SHIFT, mptr++);
+		*mptr++ = cpu_to_le32(req->nr_sectors << KERNEL_SECTOR_SHIFT);
 	} else
 #endif
 	{
-		writel(cmd | HOST_TID << 12 | tid, &msg->u.head[1]);
-		writel(ctl_flags, mptr++);
-		writel(req->nr_sectors << KERNEL_SECTOR_SHIFT, mptr++);
-		writel((u32) (req->sector << KERNEL_SECTOR_SHIFT), mptr++);
-		writel(req->sector >> (32 - KERNEL_SECTOR_SHIFT), mptr++);
+		msg->u.head[1] = cpu_to_le32(cmd | HOST_TID << 12 | tid);
+		*mptr++ = cpu_to_le32(ctl_flags);
+		*mptr++ = cpu_to_le32(req->nr_sectors << KERNEL_SECTOR_SHIFT);
+		*mptr++ =
+		    cpu_to_le32((u32) (req->sector << KERNEL_SECTOR_SHIFT));
+		*mptr++ =
+		    cpu_to_le32(req->sector >> (32 - KERNEL_SECTOR_SHIFT));
 	}
 
 	if (!i2o_block_sglist_alloc(c, ireq, &mptr)) {
@@ -876,13 +879,13 @@ static int i2o_block_transfer(struct request *req)
 		goto context_remove;
 	}
 
-	writel(I2O_MESSAGE_SIZE(mptr - &msg->u.head[0]) |
-	       sgl_offset, &msg->u.head[0]);
+	msg->u.head[0] =
+	    cpu_to_le32(I2O_MESSAGE_SIZE(mptr - &msg->u.head[0]) | sgl_offset);
 
 	list_add_tail(&ireq->queue, &dev->open_queue);
 	dev->open_queue_depth++;
 
-	i2o_msg_post(c, m);
+	i2o_msg_post(c, msg);
 
 	return 0;
 
@@ -890,7 +893,7 @@ static int i2o_block_transfer(struct request *req)
 	i2o_cntxt_list_remove(c, req);
 
       nop_msg:
-	i2o_msg_nop(c, m);
+	i2o_msg_nop(c, msg);
 
       exit:
 	return rc;
@@ -978,13 +981,12 @@ static struct i2o_block_device *i2o_block_device_alloc(void)
 	struct request_queue *queue;
 	int rc;
 
-	dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 	if (!dev) {
 		osm_err("Insufficient memory to allocate I2O Block disk.\n");
 		rc = -ENOMEM;
 		goto exit;
 	}
-	memset(dev, 0, sizeof(*dev));
 
 	INIT_LIST_HEAD(&dev->open_queue);
 	spin_lock_init(&dev->lock);
@@ -1049,8 +1051,8 @@ static int i2o_block_probe(struct device *dev)
 	int rc;
 	u64 size;
 	u32 blocksize;
-	u32 flags, status;
 	u16 body_size = 4;
+	u16 power;
 	unsigned short max_sectors;
 
 #ifdef CONFIG_I2O_EXT_ADAPTEC
@@ -1108,22 +1110,20 @@ static int i2o_block_probe(struct device *dev)
 	 *      Ask for the current media data. If that isn't supported
 	 *      then we ask for the device capacity data
 	 */
-	if (i2o_parm_field_get(i2o_dev, 0x0004, 1, &blocksize, 4) ||
-	    i2o_parm_field_get(i2o_dev, 0x0000, 3, &blocksize, 4)) {
-		blk_queue_hardsect_size(queue, blocksize);
+	if (!i2o_parm_field_get(i2o_dev, 0x0004, 1, &blocksize, 4) ||
+	    !i2o_parm_field_get(i2o_dev, 0x0000, 3, &blocksize, 4)) {
+		blk_queue_hardsect_size(queue, le32_to_cpu(blocksize));
 	} else
 		osm_warn("unable to get blocksize of %s\n", gd->disk_name);
 
-	if (i2o_parm_field_get(i2o_dev, 0x0004, 0, &size, 8) ||
-	    i2o_parm_field_get(i2o_dev, 0x0000, 4, &size, 8)) {
-		set_capacity(gd, size >> KERNEL_SECTOR_SHIFT);
+	if (!i2o_parm_field_get(i2o_dev, 0x0004, 0, &size, 8) ||
+	    !i2o_parm_field_get(i2o_dev, 0x0000, 4, &size, 8)) {
+		set_capacity(gd, le64_to_cpu(size) >> KERNEL_SECTOR_SHIFT);
 	} else
 		osm_warn("could not get size of %s\n", gd->disk_name);
 
-	if (!i2o_parm_field_get(i2o_dev, 0x0000, 2, &i2o_blk_dev->power, 2))
-		i2o_blk_dev->power = 0;
-	i2o_parm_field_get(i2o_dev, 0x0000, 5, &flags, 4);
-	i2o_parm_field_get(i2o_dev, 0x0000, 6, &status, 4);
+	if (!i2o_parm_field_get(i2o_dev, 0x0000, 2, &power, 2))
+		i2o_blk_dev->power = power;
 
 	i2o_event_register(i2o_dev, &i2o_block_driver, 0, 0xffffffff);
 
diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c
index 3c3a7abebb1b..89daf67b764d 100644
--- a/drivers/message/i2o/i2o_config.c
+++ b/drivers/message/i2o/i2o_config.c
@@ -36,12 +36,12 @@
 
 #include <asm/uaccess.h>
 
-#include "core.h"
-
 #define SG_TABLESIZE		30
 
-static int i2o_cfg_ioctl(struct inode *inode, struct file *fp, unsigned int cmd,
-			 unsigned long arg);
+extern int i2o_parm_issue(struct i2o_device *, int, void *, int, void *, int);
+
+static int i2o_cfg_ioctl(struct inode *, struct file *, unsigned int,
+			 unsigned long);
 
 static spinlock_t i2o_config_lock;
 
@@ -230,8 +230,7 @@ static int i2o_cfg_swdl(unsigned long arg)
 	struct i2o_sw_xfer __user *pxfer = (struct i2o_sw_xfer __user *)arg;
 	unsigned char maxfrag = 0, curfrag = 1;
 	struct i2o_dma buffer;
-	struct i2o_message __iomem *msg;
-	u32 m;
+	struct i2o_message *msg;
 	unsigned int status = 0, swlen = 0, fragsize = 8192;
 	struct i2o_controller *c;
 
@@ -257,31 +256,34 @@ static int i2o_cfg_swdl(unsigned long arg)
 	if (!c)
 		return -ENXIO;
 
-	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
-	if (m == I2O_QUEUE_EMPTY)
-		return -EBUSY;
+	msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+	if (IS_ERR(msg))
+		return PTR_ERR(msg);
 
 	if (i2o_dma_alloc(&c->pdev->dev, &buffer, fragsize, GFP_KERNEL)) {
-		i2o_msg_nop(c, m);
+		i2o_msg_nop(c, msg);
 		return -ENOMEM;
 	}
 
 	__copy_from_user(buffer.virt, kxfer.buf, fragsize);
 
-	writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_7, &msg->u.head[0]);
-	writel(I2O_CMD_SW_DOWNLOAD << 24 | HOST_TID << 12 | ADAPTER_TID,
-	       &msg->u.head[1]);
-	writel(i2o_config_driver.context, &msg->u.head[2]);
-	writel(0, &msg->u.head[3]);
-	writel((((u32) kxfer.flags) << 24) | (((u32) kxfer.sw_type) << 16) |
-	       (((u32) maxfrag) << 8) | (((u32) curfrag)), &msg->body[0]);
-	writel(swlen, &msg->body[1]);
-	writel(kxfer.sw_id, &msg->body[2]);
-	writel(0xD0000000 | fragsize, &msg->body[3]);
-	writel(buffer.phys, &msg->body[4]);
+	msg->u.head[0] = cpu_to_le32(NINE_WORD_MSG_SIZE | SGL_OFFSET_7);
+	msg->u.head[1] =
+	    cpu_to_le32(I2O_CMD_SW_DOWNLOAD << 24 | HOST_TID << 12 |
+			ADAPTER_TID);
+	msg->u.head[2] = cpu_to_le32(i2o_config_driver.context);
+	msg->u.head[3] = cpu_to_le32(0);
+	msg->body[0] =
+	    cpu_to_le32((((u32) kxfer.flags) << 24) | (((u32) kxfer.
+							sw_type) << 16) |
+			(((u32) maxfrag) << 8) | (((u32) curfrag)));
+	msg->body[1] = cpu_to_le32(swlen);
+	msg->body[2] = cpu_to_le32(kxfer.sw_id);
+	msg->body[3] = cpu_to_le32(0xD0000000 | fragsize);
+	msg->body[4] = cpu_to_le32(buffer.phys);
 
 	osm_debug("swdl frag %d/%d (size %d)\n", curfrag, maxfrag, fragsize);
-	status = i2o_msg_post_wait_mem(c, m, 60, &buffer);
+	status = i2o_msg_post_wait_mem(c, msg, 60, &buffer);
 
 	if (status != -ETIMEDOUT)
 		i2o_dma_free(&c->pdev->dev, &buffer);
@@ -302,8 +304,7 @@ static int i2o_cfg_swul(unsigned long arg)
 	struct i2o_sw_xfer __user *pxfer = (struct i2o_sw_xfer __user *)arg;
 	unsigned char maxfrag = 0, curfrag = 1;
 	struct i2o_dma buffer;
-	struct i2o_message __iomem *msg;
-	u32 m;
+	struct i2o_message *msg;
 	unsigned int status = 0, swlen = 0, fragsize = 8192;
 	struct i2o_controller *c;
 	int ret = 0;
@@ -330,30 +331,30 @@ static int i2o_cfg_swul(unsigned long arg)
 	if (!c)
 		return -ENXIO;
 
-	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
-	if (m == I2O_QUEUE_EMPTY)
-		return -EBUSY;
+	msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+	if (IS_ERR(msg))
+		return PTR_ERR(msg);
 
 	if (i2o_dma_alloc(&c->pdev->dev, &buffer, fragsize, GFP_KERNEL)) {
-		i2o_msg_nop(c, m);
+		i2o_msg_nop(c, msg);
 		return -ENOMEM;
 	}
 
-	writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_7, &msg->u.head[0]);
-	writel(I2O_CMD_SW_UPLOAD << 24 | HOST_TID << 12 | ADAPTER_TID,
-	       &msg->u.head[1]);
-	writel(i2o_config_driver.context, &msg->u.head[2]);
-	writel(0, &msg->u.head[3]);
-	writel((u32) kxfer.flags << 24 | (u32) kxfer.
-	       sw_type << 16 | (u32) maxfrag << 8 | (u32) curfrag,
-	       &msg->body[0]);
-	writel(swlen, &msg->body[1]);
-	writel(kxfer.sw_id, &msg->body[2]);
-	writel(0xD0000000 | fragsize, &msg->body[3]);
-	writel(buffer.phys, &msg->body[4]);
+	msg->u.head[0] = cpu_to_le32(NINE_WORD_MSG_SIZE | SGL_OFFSET_7);
+	msg->u.head[1] =
+	    cpu_to_le32(I2O_CMD_SW_UPLOAD << 24 | HOST_TID << 12 | ADAPTER_TID);
+	msg->u.head[2] = cpu_to_le32(i2o_config_driver.context);
+	msg->u.head[3] = cpu_to_le32(0);
+	msg->body[0] =
+	    cpu_to_le32((u32) kxfer.flags << 24 | (u32) kxfer.
+			sw_type << 16 | (u32) maxfrag << 8 | (u32) curfrag);
+	msg->body[1] = cpu_to_le32(swlen);
+	msg->body[2] = cpu_to_le32(kxfer.sw_id);
+	msg->body[3] = cpu_to_le32(0xD0000000 | fragsize);
+	msg->body[4] = cpu_to_le32(buffer.phys);
 
 	osm_debug("swul frag %d/%d (size %d)\n", curfrag, maxfrag, fragsize);
-	status = i2o_msg_post_wait_mem(c, m, 60, &buffer);
+	status = i2o_msg_post_wait_mem(c, msg, 60, &buffer);
 
 	if (status != I2O_POST_WAIT_OK) {
 		if (status != -ETIMEDOUT)
@@ -380,8 +381,7 @@ static int i2o_cfg_swdel(unsigned long arg)
 	struct i2o_controller *c;
 	struct i2o_sw_xfer kxfer;
 	struct i2o_sw_xfer __user *pxfer = (struct i2o_sw_xfer __user *)arg;
-	struct i2o_message __iomem *msg;
-	u32 m;
+	struct i2o_message *msg;
 	unsigned int swlen;
 	int token;
 
@@ -395,21 +395,21 @@ static int i2o_cfg_swdel(unsigned long arg)
 	if (!c)
 		return -ENXIO;
 
-	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
-	if (m == I2O_QUEUE_EMPTY)
-		return -EBUSY;
+	msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+	if (IS_ERR(msg))
+		return PTR_ERR(msg);
 
-	writel(SEVEN_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
-	writel(I2O_CMD_SW_REMOVE << 24 | HOST_TID << 12 | ADAPTER_TID,
-	       &msg->u.head[1]);
-	writel(i2o_config_driver.context, &msg->u.head[2]);
-	writel(0, &msg->u.head[3]);
-	writel((u32) kxfer.flags << 24 | (u32) kxfer.sw_type << 16,
-	       &msg->body[0]);
-	writel(swlen, &msg->body[1]);
-	writel(kxfer.sw_id, &msg->body[2]);
+	msg->u.head[0] = cpu_to_le32(SEVEN_WORD_MSG_SIZE | SGL_OFFSET_0);
+	msg->u.head[1] =
+	    cpu_to_le32(I2O_CMD_SW_REMOVE << 24 | HOST_TID << 12 | ADAPTER_TID);
+	msg->u.head[2] = cpu_to_le32(i2o_config_driver.context);
+	msg->u.head[3] = cpu_to_le32(0);
+	msg->body[0] =
+	    cpu_to_le32((u32) kxfer.flags << 24 | (u32) kxfer.sw_type << 16);
+	msg->body[1] = cpu_to_le32(swlen);
+	msg->body[2] = cpu_to_le32(kxfer.sw_id);
 
-	token = i2o_msg_post_wait(c, m, 10);
+	token = i2o_msg_post_wait(c, msg, 10);
 
 	if (token != I2O_POST_WAIT_OK) {
 		osm_info("swdel failed, DetailedStatus = %d\n", token);
@@ -423,25 +423,24 @@ static int i2o_cfg_validate(unsigned long arg)
 {
 	int token;
 	int iop = (int)arg;
-	struct i2o_message __iomem *msg;
-	u32 m;
+	struct i2o_message *msg;
 	struct i2o_controller *c;
 
 	c = i2o_find_iop(iop);
 	if (!c)
 		return -ENXIO;
 
-	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
-	if (m == I2O_QUEUE_EMPTY)
-		return -EBUSY;
+	msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+	if (IS_ERR(msg))
+		return PTR_ERR(msg);
 
-	writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
-	writel(I2O_CMD_CONFIG_VALIDATE << 24 | HOST_TID << 12 | iop,
-	       &msg->u.head[1]);
-	writel(i2o_config_driver.context, &msg->u.head[2]);
-	writel(0, &msg->u.head[3]);
+	msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0);
+	msg->u.head[1] =
+	    cpu_to_le32(I2O_CMD_CONFIG_VALIDATE << 24 | HOST_TID << 12 | iop);
+	msg->u.head[2] = cpu_to_le32(i2o_config_driver.context);
+	msg->u.head[3] = cpu_to_le32(0);
 
-	token = i2o_msg_post_wait(c, m, 10);
+	token = i2o_msg_post_wait(c, msg, 10);
 
 	if (token != I2O_POST_WAIT_OK) {
 		osm_info("Can't validate configuration, ErrorStatus = %d\n",
@@ -454,8 +453,7 @@ static int i2o_cfg_validate(unsigned long arg)
 
 static int i2o_cfg_evt_reg(unsigned long arg, struct file *fp)
 {
-	struct i2o_message __iomem *msg;
-	u32 m;
+	struct i2o_message *msg;
 	struct i2o_evt_id __user *pdesc = (struct i2o_evt_id __user *)arg;
 	struct i2o_evt_id kdesc;
 	struct i2o_controller *c;
@@ -474,18 +472,19 @@ static int i2o_cfg_evt_reg(unsigned long arg, struct file *fp)
 	if (!d)
 		return -ENODEV;
 
-	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
-	if (m == I2O_QUEUE_EMPTY)
-		return -EBUSY;
+	msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+	if (IS_ERR(msg))
+		return PTR_ERR(msg);
 
-	writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
-	writel(I2O_CMD_UTIL_EVT_REGISTER << 24 | HOST_TID << 12 | kdesc.tid,
-	       &msg->u.head[1]);
-	writel(i2o_config_driver.context, &msg->u.head[2]);
-	writel(i2o_cntxt_list_add(c, fp->private_data), &msg->u.head[3]);
-	writel(kdesc.evt_mask, &msg->body[0]);
+	msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0);
+	msg->u.head[1] =
+	    cpu_to_le32(I2O_CMD_UTIL_EVT_REGISTER << 24 | HOST_TID << 12 |
+			kdesc.tid);
+	msg->u.head[2] = cpu_to_le32(i2o_config_driver.context);
+	msg->u.head[3] = cpu_to_le32(i2o_cntxt_list_add(c, fp->private_data));
+	msg->body[0] = cpu_to_le32(kdesc.evt_mask);
 
-	i2o_msg_post(c, m);
+	i2o_msg_post(c, msg);
 
 	return 0;
 }
@@ -537,7 +536,6 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
 	u32 sg_index = 0;
 	i2o_status_block *sb;
 	struct i2o_message *msg;
-	u32 m;
 	unsigned int iop;
 
 	cmd = (struct i2o_cmd_passthru32 __user *)arg;
@@ -553,7 +551,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
 		return -ENXIO;
 	}
 
-	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+	msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
 
 	sb = c->status_block.virt;
 
@@ -585,19 +583,15 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
 	reply_size >>= 16;
 	reply_size <<= 2;
 
-	reply = kmalloc(reply_size, GFP_KERNEL);
+	reply = kzalloc(reply_size, GFP_KERNEL);
 	if (!reply) {
 		printk(KERN_WARNING "%s: Could not allocate reply buffer\n",
 		       c->name);
 		return -ENOMEM;
 	}
-	memset(reply, 0, reply_size);
 
 	sg_offset = (msg->u.head[0] >> 4) & 0x0f;
 
-	writel(i2o_config_driver.context, &msg->u.s.icntxt);
-	writel(i2o_cntxt_list_add(c, reply), &msg->u.s.tcntxt);
-
 	memset(sg_list, 0, sizeof(sg_list[0]) * SG_TABLESIZE);
 	if (sg_offset) {
 		struct sg_simple_element *sg;
@@ -631,7 +625,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
 				goto cleanup;
 			}
 			sg_size = sg[i].flag_count & 0xffffff;
-			p = &(sg_list[sg_index++]);
+			p = &(sg_list[sg_index]);
 			/* Allocate memory for the transfer */
 			if (i2o_dma_alloc
 			    (&c->pdev->dev, p, sg_size,
@@ -642,6 +636,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
 				rcode = -ENOMEM;
 				goto sg_list_cleanup;
 			}
+			sg_index++;
 			/* Copy in the user's SG buffer if necessary */
 			if (sg[i].
 			    flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR */ ) {
@@ -662,9 +657,11 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
 		}
 	}
 
-	rcode = i2o_msg_post_wait(c, m, 60);
-	if (rcode)
+	rcode = i2o_msg_post_wait(c, msg, 60);
+	if (rcode) {
+		reply[4] = ((u32) rcode) << 24;
 		goto sg_list_cleanup;
+	}
 
 	if (sg_offset) {
 		u32 msg[I2O_OUTBOUND_MSG_FRAME_SIZE];
@@ -714,6 +711,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
 		}
 	}
 
+      sg_list_cleanup:
 	/* Copy back the reply to user space */
 	if (reply_size) {
 		// we wrote our own values for context - now restore the user supplied ones
@@ -731,7 +729,6 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
 		}
 	}
 
-      sg_list_cleanup:
 	for (i = 0; i < sg_index; i++)
 		i2o_dma_free(&c->pdev->dev, &sg_list[i]);
 
@@ -780,8 +777,7 @@ static int i2o_cfg_passthru(unsigned long arg)
 	u32 i = 0;
 	void *p = NULL;
 	i2o_status_block *sb;
-	struct i2o_message __iomem *msg;
-	u32 m;
+	struct i2o_message *msg;
 	unsigned int iop;
 
 	if (get_user(iop, &cmd->iop) || get_user(user_msg, &cmd->msg))
@@ -793,7 +789,7 @@ static int i2o_cfg_passthru(unsigned long arg)
 		return -ENXIO;
 	}
 
-	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+	msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
 
 	sb = c->status_block.virt;
 
@@ -820,19 +816,15 @@ static int i2o_cfg_passthru(unsigned long arg)
 	reply_size >>= 16;
 	reply_size <<= 2;
 
-	reply = kmalloc(reply_size, GFP_KERNEL);
+	reply = kzalloc(reply_size, GFP_KERNEL);
 	if (!reply) {
 		printk(KERN_WARNING "%s: Could not allocate reply buffer\n",
 		       c->name);
 		return -ENOMEM;
 	}
-	memset(reply, 0, reply_size);
 
 	sg_offset = (msg->u.head[0] >> 4) & 0x0f;
 
-	writel(i2o_config_driver.context, &msg->u.s.icntxt);
-	writel(i2o_cntxt_list_add(c, reply), &msg->u.s.tcntxt);
-
 	memset(sg_list, 0, sizeof(sg_list[0]) * SG_TABLESIZE);
 	if (sg_offset) {
 		struct sg_simple_element *sg;
@@ -894,9 +886,11 @@ static int i2o_cfg_passthru(unsigned long arg)
 		}
 	}
 
-	rcode = i2o_msg_post_wait(c, m, 60);
-	if (rcode)
+	rcode = i2o_msg_post_wait(c, msg, 60);
+	if (rcode) {
+		reply[4] = ((u32) rcode) << 24;
 		goto sg_list_cleanup;
+	}
 
 	if (sg_offset) {
 		u32 msg[128];
@@ -946,6 +940,7 @@ static int i2o_cfg_passthru(unsigned long arg)
 		}
 	}
 
+      sg_list_cleanup:
 	/* Copy back the reply to user space */
 	if (reply_size) {
 		// we wrote our own values for context - now restore the user supplied ones
@@ -962,7 +957,6 @@ static int i2o_cfg_passthru(unsigned long arg)
 		}
 	}
 
-      sg_list_cleanup:
 	for (i = 0; i < sg_index; i++)
 		kfree(sg_list[i]);
 
diff --git a/drivers/message/i2o/i2o_lan.h b/drivers/message/i2o/i2o_lan.h
index 561d63304d7e..6502b817df58 100644
--- a/drivers/message/i2o/i2o_lan.h
+++ b/drivers/message/i2o/i2o_lan.h
@@ -103,14 +103,14 @@
 #define I2O_LAN_DSC_SUSPENDED			0x11
 
 struct i2o_packet_info {
-	u32 offset : 24;
-	u32 flags  : 8;
-	u32 len    : 24;
-	u32 status : 8;
+	u32 offset:24;
+	u32 flags:8;
+	u32 len:24;
+	u32 status:8;
 };
 
 struct i2o_bucket_descriptor {
-	u32 context; 			/* FIXME: 64bit support */
+	u32 context;		/* FIXME: 64bit support */
 	struct i2o_packet_info packet_info[1];
 };
 
@@ -127,14 +127,14 @@ struct i2o_lan_local {
 	u8 unit;
 	struct i2o_device *i2o_dev;
 
-	struct fddi_statistics stats;   /* see also struct net_device_stats */
-	unsigned short (*type_trans)(struct sk_buff *, struct net_device *);
-	atomic_t buckets_out;  		/* nbr of unused buckets on DDM */
-	atomic_t tx_out;		/* outstanding TXes */
-	u8 tx_count;  			/* packets in one TX message frame */
-	u16 tx_max_out;	   		/* DDM's Tx queue len */
-	u8 sgl_max;			/* max SGLs in one message frame */
-	u32 m;				/* IOP address of the batch msg frame */
+	struct fddi_statistics stats;	/* see also struct net_device_stats */
+	unsigned short (*type_trans) (struct sk_buff *, struct net_device *);
+	atomic_t buckets_out;	/* nbr of unused buckets on DDM */
+	atomic_t tx_out;	/* outstanding TXes */
+	u8 tx_count;		/* packets in one TX message frame */
+	u16 tx_max_out;		/* DDM's Tx queue len */
+	u8 sgl_max;		/* max SGLs in one message frame */
+	u32 m;			/* IOP address of the batch msg frame */
 
 	struct work_struct i2o_batch_send_task;
 	int send_active;
@@ -144,16 +144,16 @@ struct i2o_lan_local {
 
 	spinlock_t tx_lock;
 
-	u32 max_size_mc_table;		/* max number of multicast addresses */
+	u32 max_size_mc_table;	/* max number of multicast addresses */
 
 	/* LAN OSM configurable parameters are here: */
 
-	u16 max_buckets_out;		/* max nbr of buckets to send to DDM */
-	u16 bucket_thresh;		/* send more when this many used */
+	u16 max_buckets_out;	/* max nbr of buckets to send to DDM */
+	u16 bucket_thresh;	/* send more when this many used */
 	u16 rx_copybreak;
 
-	u8  tx_batch_mode;		/* Set when using batch mode sends */
-	u32 i2o_event_mask;		/* To turn on interesting event flags */
+	u8 tx_batch_mode;	/* Set when using batch mode sends */
+	u32 i2o_event_mask;	/* To turn on interesting event flags */
 };
 
-#endif /* _I2O_LAN_H */
+#endif				/* _I2O_LAN_H */
diff --git a/drivers/message/i2o/i2o_proc.c b/drivers/message/i2o/i2o_proc.c
index d559a1758363..2a0c42b8cda5 100644
--- a/drivers/message/i2o/i2o_proc.c
+++ b/drivers/message/i2o/i2o_proc.c
@@ -28,7 +28,7 @@
  */
 
 #define OSM_NAME	"proc-osm"
-#define OSM_VERSION	"1.145"
+#define OSM_VERSION	"1.316"
 #define OSM_DESCRIPTION	"I2O ProcFS OSM"
 
 #define I2O_MAX_MODULES 4
diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c
index 9f1744c3933b..f9e5a23697a1 100644
--- a/drivers/message/i2o/i2o_scsi.c
+++ b/drivers/message/i2o/i2o_scsi.c
@@ -70,7 +70,7 @@
 #include <scsi/sg_request.h>
 
 #define OSM_NAME	"scsi-osm"
-#define OSM_VERSION	"1.282"
+#define OSM_VERSION	"1.316"
 #define OSM_DESCRIPTION	"I2O SCSI Peripheral OSM"
 
 static struct i2o_driver i2o_scsi_driver;
@@ -113,7 +113,7 @@ static struct i2o_scsi_host *i2o_scsi_host_alloc(struct i2o_controller *c)
 
 	list_for_each_entry(i2o_dev, &c->devices, list)
 	    if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER) {
-		if (i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1)
+		if (!i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1)
 		    && (type == 0x01))	/* SCSI bus */
 			max_channel++;
 	}
@@ -146,7 +146,7 @@ static struct i2o_scsi_host *i2o_scsi_host_alloc(struct i2o_controller *c)
 	i = 0;
 	list_for_each_entry(i2o_dev, &c->devices, list)
 	    if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER) {
-		if (i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1)
+		if (!i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1)
 		    && (type == 0x01))	/* only SCSI bus */
 			i2o_shost->channel[i++] = i2o_dev;
 
@@ -238,13 +238,15 @@ static int i2o_scsi_probe(struct device *dev)
 			u8 type;
 			struct i2o_device *d = i2o_shost->channel[0];
 
-			if (i2o_parm_field_get(d, 0x0000, 0, &type, 1)
+			if (!i2o_parm_field_get(d, 0x0000, 0, &type, 1)
 			    && (type == 0x01))	/* SCSI bus */
-				if (i2o_parm_field_get(d, 0x0200, 4, &id, 4)) {
+				if (!i2o_parm_field_get(d, 0x0200, 4, &id, 4)) {
 					channel = 0;
 					if (i2o_dev->lct_data.class_id ==
 					    I2O_CLASS_RANDOM_BLOCK_STORAGE)
-						lun = i2o_shost->lun++;
+						lun =
+						    cpu_to_le64(i2o_shost->
+								lun++);
 					else
 						lun = 0;
 				}
@@ -253,10 +255,10 @@ static int i2o_scsi_probe(struct device *dev)
 		break;
 
 	case I2O_CLASS_SCSI_PERIPHERAL:
-		if (i2o_parm_field_get(i2o_dev, 0x0000, 3, &id, 4) < 0)
+		if (i2o_parm_field_get(i2o_dev, 0x0000, 3, &id, 4))
 			return -EFAULT;
 
-		if (i2o_parm_field_get(i2o_dev, 0x0000, 4, &lun, 8) < 0)
+		if (i2o_parm_field_get(i2o_dev, 0x0000, 4, &lun, 8))
 			return -EFAULT;
 
 		parent = i2o_iop_find_device(c, i2o_dev->lct_data.parent_tid);
@@ -281,20 +283,22 @@ static int i2o_scsi_probe(struct device *dev)
 		return -EFAULT;
 	}
 
-	if (id >= scsi_host->max_id) {
-		osm_warn("SCSI device id (%d) >= max_id of I2O host (%d)", id,
-			 scsi_host->max_id);
+	if (le32_to_cpu(id) >= scsi_host->max_id) {
+		osm_warn("SCSI device id (%d) >= max_id of I2O host (%d)",
+			 le32_to_cpu(id), scsi_host->max_id);
 		return -EFAULT;
 	}
 
-	if (lun >= scsi_host->max_lun) {
-		osm_warn("SCSI device id (%d) >= max_lun of I2O host (%d)",
-			 (unsigned int)lun, scsi_host->max_lun);
+	if (le64_to_cpu(lun) >= scsi_host->max_lun) {
+		osm_warn("SCSI device lun (%lu) >= max_lun of I2O host (%d)",
+			 (long unsigned int)le64_to_cpu(lun),
+			 scsi_host->max_lun);
 		return -EFAULT;
 	}
 
 	scsi_dev =
-	    __scsi_add_device(i2o_shost->scsi_host, channel, id, lun, i2o_dev);
+	    __scsi_add_device(i2o_shost->scsi_host, channel, le32_to_cpu(id),
+			      le64_to_cpu(lun), i2o_dev);
 
 	if (IS_ERR(scsi_dev)) {
 		osm_warn("can not add SCSI device %03x\n",
@@ -305,8 +309,9 @@ static int i2o_scsi_probe(struct device *dev)
 	sysfs_create_link(&i2o_dev->device.kobj, &scsi_dev->sdev_gendev.kobj,
 			  "scsi");
 
-	osm_info("device added (TID: %03x) channel: %d, id: %d, lun: %d\n",
-		 i2o_dev->lct_data.tid, channel, id, (unsigned int)lun);
+	osm_info("device added (TID: %03x) channel: %d, id: %d, lun: %ld\n",
+		 i2o_dev->lct_data.tid, channel, le32_to_cpu(id),
+		 (long unsigned int)le64_to_cpu(lun));
 
 	return 0;
 };
@@ -510,8 +515,7 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
 	struct i2o_controller *c;
 	struct i2o_device *i2o_dev;
 	int tid;
-	struct i2o_message __iomem *msg;
-	u32 m;
+	struct i2o_message *msg;
 	/*
 	 * ENABLE_DISCONNECT
 	 * SIMPLE_TAG
@@ -519,7 +523,7 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
 	 */
 	u32 scsi_flags = 0x20a00000;
 	u32 sgl_offset;
-	u32 __iomem *mptr;
+	u32 *mptr;
 	u32 cmd = I2O_CMD_SCSI_EXEC << 24;
 	int rc = 0;
 
@@ -576,8 +580,8 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
 	 *      throw it back to the scsi layer
 	 */
 
-	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
-	if (m == I2O_QUEUE_EMPTY) {
+	msg = i2o_msg_get(c);
+	if (IS_ERR(msg)) {
 		rc = SCSI_MLQUEUE_HOST_BUSY;
 		goto exit;
 	}
@@ -617,16 +621,16 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
 		if (sgl_offset == SGL_OFFSET_10)
 			sgl_offset = SGL_OFFSET_12;
 		cmd = I2O_CMD_PRIVATE << 24;
-		writel(I2O_VENDOR_DPT << 16 | I2O_CMD_SCSI_EXEC, mptr++);
-		writel(adpt_flags | tid, mptr++);
+		*mptr++ = cpu_to_le32(I2O_VENDOR_DPT << 16 | I2O_CMD_SCSI_EXEC);
+		*mptr++ = cpu_to_le32(adpt_flags | tid);
 	}
 #endif
 
-	writel(cmd | HOST_TID << 12 | tid, &msg->u.head[1]);
-	writel(i2o_scsi_driver.context, &msg->u.s.icntxt);
+	msg->u.head[1] = cpu_to_le32(cmd | HOST_TID << 12 | tid);
+	msg->u.s.icntxt = cpu_to_le32(i2o_scsi_driver.context);
 
 	/* We want the SCSI control block back */
-	writel(i2o_cntxt_list_add(c, SCpnt), &msg->u.s.tcntxt);
+	msg->u.s.tcntxt = cpu_to_le32(i2o_cntxt_list_add(c, SCpnt));
 
 	/* LSI_920_PCI_QUIRK
 	 *
@@ -649,15 +653,15 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
 	   }
 	 */
 
-	writel(scsi_flags | SCpnt->cmd_len, mptr++);
+	*mptr++ = cpu_to_le32(scsi_flags | SCpnt->cmd_len);
 
 	/* Write SCSI command into the message - always 16 byte block */
-	memcpy_toio(mptr, SCpnt->cmnd, 16);
+	memcpy(mptr, SCpnt->cmnd, 16);
 	mptr += 4;
 
 	if (sgl_offset != SGL_OFFSET_0) {
 		/* write size of data addressed by SGL */
-		writel(SCpnt->request_bufflen, mptr++);
+		*mptr++ = cpu_to_le32(SCpnt->request_bufflen);
 
 		/* Now fill in the SGList and command */
 		if (SCpnt->use_sg) {
@@ -676,11 +680,11 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
 	}
 
 	/* Stick the headers on */
-	writel(I2O_MESSAGE_SIZE(mptr - &msg->u.head[0]) | sgl_offset,
-	       &msg->u.head[0]);
+	msg->u.head[0] =
+	    cpu_to_le32(I2O_MESSAGE_SIZE(mptr - &msg->u.head[0]) | sgl_offset);
 
 	/* Queue the message */
-	i2o_msg_post(c, m);
+	i2o_msg_post(c, msg);
 
 	osm_debug("Issued %ld\n", SCpnt->serial_number);
 
@@ -688,7 +692,7 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
 
       nomem:
 	rc = -ENOMEM;
-	i2o_msg_nop(c, m);
+	i2o_msg_nop(c, msg);
 
       exit:
 	return rc;
@@ -709,8 +713,7 @@ static int i2o_scsi_abort(struct scsi_cmnd *SCpnt)
 {
 	struct i2o_device *i2o_dev;
 	struct i2o_controller *c;
-	struct i2o_message __iomem *msg;
-	u32 m;
+	struct i2o_message *msg;
 	int tid;
 	int status = FAILED;
 
@@ -720,16 +723,16 @@ static int i2o_scsi_abort(struct scsi_cmnd *SCpnt)
 	c = i2o_dev->iop;
 	tid = i2o_dev->lct_data.tid;
 
-	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
-	if (m == I2O_QUEUE_EMPTY)
+	msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+	if (IS_ERR(msg))
 		return SCSI_MLQUEUE_HOST_BUSY;
 
-	writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
-	writel(I2O_CMD_SCSI_ABORT << 24 | HOST_TID << 12 | tid,
-	       &msg->u.head[1]);
-	writel(i2o_cntxt_list_get_ptr(c, SCpnt), &msg->body[0]);
+	msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0);
+	msg->u.head[1] =
+	    cpu_to_le32(I2O_CMD_SCSI_ABORT << 24 | HOST_TID << 12 | tid);
+	msg->body[0] = cpu_to_le32(i2o_cntxt_list_get_ptr(c, SCpnt));
 
-	if (i2o_msg_post_wait(c, m, I2O_TIMEOUT_SCSI_SCB_ABORT))
+	if (i2o_msg_post_wait(c, msg, I2O_TIMEOUT_SCSI_SCB_ABORT))
 		status = SUCCESS;
 
 	return status;
diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c
index 4eb53258842e..492167446936 100644
--- a/drivers/message/i2o/iop.c
+++ b/drivers/message/i2o/iop.c
@@ -32,7 +32,7 @@
 #include "core.h"
 
 #define OSM_NAME	"i2o"
-#define OSM_VERSION	"1.288"
+#define OSM_VERSION	"1.325"
 #define OSM_DESCRIPTION	"I2O subsystem"
 
 /* global I2O controller list */
@@ -47,27 +47,6 @@ static struct i2o_dma i2o_systab;
 static int i2o_hrt_get(struct i2o_controller *c);
 
 /**
- *	i2o_msg_nop - Returns a message which is not used
- *	@c: I2O controller from which the message was created
- *	@m: message which should be returned
- *
- *	If you fetch a message via i2o_msg_get, and can't use it, you must
- *	return the message with this function. Otherwise the message frame
- *	is lost.
- */
-void i2o_msg_nop(struct i2o_controller *c, u32 m)
-{
-	struct i2o_message __iomem *msg = i2o_msg_in_to_virt(c, m);
-
-	writel(THREE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
-	writel(I2O_CMD_UTIL_NOP << 24 | HOST_TID << 12 | ADAPTER_TID,
-	       &msg->u.head[1]);
-	writel(0, &msg->u.head[2]);
-	writel(0, &msg->u.head[3]);
-	i2o_msg_post(c, m);
-};
-
-/**
  *	i2o_msg_get_wait - obtain an I2O message from the IOP
  *	@c: I2O controller
  *	@msg: pointer to a I2O message pointer
@@ -81,22 +60,21 @@ void i2o_msg_nop(struct i2o_controller *c, u32 m)
  *	address from the read port (see the i2o spec). If no message is
  *	available returns I2O_QUEUE_EMPTY and msg is leaved untouched.
  */
-u32 i2o_msg_get_wait(struct i2o_controller *c,
-		     struct i2o_message __iomem ** msg, int wait)
+struct i2o_message *i2o_msg_get_wait(struct i2o_controller *c, int wait)
 {
 	unsigned long timeout = jiffies + wait * HZ;
-	u32 m;
+	struct i2o_message *msg;
 
-	while ((m = i2o_msg_get(c, msg)) == I2O_QUEUE_EMPTY) {
+	while (IS_ERR(msg = i2o_msg_get(c))) {
 		if (time_after(jiffies, timeout)) {
 			osm_debug("%s: Timeout waiting for message frame.\n",
 				  c->name);
-			return I2O_QUEUE_EMPTY;
+			return ERR_PTR(-ETIMEDOUT);
 		}
 		schedule_timeout_uninterruptible(1);
 	}
 
-	return m;
+	return msg;
 };
 
 #if BITS_PER_LONG == 64
@@ -301,8 +279,7 @@ struct i2o_device *i2o_iop_find_device(struct i2o_controller *c, u16 tid)
  */
 static int i2o_iop_quiesce(struct i2o_controller *c)
 {
-	struct i2o_message __iomem *msg;
-	u32 m;
+	struct i2o_message *msg;
 	i2o_status_block *sb = c->status_block.virt;
 	int rc;
 
@@ -313,16 +290,17 @@ static int i2o_iop_quiesce(struct i2o_controller *c)
 	    (sb->iop_state != ADAPTER_STATE_OPERATIONAL))
 		return 0;
 
-	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
-	if (m == I2O_QUEUE_EMPTY)
-		return -ETIMEDOUT;
+	msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+	if (IS_ERR(msg))
+		return PTR_ERR(msg);
 
-	writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
-	writel(I2O_CMD_SYS_QUIESCE << 24 | HOST_TID << 12 | ADAPTER_TID,
-	       &msg->u.head[1]);
+	msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0);
+	msg->u.head[1] =
+	    cpu_to_le32(I2O_CMD_SYS_QUIESCE << 24 | HOST_TID << 12 |
+			ADAPTER_TID);
 
 	/* Long timeout needed for quiesce if lots of devices */
-	if ((rc = i2o_msg_post_wait(c, m, 240)))
+	if ((rc = i2o_msg_post_wait(c, msg, 240)))
 		osm_info("%s: Unable to quiesce (status=%#x).\n", c->name, -rc);
 	else
 		osm_debug("%s: Quiesced.\n", c->name);
@@ -342,8 +320,7 @@ static int i2o_iop_quiesce(struct i2o_controller *c)
  */
 static int i2o_iop_enable(struct i2o_controller *c)
 {
-	struct i2o_message __iomem *msg;
-	u32 m;
+	struct i2o_message *msg;
 	i2o_status_block *sb = c->status_block.virt;
 	int rc;
 
@@ -353,16 +330,17 @@ static int i2o_iop_enable(struct i2o_controller *c)
 	if (sb->iop_state != ADAPTER_STATE_READY)
 		return -EINVAL;
 
-	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
-	if (m == I2O_QUEUE_EMPTY)
-		return -ETIMEDOUT;
+	msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+	if (IS_ERR(msg))
+		return PTR_ERR(msg);
 
-	writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
-	writel(I2O_CMD_SYS_ENABLE << 24 | HOST_TID << 12 | ADAPTER_TID,
-	       &msg->u.head[1]);
+	msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0);
+	msg->u.head[1] =
+	    cpu_to_le32(I2O_CMD_SYS_ENABLE << 24 | HOST_TID << 12 |
+			ADAPTER_TID);
 
 	/* How long of a timeout do we need? */
-	if ((rc = i2o_msg_post_wait(c, m, 240)))
+	if ((rc = i2o_msg_post_wait(c, msg, 240)))
 		osm_err("%s: Could not enable (status=%#x).\n", c->name, -rc);
 	else
 		osm_debug("%s: Enabled.\n", c->name);
@@ -413,22 +391,22 @@ static inline void i2o_iop_enable_all(void)
  */
 static int i2o_iop_clear(struct i2o_controller *c)
 {
-	struct i2o_message __iomem *msg;
-	u32 m;
+	struct i2o_message *msg;
 	int rc;
 
-	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
-	if (m == I2O_QUEUE_EMPTY)
-		return -ETIMEDOUT;
+	msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+	if (IS_ERR(msg))
+		return PTR_ERR(msg);
 
 	/* Quiesce all IOPs first */
 	i2o_iop_quiesce_all();
 
-	writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
-	writel(I2O_CMD_ADAPTER_CLEAR << 24 | HOST_TID << 12 | ADAPTER_TID,
-	       &msg->u.head[1]);
+	msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0);
+	msg->u.head[1] =
+	    cpu_to_le32(I2O_CMD_ADAPTER_CLEAR << 24 | HOST_TID << 12 |
+			ADAPTER_TID);
 
-	if ((rc = i2o_msg_post_wait(c, m, 30)))
+	if ((rc = i2o_msg_post_wait(c, msg, 30)))
 		osm_info("%s: Unable to clear (status=%#x).\n", c->name, -rc);
 	else
 		osm_debug("%s: Cleared.\n", c->name);
@@ -446,13 +424,13 @@ static int i2o_iop_clear(struct i2o_controller *c)
  *	Clear and (re)initialize IOP's outbound queue and post the message
  *	frames to the IOP.
  *
- *	Returns 0 on success or a negative errno code on failure.
+ *	Returns 0 on success or negative error code on failure.
  */
 static int i2o_iop_init_outbound_queue(struct i2o_controller *c)
 {
-	volatile u8 *status = c->status.virt;
 	u32 m;
-	struct i2o_message __iomem *msg;
+	volatile u8 *status = c->status.virt;
+	struct i2o_message *msg;
 	ulong timeout;
 	int i;
 
@@ -460,23 +438,24 @@ static int i2o_iop_init_outbound_queue(struct i2o_controller *c)
 
 	memset(c->status.virt, 0, 4);
 
-	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
-	if (m == I2O_QUEUE_EMPTY)
-		return -ETIMEDOUT;
-
-	writel(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6, &msg->u.head[0]);
-	writel(I2O_CMD_OUTBOUND_INIT << 24 | HOST_TID << 12 | ADAPTER_TID,
-	       &msg->u.head[1]);
-	writel(i2o_exec_driver.context, &msg->u.s.icntxt);
-	writel(0x00000000, &msg->u.s.tcntxt);
-	writel(PAGE_SIZE, &msg->body[0]);
+	msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+	if (IS_ERR(msg))
+		return PTR_ERR(msg);
+
+	msg->u.head[0] = cpu_to_le32(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6);
+	msg->u.head[1] =
+	    cpu_to_le32(I2O_CMD_OUTBOUND_INIT << 24 | HOST_TID << 12 |
+			ADAPTER_TID);
+	msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context);
+	msg->u.s.tcntxt = cpu_to_le32(0x00000000);
+	msg->body[0] = cpu_to_le32(PAGE_SIZE);
 	/* Outbound msg frame size in words and Initcode */
-	writel(I2O_OUTBOUND_MSG_FRAME_SIZE << 16 | 0x80, &msg->body[1]);
-	writel(0xd0000004, &msg->body[2]);
-	writel(i2o_dma_low(c->status.phys), &msg->body[3]);
-	writel(i2o_dma_high(c->status.phys), &msg->body[4]);
+	msg->body[1] = cpu_to_le32(I2O_OUTBOUND_MSG_FRAME_SIZE << 16 | 0x80);
+	msg->body[2] = cpu_to_le32(0xd0000004);
+	msg->body[3] = cpu_to_le32(i2o_dma_low(c->status.phys));
+	msg->body[4] = cpu_to_le32(i2o_dma_high(c->status.phys));
 
-	i2o_msg_post(c, m);
+	i2o_msg_post(c, msg);
 
 	timeout = jiffies + I2O_TIMEOUT_INIT_OUTBOUND_QUEUE * HZ;
 	while (*status <= I2O_CMD_IN_PROGRESS) {
@@ -511,34 +490,34 @@ static int i2o_iop_init_outbound_queue(struct i2o_controller *c)
 static int i2o_iop_reset(struct i2o_controller *c)
 {
 	volatile u8 *status = c->status.virt;
-	struct i2o_message __iomem *msg;
-	u32 m;
+	struct i2o_message *msg;
 	unsigned long timeout;
 	i2o_status_block *sb = c->status_block.virt;
 	int rc = 0;
 
 	osm_debug("%s: Resetting controller\n", c->name);
 
-	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
-	if (m == I2O_QUEUE_EMPTY)
-		return -ETIMEDOUT;
+	msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+	if (IS_ERR(msg))
+		return PTR_ERR(msg);
 
 	memset(c->status_block.virt, 0, 8);
 
 	/* Quiesce all IOPs first */
 	i2o_iop_quiesce_all();
 
-	writel(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
-	writel(I2O_CMD_ADAPTER_RESET << 24 | HOST_TID << 12 | ADAPTER_TID,
-	       &msg->u.head[1]);
-	writel(i2o_exec_driver.context, &msg->u.s.icntxt);
-	writel(0, &msg->u.s.tcntxt);	//FIXME: use reasonable transaction context
-	writel(0, &msg->body[0]);
-	writel(0, &msg->body[1]);
-	writel(i2o_dma_low(c->status.phys), &msg->body[2]);
-	writel(i2o_dma_high(c->status.phys), &msg->body[3]);
+	msg->u.head[0] = cpu_to_le32(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_0);
+	msg->u.head[1] =
+	    cpu_to_le32(I2O_CMD_ADAPTER_RESET << 24 | HOST_TID << 12 |
+			ADAPTER_TID);
+	msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context);
+	msg->u.s.tcntxt = cpu_to_le32(0x00000000);
+	msg->body[0] = cpu_to_le32(0x00000000);
+	msg->body[1] = cpu_to_le32(0x00000000);
+	msg->body[2] = cpu_to_le32(i2o_dma_low(c->status.phys));
+	msg->body[3] = cpu_to_le32(i2o_dma_high(c->status.phys));
 
-	i2o_msg_post(c, m);
+	i2o_msg_post(c, msg);
 
 	/* Wait for a reply */
 	timeout = jiffies + I2O_TIMEOUT_RESET * HZ;
@@ -567,18 +546,15 @@ static int i2o_iop_reset(struct i2o_controller *c)
 		osm_debug("%s: Reset in progress, waiting for reboot...\n",
 			  c->name);
 
-		m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_RESET);
-		while (m == I2O_QUEUE_EMPTY) {
+		while (IS_ERR(msg = i2o_msg_get_wait(c, I2O_TIMEOUT_RESET))) {
 			if (time_after(jiffies, timeout)) {
 				osm_err("%s: IOP reset timeout.\n", c->name);
-				rc = -ETIMEDOUT;
+				rc = PTR_ERR(msg);
 				goto exit;
 			}
 			schedule_timeout_uninterruptible(1);
-
-			m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_RESET);
 		}
-		i2o_msg_nop(c, m);
+		i2o_msg_nop(c, msg);
 
 		/* from here all quiesce commands are safe */
 		c->no_quiesce = 0;
@@ -686,8 +662,7 @@ static int i2o_iop_activate(struct i2o_controller *c)
  */
 static int i2o_iop_systab_set(struct i2o_controller *c)
 {
-	struct i2o_message __iomem *msg;
-	u32 m;
+	struct i2o_message *msg;
 	i2o_status_block *sb = c->status_block.virt;
 	struct device *dev = &c->pdev->dev;
 	struct resource *root;
@@ -735,41 +710,38 @@ static int i2o_iop_systab_set(struct i2o_controller *c)
 		}
 	}
 
-	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
-	if (m == I2O_QUEUE_EMPTY)
-		return -ETIMEDOUT;
+	msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+	if (IS_ERR(msg))
+		return PTR_ERR(msg);
 
 	i2o_systab.phys = dma_map_single(dev, i2o_systab.virt, i2o_systab.len,
 					 PCI_DMA_TODEVICE);
 	if (!i2o_systab.phys) {
-		i2o_msg_nop(c, m);
+		i2o_msg_nop(c, msg);
 		return -ENOMEM;
 	}
 
-	writel(I2O_MESSAGE_SIZE(12) | SGL_OFFSET_6, &msg->u.head[0]);
-	writel(I2O_CMD_SYS_TAB_SET << 24 | HOST_TID << 12 | ADAPTER_TID,
-	       &msg->u.head[1]);
+	msg->u.head[0] = cpu_to_le32(I2O_MESSAGE_SIZE(12) | SGL_OFFSET_6);
+	msg->u.head[1] =
+	    cpu_to_le32(I2O_CMD_SYS_TAB_SET << 24 | HOST_TID << 12 |
+			ADAPTER_TID);
 
 	/*
 	 * Provide three SGL-elements:
 	 * System table (SysTab), Private memory space declaration and
 	 * Private i/o space declaration
-	 *
-	 * FIXME: is this still true?
-	 * Nasty one here. We can't use dma_alloc_coherent to send the
-	 * same table to everyone. We have to go remap it for them all
 	 */
 
-	writel(c->unit + 2, &msg->body[0]);
-	writel(0, &msg->body[1]);
-	writel(0x54000000 | i2o_systab.len, &msg->body[2]);
-	writel(i2o_systab.phys, &msg->body[3]);
-	writel(0x54000000 | sb->current_mem_size, &msg->body[4]);
-	writel(sb->current_mem_base, &msg->body[5]);
-	writel(0xd4000000 | sb->current_io_size, &msg->body[6]);
-	writel(sb->current_io_base, &msg->body[6]);
+	msg->body[0] = cpu_to_le32(c->unit + 2);
+	msg->body[1] = cpu_to_le32(0x00000000);
+	msg->body[2] = cpu_to_le32(0x54000000 | i2o_systab.len);
+	msg->body[3] = cpu_to_le32(i2o_systab.phys);
+	msg->body[4] = cpu_to_le32(0x54000000 | sb->current_mem_size);
+	msg->body[5] = cpu_to_le32(sb->current_mem_base);
+	msg->body[6] = cpu_to_le32(0xd4000000 | sb->current_io_size);
+	msg->body[6] = cpu_to_le32(sb->current_io_base);
 
-	rc = i2o_msg_post_wait(c, m, 120);
+	rc = i2o_msg_post_wait(c, msg, 120);
 
 	dma_unmap_single(dev, i2o_systab.phys, i2o_systab.len,
 			 PCI_DMA_TODEVICE);
@@ -780,8 +752,6 @@ static int i2o_iop_systab_set(struct i2o_controller *c)
 	else
 		osm_debug("%s: SysTab set.\n", c->name);
 
-	i2o_status_get(c);	// Entered READY state
-
 	return rc;
 }
 
@@ -791,7 +761,7 @@ static int i2o_iop_systab_set(struct i2o_controller *c)
  *
  *	Send the system table and enable the I2O controller.
  *
- *	Returns 0 on success or negativer error code on failure.
+ *	Returns 0 on success or negative error code on failure.
  */
 static int i2o_iop_online(struct i2o_controller *c)
 {
@@ -830,7 +800,6 @@ void i2o_iop_remove(struct i2o_controller *c)
 	list_for_each_entry_safe(dev, tmp, &c->devices, list)
 	    i2o_device_remove(dev);
 
-	class_device_unregister(c->classdev);
 	device_del(&c->device);
 
 	/* Ask the IOP to switch to RESET state */
@@ -869,12 +838,11 @@ static int i2o_systab_build(void)
 	i2o_systab.len = sizeof(struct i2o_sys_tbl) + num_controllers *
 	    sizeof(struct i2o_sys_tbl_entry);
 
-	systab = i2o_systab.virt = kmalloc(i2o_systab.len, GFP_KERNEL);
+	systab = i2o_systab.virt = kzalloc(i2o_systab.len, GFP_KERNEL);
 	if (!systab) {
 		osm_err("unable to allocate memory for System Table\n");
 		return -ENOMEM;
 	}
-	memset(systab, 0, i2o_systab.len);
 
 	systab->version = I2OVERSION;
 	systab->change_ind = change_ind + 1;
@@ -952,30 +920,30 @@ static int i2o_parse_hrt(struct i2o_controller *c)
  */
 int i2o_status_get(struct i2o_controller *c)
 {
-	struct i2o_message __iomem *msg;
-	u32 m;
+	struct i2o_message *msg;
 	volatile u8 *status_block;
 	unsigned long timeout;
 
 	status_block = (u8 *) c->status_block.virt;
 	memset(c->status_block.virt, 0, sizeof(i2o_status_block));
 
-	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
-	if (m == I2O_QUEUE_EMPTY)
-		return -ETIMEDOUT;
+	msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+	if (IS_ERR(msg))
+		return PTR_ERR(msg);
 
-	writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
-	writel(I2O_CMD_STATUS_GET << 24 | HOST_TID << 12 | ADAPTER_TID,
-	       &msg->u.head[1]);
-	writel(i2o_exec_driver.context, &msg->u.s.icntxt);
-	writel(0, &msg->u.s.tcntxt);	// FIXME: use resonable transaction context
-	writel(0, &msg->body[0]);
-	writel(0, &msg->body[1]);
-	writel(i2o_dma_low(c->status_block.phys), &msg->body[2]);
-	writel(i2o_dma_high(c->status_block.phys), &msg->body[3]);
-	writel(sizeof(i2o_status_block), &msg->body[4]);	/* always 88 bytes */
+	msg->u.head[0] = cpu_to_le32(NINE_WORD_MSG_SIZE | SGL_OFFSET_0);
+	msg->u.head[1] =
+	    cpu_to_le32(I2O_CMD_STATUS_GET << 24 | HOST_TID << 12 |
+			ADAPTER_TID);
+	msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context);
+	msg->u.s.tcntxt = cpu_to_le32(0x00000000);
+	msg->body[0] = cpu_to_le32(0x00000000);
+	msg->body[1] = cpu_to_le32(0x00000000);
+	msg->body[2] = cpu_to_le32(i2o_dma_low(c->status_block.phys));
+	msg->body[3] = cpu_to_le32(i2o_dma_high(c->status_block.phys));
+	msg->body[4] = cpu_to_le32(sizeof(i2o_status_block));	/* always 88 bytes */
 
-	i2o_msg_post(c, m);
+	i2o_msg_post(c, msg);
 
 	/* Wait for a reply */
 	timeout = jiffies + I2O_TIMEOUT_STATUS_GET * HZ;
@@ -1002,7 +970,7 @@ int i2o_status_get(struct i2o_controller *c)
  *	The HRT contains information about possible hidden devices but is
  *	mostly useless to us.
  *
- *	Returns 0 on success or negativer error code on failure.
+ *	Returns 0 on success or negative error code on failure.
  */
 static int i2o_hrt_get(struct i2o_controller *c)
 {
@@ -1013,20 +981,20 @@ static int i2o_hrt_get(struct i2o_controller *c)
 	struct device *dev = &c->pdev->dev;
 
 	for (i = 0; i < I2O_HRT_GET_TRIES; i++) {
-		struct i2o_message __iomem *msg;
-		u32 m;
+		struct i2o_message *msg;
 
-		m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
-		if (m == I2O_QUEUE_EMPTY)
-			return -ETIMEDOUT;
+		msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+		if (IS_ERR(msg))
+			return PTR_ERR(msg);
 
-		writel(SIX_WORD_MSG_SIZE | SGL_OFFSET_4, &msg->u.head[0]);
-		writel(I2O_CMD_HRT_GET << 24 | HOST_TID << 12 | ADAPTER_TID,
-		       &msg->u.head[1]);
-		writel(0xd0000000 | c->hrt.len, &msg->body[0]);
-		writel(c->hrt.phys, &msg->body[1]);
+		msg->u.head[0] = cpu_to_le32(SIX_WORD_MSG_SIZE | SGL_OFFSET_4);
+		msg->u.head[1] =
+		    cpu_to_le32(I2O_CMD_HRT_GET << 24 | HOST_TID << 12 |
+				ADAPTER_TID);
+		msg->body[0] = cpu_to_le32(0xd0000000 | c->hrt.len);
+		msg->body[1] = cpu_to_le32(c->hrt.phys);
 
-		rc = i2o_msg_post_wait_mem(c, m, 20, &c->hrt);
+		rc = i2o_msg_post_wait_mem(c, msg, 20, &c->hrt);
 
 		if (rc < 0) {
 			osm_err("%s: Unable to get HRT (status=%#x)\n", c->name,
@@ -1051,15 +1019,6 @@ static int i2o_hrt_get(struct i2o_controller *c)
 }
 
 /**
- *	i2o_iop_free - Free the i2o_controller struct
- *	@c: I2O controller to free
- */
-void i2o_iop_free(struct i2o_controller *c)
-{
-	kfree(c);
-};
-
-/**
  *	i2o_iop_release - release the memory for a I2O controller
  *	@dev: I2O controller which should be released
  *
@@ -1073,14 +1032,11 @@ static void i2o_iop_release(struct device *dev)
 	i2o_iop_free(c);
 };
 
-/* I2O controller class */
-static struct class *i2o_controller_class;
-
 /**
  *	i2o_iop_alloc - Allocate and initialize a i2o_controller struct
  *
  *	Allocate the necessary memory for a i2o_controller struct and
- *	initialize the lists.
+ *	initialize the lists and message mempool.
  *
  *	Returns a pointer to the I2O controller or a negative error code on
  *	failure.
@@ -1089,20 +1045,29 @@ struct i2o_controller *i2o_iop_alloc(void)
 {
 	static int unit = 0;	/* 0 and 1 are NULL IOP and Local Host */
 	struct i2o_controller *c;
+	char poolname[32];
 
-	c = kmalloc(sizeof(*c), GFP_KERNEL);
+	c = kzalloc(sizeof(*c), GFP_KERNEL);
 	if (!c) {
 		osm_err("i2o: Insufficient memory to allocate a I2O controller."
 			"\n");
 		return ERR_PTR(-ENOMEM);
 	}
-	memset(c, 0, sizeof(*c));
+
+	c->unit = unit++;
+	sprintf(c->name, "iop%d", c->unit);
+
+	snprintf(poolname, sizeof(poolname), "i2o_%s_msg_inpool", c->name);
+	if (i2o_pool_alloc
+	    (&c->in_msg, poolname, I2O_INBOUND_MSG_FRAME_SIZE * 4,
+	     I2O_MSG_INPOOL_MIN)) {
+		kfree(c);
+		return ERR_PTR(-ENOMEM);
+	};
 
 	INIT_LIST_HEAD(&c->devices);
 	spin_lock_init(&c->lock);
 	init_MUTEX(&c->lct_lock);
-	c->unit = unit++;
-	sprintf(c->name, "iop%d", c->unit);
 
 	device_initialize(&c->device);
 
@@ -1137,36 +1102,29 @@ int i2o_iop_add(struct i2o_controller *c)
 		goto iop_reset;
 	}
 
-	c->classdev = class_device_create(i2o_controller_class, NULL, MKDEV(0,0),
-			&c->device, "iop%d", c->unit);
-	if (IS_ERR(c->classdev)) {
-		osm_err("%s: could not add controller class\n", c->name);
-		goto device_del;
-	}
-
 	osm_info("%s: Activating I2O controller...\n", c->name);
 	osm_info("%s: This may take a few minutes if there are many devices\n",
 		 c->name);
 
 	if ((rc = i2o_iop_activate(c))) {
 		osm_err("%s: could not activate controller\n", c->name);
-		goto class_del;
+		goto device_del;
 	}
 
 	osm_debug("%s: building sys table...\n", c->name);
 
 	if ((rc = i2o_systab_build()))
-		goto class_del;
+		goto device_del;
 
 	osm_debug("%s: online controller...\n", c->name);
 
 	if ((rc = i2o_iop_online(c)))
-		goto class_del;
+		goto device_del;
 
 	osm_debug("%s: getting LCT...\n", c->name);
 
 	if ((rc = i2o_exec_lct_get(c)))
-		goto class_del;
+		goto device_del;
 
 	list_add(&c->list, &i2o_controllers);
 
@@ -1176,9 +1134,6 @@ int i2o_iop_add(struct i2o_controller *c)
 
 	return 0;
 
-      class_del:
-	class_device_unregister(c->classdev);
-
       device_del:
 	device_del(&c->device);
 
@@ -1199,28 +1154,27 @@ int i2o_iop_add(struct i2o_controller *c)
  *	is waited for, or expected. If you do not want further notifications,
  *	call the i2o_event_register again with a evt_mask of 0.
  *
- *	Returns 0 on success or -ETIMEDOUT if no message could be fetched for
- *	sending the request.
+ *	Returns 0 on success or negative error code on failure.
  */
 int i2o_event_register(struct i2o_device *dev, struct i2o_driver *drv,
 		       int tcntxt, u32 evt_mask)
 {
 	struct i2o_controller *c = dev->iop;
-	struct i2o_message __iomem *msg;
-	u32 m;
+	struct i2o_message *msg;
 
-	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
-	if (m == I2O_QUEUE_EMPTY)
-		return -ETIMEDOUT;
+	msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+	if (IS_ERR(msg))
+		return PTR_ERR(msg);
 
-	writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
-	writel(I2O_CMD_UTIL_EVT_REGISTER << 24 | HOST_TID << 12 | dev->lct_data.
-	       tid, &msg->u.head[1]);
-	writel(drv->context, &msg->u.s.icntxt);
-	writel(tcntxt, &msg->u.s.tcntxt);
-	writel(evt_mask, &msg->body[0]);
+	msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0);
+	msg->u.head[1] =
+	    cpu_to_le32(I2O_CMD_UTIL_EVT_REGISTER << 24 | HOST_TID << 12 | dev->
+			lct_data.tid);
+	msg->u.s.icntxt = cpu_to_le32(drv->context);
+	msg->u.s.tcntxt = cpu_to_le32(tcntxt);
+	msg->body[0] = cpu_to_le32(evt_mask);
 
-	i2o_msg_post(c, m);
+	i2o_msg_post(c, msg);
 
 	return 0;
 };
@@ -1239,14 +1193,8 @@ static int __init i2o_iop_init(void)
 
 	printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n");
 
-	i2o_controller_class = class_create(THIS_MODULE, "i2o_controller");
-	if (IS_ERR(i2o_controller_class)) {
-		osm_err("can't register class i2o_controller\n");
-		goto exit;
-	}
-
 	if ((rc = i2o_driver_init()))
-		goto class_exit;
+		goto exit;
 
 	if ((rc = i2o_exec_init()))
 		goto driver_exit;
@@ -1262,9 +1210,6 @@ static int __init i2o_iop_init(void)
       driver_exit:
 	i2o_driver_exit();
 
-      class_exit:
-	class_destroy(i2o_controller_class);
-
       exit:
 	return rc;
 }
@@ -1279,7 +1224,6 @@ static void __exit i2o_iop_exit(void)
 	i2o_pci_exit();
 	i2o_exec_exit();
 	i2o_driver_exit();
-	class_destroy(i2o_controller_class);
 };
 
 module_init(i2o_iop_init);
diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c
index ee7075fa1ec3..c5b656cdea7c 100644
--- a/drivers/message/i2o/pci.c
+++ b/drivers/message/i2o/pci.c
@@ -339,7 +339,7 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev,
 		       pci_name(pdev));
 
 	c->pdev = pdev;
-	c->device.parent = get_device(&pdev->dev);
+	c->device.parent = &pdev->dev;
 
 	/* Cards that fall apart if you hit them with large I/O loads... */
 	if (pdev->vendor == PCI_VENDOR_ID_NCR && pdev->device == 0x0630) {
@@ -410,8 +410,6 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev,
 	if ((rc = i2o_iop_add(c)))
 		goto uninstall;
 
-	get_device(&c->device);
-
 	if (i960)
 		pci_write_config_word(i960, 0x42, 0x03ff);
 
@@ -424,7 +422,6 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev,
 	i2o_pci_free(c);
 
       free_controller:
-	put_device(c->device.parent);
 	i2o_iop_free(c);
 
       disable:
@@ -454,7 +451,6 @@ static void __devexit i2o_pci_remove(struct pci_dev *pdev)
 
 	printk(KERN_INFO "%s: Controller removed.\n", c->name);
 
-	put_device(c->device.parent);
 	put_device(&c->device);
 };
 
@@ -483,4 +479,5 @@ void __exit i2o_pci_exit(void)
 {
 	pci_unregister_driver(&i2o_pci_driver);
 };
+
 MODULE_DEVICE_TABLE(pci, i2o_pci_ids);
diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c
index abcf19116d70..8e380c14bf65 100644
--- a/drivers/mmc/mmc_block.c
+++ b/drivers/mmc/mmc_block.c
@@ -263,7 +263,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
 			 */
 			add_disk_randomness(req->rq_disk);
 			blkdev_dequeue_request(req);
-			end_that_request_last(req);
+			end_that_request_last(req, 1);
 		}
 		spin_unlock_irq(&md->lock);
 	} while (ret);
@@ -289,7 +289,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
 
 	add_disk_randomness(req->rq_disk);
 	blkdev_dequeue_request(req);
-	end_that_request_last(req);
+	end_that_request_last(req, 0);
 	spin_unlock_irq(&md->lock);
 
 	return 0;
diff --git a/drivers/mmc/mmc_sysfs.c b/drivers/mmc/mmc_sysfs.c
index 3f4a66ca9555..ec701667abfc 100644
--- a/drivers/mmc/mmc_sysfs.c
+++ b/drivers/mmc/mmc_sysfs.c
@@ -80,7 +80,7 @@ static int mmc_bus_match(struct device *dev, struct device_driver *drv)
 }
 
 static int
-mmc_bus_hotplug(struct device *dev, char **envp, int num_envp, char *buf,
+mmc_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf,
 		int buf_size)
 {
 	struct mmc_card *card = dev_to_mmc_card(dev);
@@ -140,7 +140,7 @@ static struct bus_type mmc_bus_type = {
 	.name		= "mmc",
 	.dev_attrs	= mmc_dev_attrs,
 	.match		= mmc_bus_match,
-	.hotplug	= mmc_bus_hotplug,
+	.uevent		= mmc_bus_uevent,
 	.suspend	= mmc_bus_suspend,
 	.resume		= mmc_bus_resume,
 };
diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c
index af24216a0626..f0f8916da7ad 100644
--- a/drivers/mtd/maps/pcmciamtd.c
+++ b/drivers/mtd/maps/pcmciamtd.c
@@ -66,9 +66,6 @@ struct pcmciamtd_dev {
 };
 
 
-static dev_info_t dev_info = "pcmciamtd";
-static dev_link_t *dev_list;
-
 /* Module parameters */
 
 /* 2 = do 16-bit transfers, 1 = do 8-bit transfers */
@@ -691,55 +688,21 @@ static void pcmciamtd_config(dev_link_t *link)
 }
 
 
-/* The card status event handler.  Mostly, this schedules other
- * stuff to run after an event is received.  A CARD_REMOVAL event
- * also sets some flags to discourage the driver from trying
- * to talk to the card any more.
- */
+static int pcmciamtd_suspend(struct pcmcia_device *dev)
+{
+	DEBUG(2, "EVENT_PM_RESUME");
+
+	/* get_lock(link); */
+
+	return 0;
+}
 
-static int pcmciamtd_event(event_t event, int priority,
-			event_callback_args_t *args)
+static int pcmciamtd_resume(struct pcmcia_device *dev)
 {
-	dev_link_t *link = args->client_data;
-
-	DEBUG(1, "event=0x%06x", event);
-	switch (event) {
-	case CS_EVENT_CARD_REMOVAL:
-		DEBUG(2, "EVENT_CARD_REMOVAL");
-		link->state &= ~DEV_PRESENT;
-		if (link->state & DEV_CONFIG) {
-			struct pcmciamtd_dev *dev = link->priv;
-			if(dev->mtd_info) {
-				del_mtd_device(dev->mtd_info);
-				info("mtd%d: Removed", dev->mtd_info->index);
-			}
-			pcmciamtd_release(link);
-		}
-		break;
-	case CS_EVENT_CARD_INSERTION:
-		DEBUG(2, "EVENT_CARD_INSERTION");
-		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-		pcmciamtd_config(link);
-		break;
-	case CS_EVENT_PM_SUSPEND:
-		DEBUG(2, "EVENT_PM_SUSPEND");
-		link->state |= DEV_SUSPEND;
-		/* Fall through... */
-	case CS_EVENT_RESET_PHYSICAL:
-		DEBUG(2, "EVENT_RESET_PHYSICAL");
-		/* get_lock(link); */
-		break;
-	case CS_EVENT_PM_RESUME:
-		DEBUG(2, "EVENT_PM_RESUME");
-		link->state &= ~DEV_SUSPEND;
-		/* Fall through... */
-	case CS_EVENT_CARD_RESET:
-		DEBUG(2, "EVENT_CARD_RESET");
-		/* free_lock(link); */
-		break;
-	default:
-		DEBUG(2, "Unknown event %d", event);
-	}
+	DEBUG(2, "EVENT_PM_SUSPEND");
+
+	/* free_lock(link); */
+
 	return 0;
 }
 
@@ -750,23 +713,21 @@ static int pcmciamtd_event(event_t event, int priority,
  * when the device is released.
  */
 
-static void pcmciamtd_detach(dev_link_t *link)
+static void pcmciamtd_detach(struct pcmcia_device *p_dev)
 {
+	dev_link_t *link = dev_to_instance(p_dev);
+
 	DEBUG(3, "link=0x%p", link);
 
 	if(link->state & DEV_CONFIG) {
-		pcmciamtd_release(link);
-	}
+		struct pcmciamtd_dev *dev = link->priv;
+		if(dev->mtd_info) {
+			del_mtd_device(dev->mtd_info);
+			info("mtd%d: Removed", dev->mtd_info->index);
+		}
 
-	if (link->handle) {
-		int ret;
-		DEBUG(2, "Deregistering with card services");
-		ret = pcmcia_deregister_client(link->handle);
-		if (ret != CS_SUCCESS)
-			cs_error(link->handle, DeregisterClient, ret);
+		pcmciamtd_release(link);
 	}
-
-	link->state |= DEV_STALE_LINK;
 }
 
 
@@ -775,16 +736,14 @@ static void pcmciamtd_detach(dev_link_t *link)
  * with Card Services.
  */
 
-static dev_link_t *pcmciamtd_attach(void)
+static int pcmciamtd_attach(struct pcmcia_device *p_dev)
 {
 	struct pcmciamtd_dev *dev;
 	dev_link_t *link;
-	client_reg_t client_reg;
-	int ret;
 
 	/* Create new memory card device */
 	dev = kmalloc(sizeof(*dev), GFP_KERNEL);
-	if (!dev) return NULL;
+	if (!dev) return -ENOMEM;
 	DEBUG(1, "dev=0x%p", dev);
 
 	memset(dev, 0, sizeof(*dev));
@@ -794,22 +753,14 @@ static dev_link_t *pcmciamtd_attach(void)
 	link->conf.Attributes = 0;
 	link->conf.IntType = INT_MEMORY;
 
-	link->next = dev_list;
-	dev_list = link;
-
-	/* Register with Card Services */
-	client_reg.dev_info = &dev_info;
-	client_reg.Version = 0x0210;
-	client_reg.event_callback_args.client_data = link;
-	DEBUG(2, "Calling RegisterClient");
-	ret = pcmcia_register_client(&link->handle, &client_reg);
-	if (ret != 0) {
-		cs_error(link->handle, RegisterClient, ret);
-		pcmciamtd_detach(link);
-		return NULL;
-	}
-	DEBUG(2, "link = %p", link);
-	return link;
+	link->next = NULL;
+	link->handle = p_dev;
+	p_dev->instance = link;
+
+	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+	pcmciamtd_config(link);
+
+	return 0;
 }
 
 static struct pcmcia_device_id pcmciamtd_ids[] = {
@@ -843,11 +794,12 @@ static struct pcmcia_driver pcmciamtd_driver = {
 	.drv		= {
 		.name	= "pcmciamtd"
 	},
-	.attach		= pcmciamtd_attach,
-	.event		= pcmciamtd_event,
-	.detach		= pcmciamtd_detach,
+	.probe		= pcmciamtd_attach,
+	.remove		= pcmciamtd_detach,
 	.owner		= THIS_MODULE,
 	.id_table	= pcmciamtd_ids,
+	.suspend	= pcmciamtd_suspend,
+	.resume		= pcmciamtd_resume,
 };
 
 
@@ -875,7 +827,6 @@ static void __exit exit_pcmciamtd(void)
 {
 	DEBUG(1, DRIVER_DESC " unloading");
 	pcmcia_unregister_driver(&pcmciamtd_driver);
-	BUG_ON(dev_list != NULL);
 }
 
 module_init(init_pcmciamtd);
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index 30bee11c48bd..d2102a27d307 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -586,16 +586,16 @@ struct rtl8139_private {
 	dma_addr_t tx_bufs_dma;
 	signed char phys[4];		/* MII device addresses. */
 	char twistie, twist_row, twist_col;	/* Twister tune state. */
-	unsigned int default_port:4;	/* Last dev->if_port value. */
+	unsigned int default_port : 4;	/* Last dev->if_port value. */
+	unsigned int have_thread : 1;
 	spinlock_t lock;
 	spinlock_t rx_lock;
 	chip_t chipset;
-	pid_t thr_pid;
-	wait_queue_head_t thr_wait;
-	struct completion thr_exited;
 	u32 rx_config;
 	struct rtl_extra_stats xstats;
-	int time_to_die;
+
+	struct work_struct thread;
+
 	struct mii_if_info mii;
 	unsigned int regs_len;
 	unsigned long fifo_copy_timeout;
@@ -620,7 +620,7 @@ static int rtl8139_open (struct net_device *dev);
 static int mdio_read (struct net_device *dev, int phy_id, int location);
 static void mdio_write (struct net_device *dev, int phy_id, int location,
 			int val);
-static void rtl8139_start_thread(struct net_device *dev);
+static void rtl8139_start_thread(struct rtl8139_private *tp);
 static void rtl8139_tx_timeout (struct net_device *dev);
 static void rtl8139_init_ring (struct net_device *dev);
 static int rtl8139_start_xmit (struct sk_buff *skb,
@@ -637,6 +637,7 @@ static struct net_device_stats *rtl8139_get_stats (struct net_device *dev);
 static void rtl8139_set_rx_mode (struct net_device *dev);
 static void __set_rx_mode (struct net_device *dev);
 static void rtl8139_hw_start (struct net_device *dev);
+static void rtl8139_thread (void *_data);
 static struct ethtool_ops rtl8139_ethtool_ops;
 
 /* write MMIO register, with flush */
@@ -1007,8 +1008,7 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
 		(debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1));
 	spin_lock_init (&tp->lock);
 	spin_lock_init (&tp->rx_lock);
-	init_waitqueue_head (&tp->thr_wait);
-	init_completion (&tp->thr_exited);
+	INIT_WORK(&tp->thread, rtl8139_thread, dev);
 	tp->mii.dev = dev;
 	tp->mii.mdio_read = mdio_read;
 	tp->mii.mdio_write = mdio_write;
@@ -1345,7 +1345,7 @@ static int rtl8139_open (struct net_device *dev)
 			dev->irq, RTL_R8 (MediaStatus),
 			tp->mii.full_duplex ? "full" : "half");
 
-	rtl8139_start_thread(dev);
+	rtl8139_start_thread(tp);
 
 	return 0;
 }
@@ -1594,55 +1594,43 @@ static inline void rtl8139_thread_iter (struct net_device *dev,
 		 RTL_R8 (Config1));
 }
 
-static int rtl8139_thread (void *data)
+static void rtl8139_thread (void *_data)
 {
-	struct net_device *dev = data;
+	struct net_device *dev = _data;
 	struct rtl8139_private *tp = netdev_priv(dev);
-	unsigned long timeout;
-
-	daemonize("%s", dev->name);
-	allow_signal(SIGTERM);
-
-	while (1) {
-		timeout = next_tick;
-		do {
-			timeout = interruptible_sleep_on_timeout (&tp->thr_wait, timeout);
-			/* make swsusp happy with our thread */
-			try_to_freeze();
-		} while (!signal_pending (current) && (timeout > 0));
-
-		if (signal_pending (current)) {
-			flush_signals(current);
-		}
+	unsigned long thr_delay;
 
-		if (tp->time_to_die)
-			break;
-
-		if (rtnl_lock_interruptible ())
-			break;
+	if (rtnl_shlock_nowait() == 0) {
 		rtl8139_thread_iter (dev, tp, tp->mmio_addr);
 		rtnl_unlock ();
+
+		thr_delay = next_tick;
+	} else {
+		/* unlikely race.  mitigate with fast poll. */
+		thr_delay = HZ / 2;
 	}
 
-	complete_and_exit (&tp->thr_exited, 0);
+	schedule_delayed_work(&tp->thread, thr_delay);
 }
 
-static void rtl8139_start_thread(struct net_device *dev)
+static void rtl8139_start_thread(struct rtl8139_private *tp)
 {
-	struct rtl8139_private *tp = netdev_priv(dev);
-
-	tp->thr_pid = -1;
 	tp->twistie = 0;
-	tp->time_to_die = 0;
 	if (tp->chipset == CH_8139_K)
 		tp->twistie = 1;
 	else if (tp->drv_flags & HAS_LNK_CHNG)
 		return;
 
-	tp->thr_pid = kernel_thread(rtl8139_thread, dev, CLONE_FS|CLONE_FILES);
-	if (tp->thr_pid < 0) {
-		printk (KERN_WARNING "%s: unable to start kernel thread\n",
-			dev->name);
+	tp->have_thread = 1;
+
+	schedule_delayed_work(&tp->thread, next_tick);
+}
+
+static void rtl8139_stop_thread(struct rtl8139_private *tp)
+{
+	if (tp->have_thread) {
+		cancel_rearming_delayed_work(&tp->thread);
+		tp->have_thread = 0;
 	}
 }
 
@@ -2224,22 +2212,12 @@ static int rtl8139_close (struct net_device *dev)
 {
 	struct rtl8139_private *tp = netdev_priv(dev);
 	void __iomem *ioaddr = tp->mmio_addr;
-	int ret = 0;
 	unsigned long flags;
 
 	netif_stop_queue (dev);
 
-	if (tp->thr_pid >= 0) {
-		tp->time_to_die = 1;
-		wmb();
-		ret = kill_proc (tp->thr_pid, SIGTERM, 1);
-		if (ret) {
-			printk (KERN_ERR "%s: unable to signal thread\n", dev->name);
-			return ret;
-		}
-		wait_for_completion (&tp->thr_exited);
-	}
-	
+	rtl8139_stop_thread(tp);
+
 	if (netif_msg_ifdown(tp))
 		printk(KERN_DEBUG "%s: Shutting down ethercard, status was 0x%4.4x.\n",
 			dev->name, RTL_R16 (IntrStatus));
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index ebd7313d7fc1..e2fa29b612cd 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1901,6 +1901,8 @@ config E1000_NAPI
 
 	  If in doubt, say N.
 
+source "drivers/net/ixp2000/Kconfig"
+
 config MYRI_SBUS
 	tristate "MyriCOM Gigabit Ethernet support"
 	depends on SBUS
@@ -2008,7 +2010,18 @@ config SKGE
 
 	  It does not support the link failover and network management 
 	  features that "portable" vendor supplied sk98lin driver does.
-	
+
+
+config SKY2
+	tristate "SysKonnect Yukon2 support (EXPERIMENTAL)"
+	depends on PCI && EXPERIMENTAL
+	select CRC32
+	---help---
+	  This driver support the Marvell Yukon 2 Gigabit Ethernet adapter.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called sky2.  This is recommended.
+
 config SK98LIN
 	tristate "Marvell Yukon Chipset / SysKonnect SK-98xx Support"
 	depends on PCI
@@ -2120,7 +2133,7 @@ config BNX2
 
 config SPIDER_NET
 	tristate "Spider Gigabit Ethernet driver"
-	depends on PCI && PPC_BPA
+	depends on PCI && PPC_CELL
 	help
 	  This driver supports the Gigabit Ethernet chips present on the
 	  Cell Processor-Based Blades from IBM.
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 4cffd34442aa..b74a7cb5bae6 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -13,7 +13,10 @@ obj-$(CONFIG_CHELSIO_T1) += chelsio/
 obj-$(CONFIG_BONDING) += bonding/
 obj-$(CONFIG_GIANFAR) += gianfar_driver.o
 
-gianfar_driver-objs := gianfar.o gianfar_ethtool.o gianfar_mii.o
+gianfar_driver-objs := gianfar.o \
+		gianfar_ethtool.o \
+		gianfar_mii.o \
+		gianfar_sysfs.o
 
 #
 # link order important here
@@ -59,6 +62,7 @@ spidernet-y += spider_net.o spider_net_ethtool.o sungem_phy.o
 obj-$(CONFIG_SPIDER_NET) += spidernet.o
 obj-$(CONFIG_TC35815) += tc35815.o
 obj-$(CONFIG_SKGE) += skge.o
+obj-$(CONFIG_SKY2) += sky2.o
 obj-$(CONFIG_SK98LIN) += sk98lin/
 obj-$(CONFIG_SKFP) += skfp/
 obj-$(CONFIG_VIA_RHINE) += via-rhine.o
@@ -202,6 +206,7 @@ obj-$(CONFIG_NET_TULIP) += tulip/
 obj-$(CONFIG_HAMRADIO) += hamradio/
 obj-$(CONFIG_IRDA) += irda/
 obj-$(CONFIG_ETRAX_ETHERNET) += cris/
+obj-$(CONFIG_ENP2611_MSF_NET) += ixp2000/
 
 obj-$(CONFIG_NETCONSOLE) += netconsole.o
 
diff --git a/drivers/net/bonding/Makefile b/drivers/net/bonding/Makefile
index cf50384b469e..5cdae2bc055a 100644
--- a/drivers/net/bonding/Makefile
+++ b/drivers/net/bonding/Makefile
@@ -4,5 +4,5 @@
 
 obj-$(CONFIG_BONDING) += bonding.o
 
-bonding-objs := bond_main.o bond_3ad.o bond_alb.o
+bonding-objs := bond_main.o bond_3ad.o bond_alb.o bond_sysfs.o
 
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index d2f34d5a8083..f3f5825469d6 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -18,38 +18,6 @@
  * The full GNU General Public License is included in this distribution in the
  * file called LICENSE.
  *
- *
- * Changes:
- *
- * 2003/05/01 - Tsippy Mendelson <tsippy.mendelson at intel dot com> and
- *		Amir Noam <amir.noam at intel dot com>
- *	- Added support for lacp_rate module param.
- *
- * 2003/05/01 - Shmulik Hen <shmulik.hen at intel dot com>
- *	- Based on discussion on mailing list, changed locking scheme
- *	  to use lock/unlock or lock_bh/unlock_bh appropriately instead
- *	  of lock_irqsave/unlock_irqrestore. The new scheme helps exposing
- *	  hidden bugs and solves system hangs that occurred due to the fact
- *	  that holding lock_irqsave doesn't prevent softirqs from running.
- *	  This also increases total throughput since interrupts are not
- *	  blocked on each transmitted packets or monitor timeout.
- *
- * 2003/05/01 - Shmulik Hen <shmulik.hen at intel dot com>
- *	- Renamed bond_3ad_link_status_changed() to
- *	  bond_3ad_handle_link_change() for compatibility with TLB.
- *
- * 2003/05/20 - Amir Noam <amir.noam at intel dot com>
- *	- Fix long fail over time when releasing last slave of an active
- *	  aggregator - send LACPDU on unbind of slave to tell partner this
- *	  port is no longer aggregatable.
- *
- * 2003/06/25 - Tsippy Mendelson <tsippy.mendelson at intel dot com>
- *	- Send LACPDU as highest priority packet to further fix the above
- *	  problem on very high Tx traffic load where packets may get dropped
- *	  by the slave.
- *
- * 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
- *	- Code cleanup and style changes
  */
 
 //#define BONDING_DEBUG 1
@@ -1198,10 +1166,10 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
 			// detect loopback situation
 			if (!MAC_ADDRESS_COMPARE(&(lacpdu->actor_system), &(port->actor_system))) {
 				// INFO_RECEIVED_LOOPBACK_FRAMES
-				printk(KERN_ERR DRV_NAME ": An illegal loopback occurred on adapter (%s)\n",
-						port->slave->dev->name);
-				printk(KERN_ERR "Check the configuration to verify that all Adapters "
-						"are connected to 802.3ad compliant switch ports\n");
+				printk(KERN_ERR DRV_NAME ": %s: An illegal loopback occurred on "
+				       "adapter (%s). Check the configuration to verify that all "
+				       "Adapters are connected to 802.3ad compliant switch ports\n",
+				       port->slave->dev->master->name, port->slave->dev->name);
 				__release_rx_machine_lock(port);
 				return;
 			}
@@ -1378,8 +1346,9 @@ static void ad_port_selection_logic(struct port *port)
 			}
 		}
 		if (!curr_port) { // meaning: the port was related to an aggregator but was not on the aggregator port list
-			printk(KERN_WARNING DRV_NAME ": Warning: Port %d (on %s) was "
+			printk(KERN_WARNING DRV_NAME ": %s: Warning: Port %d (on %s) was "
 			       "related to aggregator %d but was not on its port list\n",
+			       port->slave->dev->master->name,
 			       port->actor_port_number, port->slave->dev->name,
 			       port->aggregator->aggregator_identifier);
 		}
@@ -1450,7 +1419,8 @@ static void ad_port_selection_logic(struct port *port)
 
 			dprintk("Port %d joined LAG %d(new LAG)\n", port->actor_port_number, port->aggregator->aggregator_identifier);
 		} else {
-			printk(KERN_ERR DRV_NAME ": Port %d (on %s) did not find a suitable aggregator\n",
+			printk(KERN_ERR DRV_NAME ": %s: Port %d (on %s) did not find a suitable aggregator\n",
+			       port->slave->dev->master->name,
 			       port->actor_port_number, port->slave->dev->name);
 		}
 	}
@@ -1582,8 +1552,9 @@ static void ad_agg_selection_logic(struct aggregator *aggregator)
 
 		// check if any partner replys
 		if (best_aggregator->is_individual) {
-			printk(KERN_WARNING DRV_NAME ": Warning: No 802.3ad response from the link partner "
-					"for any adapters in the bond\n");
+			printk(KERN_WARNING DRV_NAME ": %s: Warning: No 802.3ad response from "
+			       "the link partner for any adapters in the bond\n",
+			       best_aggregator->slave->dev->master->name);
 		}
 
 		// check if there are more than one aggregator
@@ -1915,7 +1886,8 @@ int bond_3ad_bind_slave(struct slave *slave)
 	struct aggregator *aggregator;
 
 	if (bond == NULL) {
-		printk(KERN_ERR "The slave %s is not attached to its bond\n", slave->dev->name);
+		printk(KERN_ERR DRV_NAME ": %s: The slave %s is not attached to its bond\n",
+		       slave->dev->master->name, slave->dev->name);
 		return -1;
 	}
 
@@ -1990,7 +1962,9 @@ void bond_3ad_unbind_slave(struct slave *slave)
 
 	// if slave is null, the whole port is not initialized
 	if (!port->slave) {
-		printk(KERN_WARNING DRV_NAME ": Trying to unbind an uninitialized port on %s\n", slave->dev->name);
+		printk(KERN_WARNING DRV_NAME ": Warning: %s: Trying to "
+		       "unbind an uninitialized port on %s\n",
+		       slave->dev->master->name, slave->dev->name);
 		return;
 	}
 
@@ -2021,7 +1995,8 @@ void bond_3ad_unbind_slave(struct slave *slave)
 				dprintk("Some port(s) related to LAG %d - replaceing with LAG %d\n", aggregator->aggregator_identifier, new_aggregator->aggregator_identifier);
 
 				if ((new_aggregator->lag_ports == port) && new_aggregator->is_active) {
-					printk(KERN_INFO DRV_NAME ": Removing an active aggregator\n");
+					printk(KERN_INFO DRV_NAME ": %s: Removing an active aggregator\n",
+					       aggregator->slave->dev->master->name);
 					// select new active aggregator
 					 select_new_active_agg = 1;
 				}
@@ -2051,15 +2026,17 @@ void bond_3ad_unbind_slave(struct slave *slave)
 					ad_agg_selection_logic(__get_first_agg(port));
 				}
 			} else {
-				printk(KERN_WARNING DRV_NAME ": Warning: unbinding aggregator, "
-				       "and could not find a new aggregator for its ports\n");
+				printk(KERN_WARNING DRV_NAME ": %s: Warning: unbinding aggregator, "
+				       "and could not find a new aggregator for its ports\n",
+				       slave->dev->master->name);
 			}
 		} else { // in case that the only port related to this aggregator is the one we want to remove
 			select_new_active_agg = aggregator->is_active;
 			// clear the aggregator
 			ad_clear_agg(aggregator);
 			if (select_new_active_agg) {
-				printk(KERN_INFO "Removing an active aggregator\n");
+				printk(KERN_INFO DRV_NAME ": %s: Removing an active aggregator\n",
+				       slave->dev->master->name);
 				// select new active aggregator
 				ad_agg_selection_logic(__get_first_agg(port));
 			}
@@ -2085,7 +2062,8 @@ void bond_3ad_unbind_slave(struct slave *slave)
 					// clear the aggregator
 					ad_clear_agg(temp_aggregator);
 					if (select_new_active_agg) {
-						printk(KERN_INFO "Removing an active aggregator\n");
+						printk(KERN_INFO DRV_NAME ": %s: Removing an active aggregator\n",
+						       slave->dev->master->name);
 						// select new active aggregator
 						ad_agg_selection_logic(__get_first_agg(port));
 					}
@@ -2131,7 +2109,8 @@ void bond_3ad_state_machine_handler(struct bonding *bond)
 		// select the active aggregator for the bond
 		if ((port = __get_first_port(bond))) {
 			if (!port->slave) {
-				printk(KERN_WARNING DRV_NAME ": Warning: bond's first port is uninitialized\n");
+				printk(KERN_WARNING DRV_NAME ": %s: Warning: bond's first port is "
+				       "uninitialized\n", bond->dev->name);
 				goto re_arm;
 			}
 
@@ -2143,7 +2122,8 @@ void bond_3ad_state_machine_handler(struct bonding *bond)
 	// for each port run the state machines
 	for (port = __get_first_port(bond); port; port = __get_next_port(port)) {
 		if (!port->slave) {
-			printk(KERN_WARNING DRV_NAME ": Warning: Found an uninitialized port\n");
+			printk(KERN_WARNING DRV_NAME ": %s: Warning: Found an uninitialized "
+			       "port\n", bond->dev->name);
 			goto re_arm;
 		}
 
@@ -2184,7 +2164,8 @@ static void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u
 		port = &(SLAVE_AD_INFO(slave).port);
 
 		if (!port->slave) {
-			printk(KERN_WARNING DRV_NAME ": Warning: port of slave %s is uninitialized\n", slave->dev->name);
+			printk(KERN_WARNING DRV_NAME ": %s: Warning: port of slave %s is "
+			       "uninitialized\n", slave->dev->name, slave->dev->master->name);
 			return;
 		}
 
@@ -2230,8 +2211,9 @@ void bond_3ad_adapter_speed_changed(struct slave *slave)
 
 	// if slave is null, the whole port is not initialized
 	if (!port->slave) {
-		printk(KERN_WARNING DRV_NAME ": Warning: speed changed for uninitialized port on %s\n",
-		       slave->dev->name);
+		printk(KERN_WARNING DRV_NAME ": Warning: %s: speed "
+		       "changed for uninitialized port on %s\n",
+		       slave->dev->master->name, slave->dev->name);
 		return;
 	}
 
@@ -2257,8 +2239,9 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave)
 
 	// if slave is null, the whole port is not initialized
 	if (!port->slave) {
-		printk(KERN_WARNING DRV_NAME ": Warning: duplex changed for uninitialized port on %s\n",
-		       slave->dev->name);
+		printk(KERN_WARNING DRV_NAME ": %s: Warning: duplex changed "
+		       "for uninitialized port on %s\n",
+		       slave->dev->master->name, slave->dev->name);
 		return;
 	}
 
@@ -2285,8 +2268,9 @@ void bond_3ad_handle_link_change(struct slave *slave, char link)
 
 	// if slave is null, the whole port is not initialized
 	if (!port->slave) {
-		printk(KERN_WARNING DRV_NAME ": Warning: link status changed for uninitialized port on %s\n",
-			slave->dev->name);
+		printk(KERN_WARNING DRV_NAME ": Warning: %s: link status changed for "
+		       "uninitialized port on %s\n",
+			slave->dev->master->name, slave->dev->name);
 		return;
 	}
 
@@ -2363,7 +2347,8 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
 	}
 
 	if (bond_3ad_get_active_agg_info(bond, &ad_info)) {
-		printk(KERN_DEBUG "ERROR: bond_3ad_get_active_agg_info failed\n");
+		printk(KERN_DEBUG DRV_NAME ": %s: Error: "
+		       "bond_3ad_get_active_agg_info failed\n", dev->name);
 		goto out;
 	}
 
@@ -2372,7 +2357,9 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
 
 	if (slaves_in_agg == 0) {
 		/*the aggregator is empty*/
-		printk(KERN_DEBUG "ERROR: active aggregator is empty\n");
+		printk(KERN_DEBUG DRV_NAME ": %s: Error: active "
+		       "aggregator is empty\n",
+		       dev->name);
 		goto out;
 	}
 
@@ -2390,7 +2377,8 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
 	}
 
 	if (slave_agg_no >= 0) {
-		printk(KERN_ERR DRV_NAME ": Error: Couldn't find a slave to tx on for aggregator ID %d\n", agg_id);
+		printk(KERN_ERR DRV_NAME ": %s: Error: Couldn't find a slave to tx on "
+		       "for aggregator ID %d\n", dev->name, agg_id);
 		goto out;
 	}
 
diff --git a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h
index 673a30af5660..5ee2cef5b037 100644
--- a/drivers/net/bonding/bond_3ad.h
+++ b/drivers/net/bonding/bond_3ad.h
@@ -18,19 +18,6 @@
  * The full GNU General Public License is included in this distribution in the
  * file called LICENSE.
  *
- *
- * Changes:
- *
- * 2003/05/01 - Tsippy Mendelson <tsippy.mendelson at intel dot com> and
- *		Amir Noam <amir.noam at intel dot com>
- *	- Added support for lacp_rate module param.
- *
- * 2003/05/01 - Shmulik Hen <shmulik.hen at intel dot com>
- *	- Renamed bond_3ad_link_status_changed() to
- *	  bond_3ad_handle_link_change() for compatibility with TLB.
- *
- * 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
- *	- Code cleanup and style changes
  */
 
 #ifndef __BOND_3AD_H__
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index f8fce3961197..854ddfb90da1 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -18,25 +18,6 @@
  * The full GNU General Public License is included in this distribution in the
  * file called LICENSE.
  *
- *
- * Changes:
- *
- * 2003/06/25 - Shmulik Hen <shmulik.hen at intel dot com>
- *	- Fixed signed/unsigned calculation errors that caused load sharing
- *	  to collapse to one slave under very heavy UDP Tx stress.
- *
- * 2003/08/06 - Amir Noam <amir.noam at intel dot com>
- *	- Add support for setting bond's MAC address with special
- *	  handling required for ALB/TLB.
- *
- * 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
- *	- Code cleanup and style changes
- *
- * 2003/12/30 - Amir Noam <amir.noam at intel dot com>
- *	- Fixed: Cannot remove and re-enslave the original active slave.
- *
- * 2004/01/14 - Shmulik Hen <shmulik.hen at intel dot com>
- *	- Add capability to tag self generated packets in ALB/TLB modes.
  */
 
 //#define BONDING_DEBUG 1
@@ -198,20 +179,21 @@ static int tlb_initialize(struct bonding *bond)
 {
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
 	int size = TLB_HASH_TABLE_SIZE * sizeof(struct tlb_client_info);
+	struct tlb_client_info *new_hashtbl;
 	int i;
 
 	spin_lock_init(&(bond_info->tx_hashtbl_lock));
 
-	_lock_tx_hashtbl(bond);
-
-	bond_info->tx_hashtbl = kmalloc(size, GFP_KERNEL);
-	if (!bond_info->tx_hashtbl) {
+	new_hashtbl = kmalloc(size, GFP_KERNEL);
+	if (!new_hashtbl) {
 		printk(KERN_ERR DRV_NAME
-		       ": Error: %s: Failed to allocate TLB hash table\n",
+		       ": %s: Error: Failed to allocate TLB hash table\n",
 		       bond->dev->name);
-		_unlock_tx_hashtbl(bond);
 		return -1;
 	}
+	_lock_tx_hashtbl(bond);
+
+	bond_info->tx_hashtbl = new_hashtbl;
 
 	memset(bond_info->tx_hashtbl, 0, size);
 
@@ -513,7 +495,8 @@ static void rlb_update_client(struct rlb_client_info *client_info)
 				 client_info->mac_dst);
 		if (!skb) {
 			printk(KERN_ERR DRV_NAME
-			       ": Error: failed to create an ARP packet\n");
+			       ": %s: Error: failed to create an ARP packet\n",
+			       client_info->slave->dev->master->name);
 			continue;
 		}
 
@@ -523,7 +506,8 @@ static void rlb_update_client(struct rlb_client_info *client_info)
 			skb = vlan_put_tag(skb, client_info->vlan_id);
 			if (!skb) {
 				printk(KERN_ERR DRV_NAME
-				       ": Error: failed to insert VLAN tag\n");
+				       ": %s: Error: failed to insert VLAN tag\n",
+				       client_info->slave->dev->master->name);
 				continue;
 			}
 		}
@@ -606,8 +590,9 @@ static void rlb_req_update_subnet_clients(struct bonding *bond, u32 src_ip)
 
 		if (!client_info->slave) {
 			printk(KERN_ERR DRV_NAME
-			       ": Error: found a client with no channel in "
-			       "the client's hash table\n");
+			       ": %s: Error: found a client with no channel in "
+			       "the client's hash table\n",
+			       bond->dev->name);
 			continue;
 		}
 		/*update all clients using this src_ip, that are not assigned
@@ -797,21 +782,22 @@ static int rlb_initialize(struct bonding *bond)
 {
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
 	struct packet_type *pk_type = &(BOND_ALB_INFO(bond).rlb_pkt_type);
+	struct rlb_client_info	*new_hashtbl;
 	int size = RLB_HASH_TABLE_SIZE * sizeof(struct rlb_client_info);
 	int i;
 
 	spin_lock_init(&(bond_info->rx_hashtbl_lock));
 
-	_lock_rx_hashtbl(bond);
-
-	bond_info->rx_hashtbl = kmalloc(size, GFP_KERNEL);
-	if (!bond_info->rx_hashtbl) {
+	new_hashtbl = kmalloc(size, GFP_KERNEL);
+	if (!new_hashtbl) {
 		printk(KERN_ERR DRV_NAME
-		       ": Error: %s: Failed to allocate RLB hash table\n",
+		       ": %s: Error: Failed to allocate RLB hash table\n",
 		       bond->dev->name);
-		_unlock_rx_hashtbl(bond);
 		return -1;
 	}
+	_lock_rx_hashtbl(bond);
+
+	bond_info->rx_hashtbl = new_hashtbl;
 
 	bond_info->rx_hashtbl_head = RLB_NULL_INDEX;
 
@@ -927,7 +913,8 @@ static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[])
 			skb = vlan_put_tag(skb, vlan->vlan_id);
 			if (!skb) {
 				printk(KERN_ERR DRV_NAME
-				       ": Error: failed to insert VLAN tag\n");
+				       ": %s: Error: failed to insert VLAN tag\n",
+				       bond->dev->name);
 				continue;
 			}
 		}
@@ -956,11 +943,11 @@ static int alb_set_slave_mac_addr(struct slave *slave, u8 addr[], int hw)
 	s_addr.sa_family = dev->type;
 	if (dev_set_mac_address(dev, &s_addr)) {
 		printk(KERN_ERR DRV_NAME
-		       ": Error: dev_set_mac_address of dev %s failed! ALB "
+		       ": %s: Error: dev_set_mac_address of dev %s failed! ALB "
 		       "mode requires that the base driver support setting "
 		       "the hw address also when the network device's "
 		       "interface is open\n",
-		       dev->name);
+		       dev->master->name, dev->name);
 		return -EOPNOTSUPP;
 	}
 	return 0;
@@ -1153,16 +1140,16 @@ static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slav
 				       bond->alb_info.rlb_enabled);
 
 		printk(KERN_WARNING DRV_NAME
-		       ": Warning: the hw address of slave %s is in use by "
+		       ": %s: Warning: the hw address of slave %s is in use by "
 		       "the bond; giving it the hw address of %s\n",
-		       slave->dev->name, free_mac_slave->dev->name);
+		       bond->dev->name, slave->dev->name, free_mac_slave->dev->name);
 
 	} else if (has_bond_addr) {
 		printk(KERN_ERR DRV_NAME
-		       ": Error: the hw address of slave %s is in use by the "
+		       ": %s: Error: the hw address of slave %s is in use by the "
 		       "bond; couldn't find a slave with a free hw address to "
 		       "give it (this should not have happened)\n",
-		       slave->dev->name);
+		       bond->dev->name, slave->dev->name);
 		return -EFAULT;
 	}
 
@@ -1250,6 +1237,8 @@ int bond_alb_initialize(struct bonding *bond, int rlb_enabled)
 			tlb_deinitialize(bond);
 			return res;
 		}
+	} else {
+		bond->alb_info.rlb_enabled = 0;
 	}
 
 	return 0;
@@ -1409,7 +1398,7 @@ void bond_alb_monitor(struct bonding *bond)
 		read_lock(&bond->curr_slave_lock);
 
 		bond_for_each_slave(bond, slave, i) {
-			alb_send_learning_packets(slave,slave->dev->dev_addr);
+			alb_send_learning_packets(slave, slave->dev->dev_addr);
 		}
 
 		read_unlock(&bond->curr_slave_lock);
diff --git a/drivers/net/bonding/bond_alb.h b/drivers/net/bonding/bond_alb.h
index e4091cd8d654..28f2a2fd1b5a 100644
--- a/drivers/net/bonding/bond_alb.h
+++ b/drivers/net/bonding/bond_alb.h
@@ -18,15 +18,6 @@
  * The full GNU General Public License is included in this distribution in the
  * file called LICENSE.
  *
- *
- * Changes:
- *
- * 2003/08/06 - Amir Noam <amir.noam at intel dot com>
- *	- Add support for setting bond's MAC address with special
- *	  handling required for ALB/TLB.
- *
- * 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
- *	- Code cleanup and style changes
  */
 
 #ifndef __BOND_ALB_H__
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 94cec3cf2a13..2582d98ef5c3 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -29,466 +29,6 @@
  *	b: if a hw mac address already is there, eth0's hw mac address
  *	   will then be set from bond0.
  *
- * v0.1 - first working version.
- * v0.2 - changed stats to be calculated by summing slaves stats.
- *
- * Changes:
- * Arnaldo Carvalho de Melo <acme@conectiva.com.br>
- * - fix leaks on failure at bond_init
- *
- * 2000/09/30 - Willy Tarreau <willy at meta-x.org>
- *     - added trivial code to release a slave device.
- *     - fixed security bug (CAP_NET_ADMIN not checked)
- *     - implemented MII link monitoring to disable dead links :
- *       All MII capable slaves are checked every <miimon> milliseconds
- *       (100 ms seems good). This value can be changed by passing it to
- *       insmod. A value of zero disables the monitoring (default).
- *     - fixed an infinite loop in bond_xmit_roundrobin() when there's no
- *       good slave.
- *     - made the code hopefully SMP safe
- *
- * 2000/10/03 - Willy Tarreau <willy at meta-x.org>
- *     - optimized slave lists based on relevant suggestions from Thomas Davis
- *     - implemented active-backup method to obtain HA with two switches:
- *       stay as long as possible on the same active interface, while we
- *       also monitor the backup one (MII link status) because we want to know
- *       if we are able to switch at any time. ( pass "mode=1" to insmod )
- *     - lots of stress testings because we need it to be more robust than the
- *       wires ! :->
- *
- * 2000/10/09 - Willy Tarreau <willy at meta-x.org>
- *     - added up and down delays after link state change.
- *     - optimized the slaves chaining so that when we run forward, we never
- *       repass through the bond itself, but we can find it by searching
- *       backwards. Renders the deletion more difficult, but accelerates the
- *       scan.
- *     - smarter enslaving and releasing.
- *     - finer and more robust SMP locking
- *
- * 2000/10/17 - Willy Tarreau <willy at meta-x.org>
- *     - fixed two potential SMP race conditions
- *
- * 2000/10/18 - Willy Tarreau <willy at meta-x.org>
- *     - small fixes to the monitoring FSM in case of zero delays
- * 2000/11/01 - Willy Tarreau <willy at meta-x.org>
- *     - fixed first slave not automatically used in trunk mode.
- * 2000/11/10 : spelling of "EtherChannel" corrected.
- * 2000/11/13 : fixed a race condition in case of concurrent accesses to ioctl().
- * 2000/12/16 : fixed improper usage of rtnl_exlock_nowait().
- *
- * 2001/1/3 - Chad N. Tindel <ctindel at ieee dot org>
- *     - The bonding driver now simulates MII status monitoring, just like
- *       a normal network device.  It will show that the link is down iff
- *       every slave in the bond shows that their links are down.  If at least
- *       one slave is up, the bond's MII status will appear as up.
- *
- * 2001/2/7 - Chad N. Tindel <ctindel at ieee dot org>
- *     - Applications can now query the bond from user space to get
- *       information which may be useful.  They do this by calling
- *       the BOND_INFO_QUERY ioctl.  Once the app knows how many slaves
- *       are in the bond, it can call the BOND_SLAVE_INFO_QUERY ioctl to
- *       get slave specific information (# link failures, etc).  See
- *       <linux/if_bonding.h> for more details.  The structs of interest
- *       are ifbond and ifslave.
- *
- * 2001/4/5 - Chad N. Tindel <ctindel at ieee dot org>
- *     - Ported to 2.4 Kernel
- *
- * 2001/5/2 - Jeffrey E. Mast <jeff at mastfamily dot com>
- *     - When a device is detached from a bond, the slave device is no longer
- *       left thinking that is has a master.
- *
- * 2001/5/16 - Jeffrey E. Mast <jeff at mastfamily dot com>
- *     - memset did not appropriately initialized the bond rw_locks. Used
- *       rwlock_init to initialize to unlocked state to prevent deadlock when
- *       first attempting a lock
- *     - Called SET_MODULE_OWNER for bond device
- *
- * 2001/5/17 - Tim Anderson <tsa at mvista.com>
- *     - 2 paths for releasing for slave release; 1 through ioctl
- *       and 2) through close. Both paths need to release the same way.
- *     - the free slave in bond release is changing slave status before
- *       the free. The netdev_set_master() is intended to change slave state
- *       so it should not be done as part of the release process.
- *     - Simple rule for slave state at release: only the active in A/B and
- *       only one in the trunked case.
- *
- * 2001/6/01 - Tim Anderson <tsa at mvista.com>
- *     - Now call dev_close when releasing a slave so it doesn't screw up
- *       out routing table.
- *
- * 2001/6/01 - Chad N. Tindel <ctindel at ieee dot org>
- *     - Added /proc support for getting bond and slave information.
- *       Information is in /proc/net/<bond device>/info.
- *     - Changed the locking when calling bond_close to prevent deadlock.
- *
- * 2001/8/05 - Janice Girouard <girouard at us.ibm.com>
- *     - correct problem where refcnt of slave is not incremented in bond_ioctl
- *       so the system hangs when halting.
- *     - correct locking problem when unable to malloc in bond_enslave.
- *     - adding bond_xmit_xor logic.
- *     - adding multiple bond device support.
- *
- * 2001/8/13 - Erik Habbinga <erik_habbinga at hp dot com>
- *     - correct locking problem with rtnl_exlock_nowait
- *
- * 2001/8/23 - Janice Girouard <girouard at us.ibm.com>
- *     - bzero initial dev_bonds, to correct oops
- *     - convert SIOCDEVPRIVATE to new MII ioctl calls
- *
- * 2001/9/13 - Takao Indoh <indou dot takao at jp dot fujitsu dot com>
- *     - Add the BOND_CHANGE_ACTIVE ioctl implementation
- *
- * 2001/9/14 - Mark Huth <mhuth at mvista dot com>
- *     - Change MII_LINK_READY to not check for end of auto-negotiation,
- *       but only for an up link.
- *
- * 2001/9/20 - Chad N. Tindel <ctindel at ieee dot org>
- *     - Add the device field to bonding_t.  Previously the net_device
- *       corresponding to a bond wasn't available from the bonding_t
- *       structure.
- *
- * 2001/9/25 - Janice Girouard <girouard at us.ibm.com>
- *     - add arp_monitor for active backup mode
- *
- * 2001/10/23 - Takao Indoh <indou dot takao at jp dot fujitsu dot com>
- *     - Various memory leak fixes
- *
- * 2001/11/5 - Mark Huth <mark dot huth at mvista dot com>
- *     - Don't take rtnl lock in bond_mii_monitor as it deadlocks under
- *       certain hotswap conditions.
- *       Note:  this same change may be required in bond_arp_monitor ???
- *     - Remove possibility of calling bond_sethwaddr with NULL slave_dev ptr
- *     - Handle hot swap ethernet interface deregistration events to remove
- *       kernel oops following hot swap of enslaved interface
- *
- * 2002/1/2 - Chad N. Tindel <ctindel at ieee dot org>
- *     - Restore original slave flags at release time.
- *
- * 2002/02/18 - Erik Habbinga <erik_habbinga at hp dot com>
- *     - bond_release(): calling kfree on our_slave after call to
- *       bond_restore_slave_flags, not before
- *     - bond_enslave(): saving slave flags into original_flags before
- *       call to netdev_set_master, so the IFF_SLAVE flag doesn't end
- *       up in original_flags
- *
- * 2002/04/05 - Mark Smith <mark.smith at comdev dot cc> and
- *              Steve Mead <steve.mead at comdev dot cc>
- *     - Port Gleb Natapov's multicast support patchs from 2.4.12
- *       to 2.4.18 adding support for multicast.
- *
- * 2002/06/10 - Tony Cureington <tony.cureington * hp_com>
- *     - corrected uninitialized pointer (ifr.ifr_data) in bond_check_dev_link;
- *       actually changed function to use MIIPHY, then MIIREG, and finally
- *       ETHTOOL to determine the link status
- *     - fixed bad ifr_data pointer assignments in bond_ioctl
- *     - corrected mode 1 being reported as active-backup in bond_get_info;
- *       also added text to distinguish type of load balancing (rr or xor)
- *     - change arp_ip_target module param from "1-12s" (array of 12 ptrs)
- *       to "s" (a single ptr)
- *
- * 2002/08/30 - Jay Vosburgh <fubar at us dot ibm dot com>
- *     - Removed acquisition of xmit_lock in set_multicast_list; caused
- *       deadlock on SMP (lock is held by caller).
- *     - Revamped SIOCGMIIPHY, SIOCGMIIREG portion of bond_check_dev_link().
- *
- * 2002/09/18 - Jay Vosburgh <fubar at us dot ibm dot com>
- *     - Fixed up bond_check_dev_link() (and callers): removed some magic
- *	 numbers, banished local MII_ defines, wrapped ioctl calls to
- *	 prevent EFAULT errors
- *
- * 2002/9/30 - Jay Vosburgh <fubar at us dot ibm dot com>
- *     - make sure the ip target matches the arp_target before saving the
- *	 hw address.
- *
- * 2002/9/30 - Dan Eisner <eisner at 2robots dot com>
- *     - make sure my_ip is set before taking down the link, since
- *	 not all switches respond if the source ip is not set.
- *
- * 2002/10/8 - Janice Girouard <girouard at us dot ibm dot com>
- *     - read in the local ip address when enslaving a device
- *     - add primary support
- *     - make sure 2*arp_interval has passed when a new device
- *       is brought on-line before taking it down.
- *
- * 2002/09/11 - Philippe De Muyter <phdm at macqel dot be>
- *     - Added bond_xmit_broadcast logic.
- *     - Added bond_mode() support function.
- *
- * 2002/10/26 - Laurent Deniel <laurent.deniel at free.fr>
- *     - allow to register multicast addresses only on active slave
- *       (useful in active-backup mode)
- *     - add multicast module parameter
- *     - fix deletion of multicast groups after unloading module
- *
- * 2002/11/06 - Kameshwara Rayaprolu <kameshwara.rao * wipro_com>
- *     - Changes to prevent panic from closing the device twice; if we close
- *       the device in bond_release, we must set the original_flags to down
- *       so it won't be closed again by the network layer.
- *
- * 2002/11/07 - Tony Cureington <tony.cureington * hp_com>
- *     - Fix arp_target_hw_addr memory leak
- *     - Created activebackup_arp_monitor function to handle arp monitoring
- *       in active backup mode - the bond_arp_monitor had several problems...
- *       such as allowing slaves to tx arps sequentially without any delay
- *       for a response
- *     - Renamed bond_arp_monitor to loadbalance_arp_monitor and re-wrote
- *       this function to just handle arp monitoring in load-balancing mode;
- *       it is a lot more compact now
- *     - Changes to ensure one and only one slave transmits in active-backup
- *       mode
- *     - Robustesize parameters; warn users about bad combinations of
- *       parameters; also if miimon is specified and a network driver does
- *       not support MII or ETHTOOL, inform the user of this
- *     - Changes to support link_failure_count when in arp monitoring mode
- *     - Fix up/down delay reported in /proc
- *     - Added version; log version; make version available from "modinfo -d"
- *     - Fixed problem in bond_check_dev_link - if the first IOCTL (SIOCGMIIPH)
- *	 failed, the ETHTOOL ioctl never got a chance
- *
- * 2002/11/16 - Laurent Deniel <laurent.deniel at free.fr>
- *     - fix multicast handling in activebackup_arp_monitor
- *     - remove one unnecessary and confusing curr_active_slave == slave test
- *	 in activebackup_arp_monitor
- *
- *  2002/11/17 - Laurent Deniel <laurent.deniel at free.fr>
- *     - fix bond_slave_info_query when slave_id = num_slaves
- *
- *  2002/11/19 - Janice Girouard <girouard at us dot ibm dot com>
- *     - correct ifr_data reference.  Update ifr_data reference
- *       to mii_ioctl_data struct values to avoid confusion.
- *
- *  2002/11/22 - Bert Barbe <bert.barbe at oracle dot com>
- *      - Add support for multiple arp_ip_target
- *
- *  2002/12/13 - Jay Vosburgh <fubar at us dot ibm dot com>
- *	- Changed to allow text strings for mode and multicast, e.g.,
- *	  insmod bonding mode=active-backup.  The numbers still work.
- *	  One change: an invalid choice will cause module load failure,
- *	  rather than the previous behavior of just picking one.
- *	- Minor cleanups; got rid of dup ctype stuff, atoi function
- *
- * 2003/02/07 - Jay Vosburgh <fubar at us dot ibm dot com>
- *	- Added use_carrier module parameter that causes miimon to
- *	  use netif_carrier_ok() test instead of MII/ETHTOOL ioctls.
- *	- Minor cleanups; consolidated ioctl calls to one function.
- *
- * 2003/02/07 - Tony Cureington <tony.cureington * hp_com>
- *	- Fix bond_mii_monitor() logic error that could result in
- *	  bonding round-robin mode ignoring links after failover/recovery
- *
- * 2003/03/17 - Jay Vosburgh <fubar at us dot ibm dot com>
- *	- kmalloc fix (GFP_KERNEL to GFP_ATOMIC) reported by
- *	  Shmulik dot Hen at intel.com.
- *	- Based on discussion on mailing list, changed use of
- *	  update_slave_cnt(), created wrapper functions for adding/removing
- *	  slaves, changed bond_xmit_xor() to check slave_cnt instead of
- *	  checking slave and slave->dev (which only worked by accident).
- *	- Misc code cleanup: get arp_send() prototype from header file,
- *	  add max_bonds to bonding.txt.
- *
- * 2003/03/18 - Tsippy Mendelson <tsippy.mendelson at intel dot com> and
- *		Shmulik Hen <shmulik.hen at intel dot com>
- *	- Make sure only bond_attach_slave() and bond_detach_slave() can
- *	  manipulate the slave list, including slave_cnt, even when in
- *	  bond_release_all().
- *	- Fixed hang in bond_release() with traffic running:
- *	  netdev_set_master() must not be called from within the bond lock.
- *
- * 2003/03/18 - Tsippy Mendelson <tsippy.mendelson at intel dot com> and
- *		Shmulik Hen <shmulik.hen at intel dot com>
- *	- Fixed hang in bond_enslave() with traffic running:
- *	  netdev_set_master() must not be called from within the bond lock.
- *
- * 2003/03/18 - Amir Noam <amir.noam at intel dot com>
- *	- Added support for getting slave's speed and duplex via ethtool.
- *	  Needed for 802.3ad and other future modes.
- *
- * 2003/03/18 - Tsippy Mendelson <tsippy.mendelson at intel dot com> and
- *		Shmulik Hen <shmulik.hen at intel dot com>
- *	- Enable support of modes that need to use the unique mac address of
- *	  each slave.
- *	  * bond_enslave(): Moved setting the slave's mac address, and
- *	    openning it, from the application to the driver. This breaks
- *	    backward comaptibility with old versions of ifenslave that open
- *	     the slave before enalsving it !!!.
- *	  * bond_release(): The driver also takes care of closing the slave
- *	    and restoring its original mac address.
- *	- Removed the code that restores all base driver's flags.
- *	  Flags are automatically restored once all undo stages are done
- *	  properly.
- *	- Block possibility of enslaving before the master is up. This
- *	  prevents putting the system in an unstable state.
- *
- * 2003/03/18 - Amir Noam <amir.noam at intel dot com>,
- *		Tsippy Mendelson <tsippy.mendelson at intel dot com> and
- *		Shmulik Hen <shmulik.hen at intel dot com>
- *	- Added support for IEEE 802.3ad Dynamic link aggregation mode.
- *
- * 2003/05/01 - Amir Noam <amir.noam at intel dot com>
- *	- Added ABI version control to restore compatibility between
- *	  new/old ifenslave and new/old bonding.
- *
- * 2003/05/01 - Shmulik Hen <shmulik.hen at intel dot com>
- *	- Fixed bug in bond_release_all(): save old value of curr_active_slave
- *	  before setting it to NULL.
- *	- Changed driver versioning scheme to include version number instead
- *	  of release date (that is already in another field). There are 3
- *	  fields X.Y.Z where:
- *		X - Major version - big behavior changes
- *		Y - Minor version - addition of features
- *		Z - Extra version - minor changes and bug fixes
- *	  The current version is 1.0.0 as a base line.
- *
- * 2003/05/01 - Tsippy Mendelson <tsippy.mendelson at intel dot com> and
- *		Amir Noam <amir.noam at intel dot com>
- *	- Added support for lacp_rate module param.
- *	- Code beautification and style changes (mainly in comments).
- *	  new version - 1.0.1
- *
- * 2003/05/01 - Shmulik Hen <shmulik.hen at intel dot com>
- *	- Based on discussion on mailing list, changed locking scheme
- *	  to use lock/unlock or lock_bh/unlock_bh appropriately instead
- *	  of lock_irqsave/unlock_irqrestore. The new scheme helps exposing
- *	  hidden bugs and solves system hangs that occurred due to the fact
- *	  that holding lock_irqsave doesn't prevent softirqs from running.
- *	  This also increases total throughput since interrupts are not
- *	  blocked on each transmitted packets or monitor timeout.
- *	  new version - 2.0.0
- *
- * 2003/05/01 - Shmulik Hen <shmulik.hen at intel dot com>
- *	- Added support for Transmit load balancing mode.
- *	- Concentrate all assignments of curr_active_slave to a single point
- *	  so specific modes can take actions when the primary adapter is
- *	  changed.
- *	- Take the updelay parameter into consideration during bond_enslave
- *	  since some adapters loose their link during setting the device.
- *	- Renamed bond_3ad_link_status_changed() to
- *	  bond_3ad_handle_link_change() for compatibility with TLB.
- *	  new version - 2.1.0
- *
- * 2003/05/01 - Tsippy Mendelson <tsippy.mendelson at intel dot com>
- *	- Added support for Adaptive load balancing mode which is
- *	  equivalent to Transmit load balancing + Receive load balancing.
- *	  new version - 2.2.0
- *
- * 2003/05/15 - Jay Vosburgh <fubar at us dot ibm dot com>
- *	- Applied fix to activebackup_arp_monitor posted to bonding-devel
- *	  by Tony Cureington <tony.cureington * hp_com>.  Fixes ARP
- *	  monitor endless failover bug.  Version to 2.2.10
- *
- * 2003/05/20 - Amir Noam <amir.noam at intel dot com>
- *	- Fixed bug in ABI version control - Don't commit to a specific
- *	  ABI version if receiving unsupported ioctl commands.
- *
- * 2003/05/22 - Jay Vosburgh <fubar at us dot ibm dot com>
- *	- Fix ifenslave -c causing bond to loose existing routes;
- *	  added bond_set_mac_address() that doesn't require the
- *	  bond to be down.
- *	- In conjunction with fix for ifenslave -c, in
- *	  bond_change_active(), changing to the already active slave
- *	  is no longer an error (it successfully does nothing).
- *
- * 2003/06/30 - Amir Noam <amir.noam at intel dot com>
- * 	- Fixed bond_change_active() for ALB/TLB modes.
- *	  Version to 2.2.14.
- *
- * 2003/07/29 - Amir Noam <amir.noam at intel dot com>
- * 	- Fixed ARP monitoring bug.
- *	  Version to 2.2.15.
- *
- * 2003/07/31 - Willy Tarreau <willy at ods dot org>
- * 	- Fixed kernel panic when using ARP monitoring without
- *	  setting bond's IP address.
- *	  Version to 2.2.16.
- *
- * 2003/08/06 - Amir Noam <amir.noam at intel dot com>
- * 	- Back port from 2.6: use alloc_netdev(); fix /proc handling;
- *	  made stats a part of bond struct so no need to allocate
- *	  and free it separately; use standard list operations instead
- *	  of pre-allocated array of bonds.
- *	  Version to 2.3.0.
- *
- * 2003/08/07 - Jay Vosburgh <fubar at us dot ibm dot com>,
- *	       Amir Noam <amir.noam at intel dot com> and
- *	       Shmulik Hen <shmulik.hen at intel dot com>
- *	- Propagating master's settings: Distinguish between modes that
- *	  use a primary slave from those that don't, and propagate settings
- *	  accordingly; Consolidate change_active opeartions and add
- *	  reselect_active and find_best opeartions; Decouple promiscuous
- *	  handling from the multicast mode setting; Add support for changing
- *	  HW address and MTU with proper unwind; Consolidate procfs code,
- *	  add CHANGENAME handler; Enhance netdev notification handling.
- *	  Version to 2.4.0.
- *
- * 2003/09/15 - Stephen Hemminger <shemminger at osdl dot org>,
- *	       Amir Noam <amir.noam at intel dot com>
- *	- Convert /proc to seq_file interface.
- *	  Change /proc/net/bondX/info to /proc/net/bonding/bondX.
- *	  Set version to 2.4.1.
- *
- * 2003/11/20 - Amir Noam <amir.noam at intel dot com>
- *	- Fix /proc creation/destruction.
- *
- * 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
- *	- Massive cleanup - Set version to 2.5.0
- *	  Code changes:
- *	  o Consolidate format of prints and debug prints.
- *	  o Remove bonding_t/slave_t typedefs and consolidate all casts.
- *	  o Remove dead code and unnecessary checks.
- *	  o Consolidate starting/stopping timers.
- *	  o Consolidate handling of primary module param throughout the code.
- *	  o Removed multicast module param support - all settings are done
- *	    according to mode.
- *	  o Slave list iteration - bond is no longer part of the list,
- *	    added cyclic list iteration macros.
- *	  o Consolidate error handling in all xmit functions.
- *	  Style changes:
- *	  o Consolidate function naming and declarations.
- *	  o Consolidate function params and local variables names.
- *	  o Consolidate return values.
- *	  o Consolidate curly braces.
- *	  o Consolidate conditionals format.
- *	  o Change struct member names and types.
- *	  o Chomp trailing spaces, remove empty lines, fix indentations.
- *	  o Re-organize code according to context.
- *
- * 2003/12/30 - Amir Noam <amir.noam at intel dot com>
- *	- Fixed: Cannot remove and re-enslave the original active slave.
- *	- Fixed: Releasing the original active slave causes mac address
- *		 duplication.
- *	- Add support for slaves that use ethtool_ops.
- *	  Set version to 2.5.3.
- *
- * 2004/01/05 - Amir Noam <amir.noam at intel dot com>
- *	- Save bonding parameters per bond instead of using the global values.
- *	  Set version to 2.5.4.
- *
- * 2004/01/14 - Shmulik Hen <shmulik.hen at intel dot com>
- *	- Enhance VLAN support:
- *	  * Add support for VLAN hardware acceleration capable slaves.
- *	  * Add capability to tag self generated packets in ALB/TLB modes.
- *	  Set version to 2.6.0.
- * 2004/10/29 - Mitch Williams <mitch.a.williams at intel dot com>
- *      - Fixed bug when unloading module while using 802.3ad.  If
- *        spinlock debugging is turned on, this causes a stack dump.
- *        Solution is to move call to dev_remove_pack outside of the
- *        spinlock.
- *        Set version to 2.6.1.
- * 2005/06/05 - Jay Vosburgh <fubar@us.ibm.com>
- * 	- Support for generating gratuitous ARPs in active-backup mode.
- * 	  Includes support for VLAN tagging all bonding-generated ARPs
- * 	  as needed.  Set version to 2.6.2.
- * 2005/06/08 - Jason Gabler <jygabler at lbl dot gov>
- *	- alternate hashing policy support for mode 2
- *	  * Added kernel parameter "xmit_hash_policy" to allow the selection
- *	    of different hashing policies for mode 2.  The original mode 2
- *	    policy is the default, now found in xmit_hash_policy_layer2().
- *	  * Added xmit_hash_policy_layer34()
- *	- Modified by Jay Vosburgh <fubar@us.ibm.com> to also support mode 4.
- *	  Set version to 2.6.3.
- * 2005/09/26 - Jay Vosburgh <fubar@us.ibm.com>
- *	- Removed backwards compatibility for old ifenslaves.  Version 2.6.4.
  */
 
 //#define BONDING_DEBUG 1
@@ -557,6 +97,7 @@ static char *lacp_rate	= NULL;
 static char *xmit_hash_policy = NULL;
 static int arp_interval = BOND_LINK_ARP_INTERV;
 static char *arp_ip_target[BOND_MAX_ARP_TARGETS] = { NULL, };
+struct bond_params bonding_defaults;
 
 module_param(max_bonds, int, 0);
 MODULE_PARM_DESC(max_bonds, "Max number of bonded devices");
@@ -565,17 +106,24 @@ MODULE_PARM_DESC(miimon, "Link check interval in milliseconds");
 module_param(updelay, int, 0);
 MODULE_PARM_DESC(updelay, "Delay before considering link up, in milliseconds");
 module_param(downdelay, int, 0);
-MODULE_PARM_DESC(downdelay, "Delay before considering link down, in milliseconds");
+MODULE_PARM_DESC(downdelay, "Delay before considering link down, "
+			    "in milliseconds");
 module_param(use_carrier, int, 0);
-MODULE_PARM_DESC(use_carrier, "Use netif_carrier_ok (vs MII ioctls) in miimon; 0 for off, 1 for on (default)");
+MODULE_PARM_DESC(use_carrier, "Use netif_carrier_ok (vs MII ioctls) in miimon; "
+			      "0 for off, 1 for on (default)");
 module_param(mode, charp, 0);
-MODULE_PARM_DESC(mode, "Mode of operation : 0 for round robin, 1 for active-backup, 2 for xor");
+MODULE_PARM_DESC(mode, "Mode of operation : 0 for balance-rr, "
+		       "1 for active-backup, 2 for balance-xor, "
+		       "3 for broadcast, 4 for 802.3ad, 5 for balance-tlb, "
+		       "6 for balance-alb");
 module_param(primary, charp, 0);
 MODULE_PARM_DESC(primary, "Primary network device to use");
 module_param(lacp_rate, charp, 0);
-MODULE_PARM_DESC(lacp_rate, "LACPDU tx rate to request from 802.3ad partner (slow/fast)");
+MODULE_PARM_DESC(lacp_rate, "LACPDU tx rate to request from 802.3ad partner "
+			    "(slow/fast)");
 module_param(xmit_hash_policy, charp, 0);
-MODULE_PARM_DESC(xmit_hash_policy, "XOR hashing method : 0 for layer 2 (default), 1 for layer 3+4");
+MODULE_PARM_DESC(xmit_hash_policy, "XOR hashing method: 0 for layer 2 (default)"
+				   ", 1 for layer 3+4");
 module_param(arp_interval, int, 0);
 MODULE_PARM_DESC(arp_interval, "arp interval in milliseconds");
 module_param_array(arp_ip_target, charp, NULL, 0);
@@ -586,30 +134,27 @@ MODULE_PARM_DESC(arp_ip_target, "arp targets in n.n.n.n form");
 static const char *version =
 	DRV_DESCRIPTION ": v" DRV_VERSION " (" DRV_RELDATE ")\n";
 
-static LIST_HEAD(bond_dev_list);
+LIST_HEAD(bond_dev_list);
 
 #ifdef CONFIG_PROC_FS
 static struct proc_dir_entry *bond_proc_dir = NULL;
 #endif
 
+extern struct rw_semaphore bonding_rwsem;
 static u32 arp_target[BOND_MAX_ARP_TARGETS] = { 0, } ;
 static int arp_ip_count	= 0;
 static int bond_mode	= BOND_MODE_ROUNDROBIN;
 static int xmit_hashtype= BOND_XMIT_POLICY_LAYER2;
 static int lacp_fast	= 0;
 
-struct bond_parm_tbl {
-	char *modename;
-	int mode;
-};
 
-static struct bond_parm_tbl bond_lacp_tbl[] = {
+struct bond_parm_tbl bond_lacp_tbl[] = {
 {	"slow",		AD_LACP_SLOW},
 {	"fast",		AD_LACP_FAST},
 {	NULL,		-1},
 };
 
-static struct bond_parm_tbl bond_mode_tbl[] = {
+struct bond_parm_tbl bond_mode_tbl[] = {
 {	"balance-rr",		BOND_MODE_ROUNDROBIN},
 {	"active-backup",	BOND_MODE_ACTIVEBACKUP},
 {	"balance-xor",		BOND_MODE_XOR},
@@ -620,7 +165,7 @@ static struct bond_parm_tbl bond_mode_tbl[] = {
 {	NULL,			-1},
 };
 
-static struct bond_parm_tbl xmit_hashtype_tbl[] = {
+struct bond_parm_tbl xmit_hashtype_tbl[] = {
 {	"layer2",		BOND_XMIT_POLICY_LAYER2},
 {	"layer3+4",		BOND_XMIT_POLICY_LAYER34},
 {	NULL,			-1},
@@ -628,12 +173,11 @@ static struct bond_parm_tbl xmit_hashtype_tbl[] = {
 
 /*-------------------------- Forward declarations ---------------------------*/
 
-static inline void bond_set_mode_ops(struct bonding *bond, int mode);
 static void bond_send_gratuitous_arp(struct bonding *bond);
 
 /*---------------------------- General routines -----------------------------*/
 
-static const char *bond_mode_name(int mode)
+const char *bond_mode_name(int mode)
 {
 	switch (mode) {
 	case BOND_MODE_ROUNDROBIN :
@@ -910,7 +454,7 @@ static void bond_vlan_rx_add_vid(struct net_device *bond_dev, uint16_t vid)
 	res = bond_add_vlan(bond, vid);
 	if (res) {
 		printk(KERN_ERR DRV_NAME
-		       ": %s: Failed to add vlan id %d\n",
+		       ": %s: Error: Failed to add vlan id %d\n",
 		       bond_dev->name, vid);
 	}
 }
@@ -944,7 +488,7 @@ static void bond_vlan_rx_kill_vid(struct net_device *bond_dev, uint16_t vid)
 	res = bond_del_vlan(bond, vid);
 	if (res) {
 		printk(KERN_ERR DRV_NAME
-		       ": %s: Failed to remove vlan id %d\n",
+		       ": %s: Error: Failed to remove vlan id %d\n",
 		       bond_dev->name, vid);
 	}
 }
@@ -1449,7 +993,7 @@ static struct slave *bond_find_best_slave(struct bonding *bond)
  *
  * Warning: Caller must hold curr_slave_lock for writing.
  */
-static void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
+void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
 {
 	struct slave *old_active = bond->curr_active_slave;
 
@@ -1523,7 +1067,7 @@ static void bond_change_active_slave(struct bonding *bond, struct slave *new_act
  *
  * Warning: Caller must hold curr_slave_lock for writing.
  */
-static void bond_select_active_slave(struct bonding *bond)
+void bond_select_active_slave(struct bonding *bond)
 {
 	struct slave *best_slave;
 
@@ -1591,7 +1135,7 @@ static void bond_detach_slave(struct bonding *bond, struct slave *slave)
 
 /*---------------------------------- IOCTL ----------------------------------*/
 
-static int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev)
+int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev)
 {
 	dprintk("bond_dev=%p\n", bond_dev);
 	dprintk("slave_dev=%p\n", slave_dev);
@@ -1631,7 +1175,7 @@ static int bond_compute_features(struct bonding *bond)
 }
 
 /* enslave device <slave> to bond device <master> */
-static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
+int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 {
 	struct bonding *bond = bond_dev->priv;
 	struct slave *new_slave = NULL;
@@ -1644,8 +1188,8 @@ static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_de
 	if (!bond->params.use_carrier && slave_dev->ethtool_ops == NULL &&
 		slave_dev->do_ioctl == NULL) {
 		printk(KERN_WARNING DRV_NAME
-		       ": Warning : no link monitoring support for %s\n",
-		       slave_dev->name);
+		       ": %s: Warning: no link monitoring support for %s\n",
+		       bond_dev->name, slave_dev->name);
 	}
 
 	/* bond must be initialized by bond_open() before enslaving */
@@ -1666,17 +1210,17 @@ static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_de
 		dprintk("%s: NETIF_F_VLAN_CHALLENGED\n", slave_dev->name);
 		if (!list_empty(&bond->vlan_list)) {
 			printk(KERN_ERR DRV_NAME
-			       ": Error: cannot enslave VLAN "
+			       ": %s: Error: cannot enslave VLAN "
 			       "challenged slave %s on VLAN enabled "
-			       "bond %s\n", slave_dev->name,
+			       "bond %s\n", bond_dev->name, slave_dev->name,
 			       bond_dev->name);
 			return -EPERM;
 		} else {
 			printk(KERN_WARNING DRV_NAME
-			       ": Warning: enslaved VLAN challenged "
+			       ": %s: Warning: enslaved VLAN challenged "
 			       "slave %s. Adding VLANs will be blocked as "
 			       "long as %s is part of bond %s\n",
-			       slave_dev->name, slave_dev->name,
+			       bond_dev->name, slave_dev->name, slave_dev->name,
 			       bond_dev->name);
 			bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
 		}
@@ -1706,12 +1250,11 @@ static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_de
 
 	if (slave_dev->set_mac_address == NULL) {
 		printk(KERN_ERR DRV_NAME
-		       ": Error: The slave device you specified does "
-		       "not support setting the MAC address.\n");
-		printk(KERN_ERR
-		       "Your kernel likely does not support slave devices.\n");
-
-		res = -EOPNOTSUPP;
+			": %s: Error: The slave device you specified does "
+			"not support setting the MAC address. "
+			"Your kernel likely does not support slave "
+			"devices.\n", bond_dev->name);
+  		res = -EOPNOTSUPP;
 		goto err_undo_flags;
 	}
 
@@ -1827,21 +1370,21 @@ static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_de
 			 * the messages for netif_carrier.
 			 */
 			printk(KERN_WARNING DRV_NAME
-			       ": Warning: MII and ETHTOOL support not "
+			       ": %s: Warning: MII and ETHTOOL support not "
 			       "available for interface %s, and "
 			       "arp_interval/arp_ip_target module parameters "
 			       "not specified, thus bonding will not detect "
 			       "link failures! see bonding.txt for details.\n",
-			       slave_dev->name);
+			       bond_dev->name, slave_dev->name);
 		} else if (link_reporting == -1) {
 			/* unable get link status using mii/ethtool */
 			printk(KERN_WARNING DRV_NAME
-			       ": Warning: can't get link status from "
+			       ": %s: Warning: can't get link status from "
 			       "interface %s; the network driver associated "
 			       "with this interface does not support MII or "
 			       "ETHTOOL link status reporting, thus miimon "
 			       "has no effect on this interface.\n",
-			       slave_dev->name);
+			       bond_dev->name, slave_dev->name);
 		}
 	}
 
@@ -1868,15 +1411,15 @@ static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_de
 	if (bond_update_speed_duplex(new_slave) &&
 	    (new_slave->link != BOND_LINK_DOWN)) {
 		printk(KERN_WARNING DRV_NAME
-		       ": Warning: failed to get speed and duplex from %s, "
+		       ": %s: Warning: failed to get speed and duplex from %s, "
 		       "assumed to be 100Mb/sec and Full.\n",
-		       new_slave->dev->name);
+		       bond_dev->name, new_slave->dev->name);
 
 		if (bond->params.mode == BOND_MODE_8023AD) {
-			printk(KERN_WARNING
-			       "Operation of 802.3ad mode requires ETHTOOL "
+			printk(KERN_WARNING DRV_NAME
+			       ": %s: Warning: Operation of 802.3ad mode requires ETHTOOL "
 			       "support in base driver for proper aggregator "
-			       "selection.\n");
+			       "selection.\n", bond_dev->name);
 		}
 	}
 
@@ -1958,6 +1501,10 @@ static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_de
 
 	write_unlock_bh(&bond->lock);
 
+	res = bond_create_slave_symlinks(bond_dev, slave_dev);
+	if (res)
+		goto err_unset_master;
+
 	printk(KERN_INFO DRV_NAME
 	       ": %s: enslaving %s as a%s interface with a%s link.\n",
 	       bond_dev->name, slave_dev->name,
@@ -1999,7 +1546,7 @@ err_undo_flags:
  *   for Bonded connections:
  *     The first up interface should be left on and all others downed.
  */
-static int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
+int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
 {
 	struct bonding *bond = bond_dev->priv;
 	struct slave *slave, *oldcurrent;
@@ -2010,7 +1557,7 @@ static int bond_release(struct net_device *bond_dev, struct net_device *slave_de
 	if (!(slave_dev->flags & IFF_SLAVE) ||
 	    (slave_dev->master != bond_dev)) {
 		printk(KERN_ERR DRV_NAME
-		       ": Error: %s: cannot release %s.\n",
+		       ": %s: Error: cannot release %s.\n",
 		       bond_dev->name, slave_dev->name);
 		return -EINVAL;
 	}
@@ -2031,11 +1578,12 @@ static int bond_release(struct net_device *bond_dev, struct net_device *slave_de
 				 ETH_ALEN);
 	if (!mac_addr_differ && (bond->slave_cnt > 1)) {
 		printk(KERN_WARNING DRV_NAME
-		       ": Warning: the permanent HWaddr of %s "
+		       ": %s: Warning: the permanent HWaddr of %s "
 		       "- %02X:%02X:%02X:%02X:%02X:%02X - is "
 		       "still in use by %s. Set the HWaddr of "
 		       "%s to a different address to avoid "
 		       "conflicts.\n",
+		       bond_dev->name,
 		       slave_dev->name,
 		       slave->perm_hwaddr[0],
 		       slave->perm_hwaddr[1],
@@ -2111,24 +1659,28 @@ static int bond_release(struct net_device *bond_dev, struct net_device *slave_de
 			bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
 		} else {
 			printk(KERN_WARNING DRV_NAME
-			       ": Warning: clearing HW address of %s while it "
+			       ": %s: Warning: clearing HW address of %s while it "
 			       "still has VLANs.\n",
-			       bond_dev->name);
+			       bond_dev->name, bond_dev->name);
 			printk(KERN_WARNING DRV_NAME
-			       ": When re-adding slaves, make sure the bond's "
-			       "HW address matches its VLANs'.\n");
+			       ": %s: When re-adding slaves, make sure the bond's "
+			       "HW address matches its VLANs'.\n",
+			       bond_dev->name);
 		}
 	} else if ((bond_dev->features & NETIF_F_VLAN_CHALLENGED) &&
 		   !bond_has_challenged_slaves(bond)) {
 		printk(KERN_INFO DRV_NAME
-		       ": last VLAN challenged slave %s "
+		       ": %s: last VLAN challenged slave %s "
 		       "left bond %s. VLAN blocking is removed\n",
-		       slave_dev->name, bond_dev->name);
+		       bond_dev->name, slave_dev->name, bond_dev->name);
 		bond_dev->features &= ~NETIF_F_VLAN_CHALLENGED;
 	}
 
 	write_unlock_bh(&bond->lock);
 
+	/* must do this from outside any spinlocks */
+	bond_destroy_slave_symlinks(bond_dev, slave_dev);
+
 	bond_del_vlans_from_slave(bond, slave_dev);
 
 	/* If the mode USES_PRIMARY, then we should only remove its
@@ -2220,6 +1772,7 @@ static int bond_release_all(struct net_device *bond_dev)
 		 */
 		write_unlock_bh(&bond->lock);
 
+		bond_destroy_slave_symlinks(bond_dev, slave_dev);
 		bond_del_vlans_from_slave(bond, slave_dev);
 
 		/* If the mode USES_PRIMARY, then we should only remove its
@@ -2274,12 +1827,13 @@ static int bond_release_all(struct net_device *bond_dev)
 		bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
 	} else {
 		printk(KERN_WARNING DRV_NAME
-		       ": Warning: clearing HW address of %s while it "
+		       ": %s: Warning: clearing HW address of %s while it "
 		       "still has VLANs.\n",
-		       bond_dev->name);
+		       bond_dev->name, bond_dev->name);
 		printk(KERN_WARNING DRV_NAME
-		       ": When re-adding slaves, make sure the bond's "
-		       "HW address matches its VLANs'.\n");
+		       ": %s: When re-adding slaves, make sure the bond's "
+		       "HW address matches its VLANs'.\n",
+		       bond_dev->name);
 	}
 
 	printk(KERN_INFO DRV_NAME
@@ -2397,7 +1951,7 @@ static int bond_slave_info_query(struct net_device *bond_dev, struct ifslave *in
 /*-------------------------------- Monitoring -------------------------------*/
 
 /* this function is called regularly to monitor each slave's link. */
-static void bond_mii_monitor(struct net_device *bond_dev)
+void bond_mii_monitor(struct net_device *bond_dev)
 {
 	struct bonding *bond = bond_dev->priv;
 	struct slave *slave, *oldcurrent;
@@ -2596,8 +2150,11 @@ static void bond_mii_monitor(struct net_device *bond_dev)
 			break;
 		default:
 			/* Should not happen */
-			printk(KERN_ERR "bonding: Error: %s  Illegal value (link=%d)\n",
-			       slave->dev->name, slave->link);
+			printk(KERN_ERR DRV_NAME
+			       ": %s: Error: %s Illegal value (link=%d)\n",
+			       bond_dev->name,
+			       slave->dev->name,
+			       slave->link);
 			goto out;
 		} /* end of switch (slave->link) */
 
@@ -2721,7 +2278,9 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
 	struct flowi fl;
 	struct rtable *rt;
 
-	for (i = 0; (i < BOND_MAX_ARP_TARGETS) && targets[i]; i++) {
+	for (i = 0; (i < BOND_MAX_ARP_TARGETS); i++) {
+		if (!targets[i])
+			continue;
 		dprintk("basa: target %x\n", targets[i]);
 		if (list_empty(&bond->vlan_list)) {
 			dprintk("basa: empty vlan: arp_send\n");
@@ -2825,7 +2384,7 @@ static void bond_send_gratuitous_arp(struct bonding *bond)
  * arp is transmitted to generate traffic. see activebackup_arp_monitor for
  * arp monitoring in active backup mode.
  */
-static void bond_loadbalance_arp_mon(struct net_device *bond_dev)
+void bond_loadbalance_arp_mon(struct net_device *bond_dev)
 {
 	struct bonding *bond = bond_dev->priv;
 	struct slave *slave, *oldcurrent;
@@ -2963,7 +2522,7 @@ out:
  * may have received.
  * see loadbalance_arp_monitor for arp monitoring in load balancing mode
  */
-static void bond_activebackup_arp_mon(struct net_device *bond_dev)
+void bond_activebackup_arp_mon(struct net_device *bond_dev)
 {
 	struct bonding *bond = bond_dev->priv;
 	struct slave *slave;
@@ -3249,6 +2808,8 @@ static void bond_info_show_master(struct seq_file *seq)
 {
 	struct bonding *bond = seq->private;
 	struct slave *curr;
+	int i;
+	u32 target;
 
 	read_lock(&bond->curr_slave_lock);
 	curr = bond->curr_active_slave;
@@ -3257,10 +2818,17 @@ static void bond_info_show_master(struct seq_file *seq)
 	seq_printf(seq, "Bonding Mode: %s\n",
 		   bond_mode_name(bond->params.mode));
 
+	if (bond->params.mode == BOND_MODE_XOR ||
+		bond->params.mode == BOND_MODE_8023AD) {
+		seq_printf(seq, "Transmit Hash Policy: %s (%d)\n",
+			xmit_hashtype_tbl[bond->params.xmit_policy].modename,
+			bond->params.xmit_policy);
+	}
+
 	if (USES_PRIMARY(bond->params.mode)) {
 		seq_printf(seq, "Primary Slave: %s\n",
-			   (bond->params.primary[0]) ?
-			   	bond->params.primary : "None");
+			   (bond->primary_slave) ?
+			   bond->primary_slave->dev->name : "None");
 
 		seq_printf(seq, "Currently Active Slave: %s\n",
 			   (curr) ? curr->dev->name : "None");
@@ -3273,6 +2841,27 @@ static void bond_info_show_master(struct seq_file *seq)
 	seq_printf(seq, "Down Delay (ms): %d\n",
 		   bond->params.downdelay * bond->params.miimon);
 
+
+	/* ARP information */
+	if(bond->params.arp_interval > 0) {
+		int printed=0;
+		seq_printf(seq, "ARP Polling Interval (ms): %d\n",
+				bond->params.arp_interval);
+
+		seq_printf(seq, "ARP IP target/s (n.n.n.n form):");
+
+		for(i = 0; (i < BOND_MAX_ARP_TARGETS) ;i++) {
+			if (!bond->params.arp_targets[i])
+				continue;
+			if (printed)
+				seq_printf(seq, ",");
+			target = ntohl(bond->params.arp_targets[i]);
+			seq_printf(seq, " %d.%d.%d.%d", HIPQUAD(target));
+			printed = 1;
+		}
+		seq_printf(seq, "\n");
+	}
+
 	if (bond->params.mode == BOND_MODE_8023AD) {
 		struct ad_info ad_info;
 
@@ -3478,7 +3067,10 @@ static int bond_event_changename(struct bonding *bond)
 	bond_remove_proc_entry(bond);
 	bond_create_proc_entry(bond);
 #endif
-
+	down_write(&(bonding_rwsem));
+        bond_destroy_sysfs_entry(bond);
+        bond_create_sysfs_entry(bond);
+	up_write(&(bonding_rwsem));
 	return NOTIFY_DONE;
 }
 
@@ -3955,6 +3547,7 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd
 		return -EPERM;
 	}
 
+	down_write(&(bonding_rwsem));
 	slave_dev = dev_get_by_name(ifr->ifr_slave);
 
 	dprintk("slave_dev=%p: \n", slave_dev);
@@ -3987,6 +3580,7 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd
 		dev_put(slave_dev);
 	}
 
+	up_write(&(bonding_rwsem));
 	return res;
 }
 
@@ -4071,6 +3665,7 @@ static int bond_change_mtu(struct net_device *bond_dev, int new_mtu)
 	bond_for_each_slave(bond, slave, i) {
 		dprintk("s %p s->p %p c_m %p\n", slave,
 			slave->prev, slave->dev->change_mtu);
+
 		res = dev_set_mtu(slave->dev, new_mtu);
 
 		if (res) {
@@ -4397,8 +3992,9 @@ static int bond_xmit_broadcast(struct sk_buff *skb, struct net_device *bond_dev)
 				struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
 				if (!skb2) {
 					printk(KERN_ERR DRV_NAME
-					       ": Error: bond_xmit_broadcast(): "
-					       "skb_clone() failed\n");
+					       ": %s: Error: bond_xmit_broadcast(): "
+					       "skb_clone() failed\n",
+					       bond_dev->name);
 					continue;
 				}
 
@@ -4431,7 +4027,7 @@ out:
 /*
  * set bond mode specific net device operations
  */
-static inline void bond_set_mode_ops(struct bonding *bond, int mode)
+void bond_set_mode_ops(struct bonding *bond, int mode)
 {
 	struct net_device *bond_dev = bond->dev;
 
@@ -4467,7 +4063,8 @@ static inline void bond_set_mode_ops(struct bonding *bond, int mode)
 	default:
 		/* Should never happen, mode already checked */
 		printk(KERN_ERR DRV_NAME
-		       ": Error: Unknown bonding mode %d\n",
+		       ": %s: Error: Unknown bonding mode %d\n",
+		       bond_dev->name,
 		       mode);
 		break;
 	}
@@ -4491,7 +4088,7 @@ static struct ethtool_ops bond_ethtool_ops = {
  * Does not allocate but creates a /proc entry.
  * Allowed to fail.
  */
-static int __init bond_init(struct net_device *bond_dev, struct bond_params *params)
+static int bond_init(struct net_device *bond_dev, struct bond_params *params)
 {
 	struct bonding *bond = bond_dev->priv;
 
@@ -4565,7 +4162,7 @@ static int __init bond_init(struct net_device *bond_dev, struct bond_params *par
 /* De-initialize device specific data.
  * Caller must hold rtnl_lock.
  */
-static inline void bond_deinit(struct net_device *bond_dev)
+void bond_deinit(struct net_device *bond_dev)
 {
 	struct bonding *bond = bond_dev->priv;
 
@@ -4601,7 +4198,7 @@ static void bond_free_all(void)
  * Convert string input module parms.  Accept either the
  * number of the mode or its string name.
  */
-static inline int bond_parse_parm(char *mode_arg, struct bond_parm_tbl *tbl)
+int bond_parse_parm(char *mode_arg, struct bond_parm_tbl *tbl)
 {
 	int i;
 
@@ -4670,7 +4267,7 @@ static int bond_check_params(struct bond_params *params)
 	if (max_bonds < 1 || max_bonds > INT_MAX) {
 		printk(KERN_WARNING DRV_NAME
 		       ": Warning: max_bonds (%d) not in range %d-%d, so it "
-		       "was reset to BOND_DEFAULT_MAX_BONDS (%d)",
+		       "was reset to BOND_DEFAULT_MAX_BONDS (%d)\n",
 		       max_bonds, 1, INT_MAX, BOND_DEFAULT_MAX_BONDS);
 		max_bonds = BOND_DEFAULT_MAX_BONDS;
 	}
@@ -4881,81 +4478,96 @@ static int bond_check_params(struct bond_params *params)
 	return 0;
 }
 
+/* Create a new bond based on the specified name and bonding parameters.
+ * Caller must NOT hold rtnl_lock; we need to release it here before we
+ * set up our sysfs entries.
+ */
+int bond_create(char *name, struct bond_params *params, struct bonding **newbond)
+{
+	struct net_device *bond_dev;
+	int res;
+
+	rtnl_lock();
+	bond_dev = alloc_netdev(sizeof(struct bonding), name, ether_setup);
+	if (!bond_dev) {
+		printk(KERN_ERR DRV_NAME
+		       ": %s: eek! can't alloc netdev!\n",
+		       name);
+		res = -ENOMEM;
+		goto out_rtnl;
+	}
+
+	/* bond_init() must be called after dev_alloc_name() (for the
+	 * /proc files), but before register_netdevice(), because we
+	 * need to set function pointers.
+	 */
+
+	res = bond_init(bond_dev, params);
+	if (res < 0) {
+		goto out_netdev;
+	}
+
+	SET_MODULE_OWNER(bond_dev);
+
+	res = register_netdevice(bond_dev);
+	if (res < 0) {
+		goto out_bond;
+	}
+	if (newbond)
+		*newbond = bond_dev->priv;
+
+	rtnl_unlock(); /* allows sysfs registration of net device */
+	res = bond_create_sysfs_entry(bond_dev->priv);
+	goto done;
+out_bond:
+	bond_deinit(bond_dev);
+out_netdev:
+	free_netdev(bond_dev);
+out_rtnl:
+	rtnl_unlock();
+done:
+	return res;
+}
+
 static int __init bonding_init(void)
 {
-	struct bond_params params;
 	int i;
 	int res;
+	char new_bond_name[8];  /* Enough room for 999 bonds at init. */
 
 	printk(KERN_INFO "%s", version);
 
-	res = bond_check_params(&params);
+	res = bond_check_params(&bonding_defaults);
 	if (res) {
-		return res;
+		goto out;
 	}
 
-	rtnl_lock();
-
 #ifdef CONFIG_PROC_FS
 	bond_create_proc_dir();
 #endif
-
 	for (i = 0; i < max_bonds; i++) {
-		struct net_device *bond_dev;
-
-		bond_dev = alloc_netdev(sizeof(struct bonding), "", ether_setup);
-		if (!bond_dev) {
-			res = -ENOMEM;
-			goto out_err;
-		}
-
-		res = dev_alloc_name(bond_dev, "bond%d");
-		if (res < 0) {
-			free_netdev(bond_dev);
-			goto out_err;
-		}
-
-		/* bond_init() must be called after dev_alloc_name() (for the
-		 * /proc files), but before register_netdevice(), because we
-		 * need to set function pointers.
-		 */
-		res = bond_init(bond_dev, &params);
-		if (res < 0) {
-			free_netdev(bond_dev);
-			goto out_err;
-		}
-
-		SET_MODULE_OWNER(bond_dev);
-
-		res = register_netdevice(bond_dev);
-		if (res < 0) {
-			bond_deinit(bond_dev);
-			free_netdev(bond_dev);
-			goto out_err;
-		}
+		sprintf(new_bond_name, "bond%d",i);
+		res = bond_create(new_bond_name,&bonding_defaults, NULL);
+		if (res)
+			goto err;
 	}
 
-	rtnl_unlock();
+	res = bond_create_sysfs();
+	if (res)
+		goto err;
+
 	register_netdevice_notifier(&bond_netdev_notifier);
 	register_inetaddr_notifier(&bond_inetaddr_notifier);
 
-	return 0;
-
-out_err:
-	/*
-	 * rtnl_unlock() will run netdev_run_todo(), putting the
-	 * thus-far-registered bonding devices into a state which
-	 * unregigister_netdevice() will accept
-	 */
-	rtnl_unlock();
+	goto out;
+err:
 	rtnl_lock();
-
-	/* free and unregister all bonds that were successfully added */
 	bond_free_all();
-
+	bond_destroy_sysfs();
 	rtnl_unlock();
-
+out:
 	return res;
+
 }
 
 static void __exit bonding_exit(void)
@@ -4965,6 +4577,7 @@ static void __exit bonding_exit(void)
 
 	rtnl_lock();
 	bond_free_all();
+	bond_destroy_sysfs();
 	rtnl_unlock();
 }
 
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
new file mode 100644
index 000000000000..32d13da43a0b
--- /dev/null
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -0,0 +1,1358 @@
+
+/*
+ * Copyright(c) 2004-2005 Intel Corporation. All rights reserved.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/device.h>
+#include <linux/sysdev.h>
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <linux/in.h>
+#include <linux/sysfs.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/inet.h>
+#include <linux/rtnetlink.h>
+
+/* #define BONDING_DEBUG 1 */
+#include "bonding.h"
+#define to_class_dev(obj) container_of(obj,struct class_device,kobj)
+#define to_net_dev(class) container_of(class, struct net_device, class_dev)
+#define to_bond(cd)	((struct bonding *)(to_net_dev(cd)->priv))
+
+/*---------------------------- Declarations -------------------------------*/
+
+
+extern struct list_head bond_dev_list;
+extern struct bond_params bonding_defaults;
+extern struct bond_parm_tbl bond_mode_tbl[];
+extern struct bond_parm_tbl bond_lacp_tbl[];
+extern struct bond_parm_tbl xmit_hashtype_tbl[];
+
+static int expected_refcount = -1;
+static struct class *netdev_class;
+/*--------------------------- Data Structures -----------------------------*/
+
+/* Bonding sysfs lock.  Why can't we just use the subsytem lock?
+ * Because kobject_register tries to acquire the subsystem lock.  If
+ * we already hold the lock (which we would if the user was creating
+ * a new bond through the sysfs interface), we deadlock.
+ * This lock is only needed when deleting a bond - we need to make sure
+ * that we don't collide with an ongoing ioctl.
+ */
+
+struct rw_semaphore bonding_rwsem;
+
+
+
+
+/*------------------------------ Functions --------------------------------*/
+
+/*
+ * "show" function for the bond_masters attribute.
+ * The class parameter is ignored.
+ */
+static ssize_t bonding_show_bonds(struct class *cls, char *buffer)
+{
+	int res = 0;
+	struct bonding *bond;
+
+	down_read(&(bonding_rwsem));
+
+	list_for_each_entry(bond, &bond_dev_list, bond_list) {
+		if (res > (PAGE_SIZE - IFNAMSIZ)) {
+			/* not enough space for another interface name */
+			if ((PAGE_SIZE - res) > 10)
+				res = PAGE_SIZE - 10;
+			res += sprintf(buffer + res, "++more++");
+			break;
+		}
+		res += sprintf(buffer + res, "%s ",
+			       bond->dev->name);
+	}
+	res += sprintf(buffer + res, "\n");
+	res++;
+	up_read(&(bonding_rwsem));
+	return res;
+}
+
+/*
+ * "store" function for the bond_masters attribute.  This is what
+ * creates and deletes entire bonds.
+ *
+ * The class parameter is ignored.
+ *
+ */
+
+static ssize_t bonding_store_bonds(struct class *cls, const char *buffer, size_t count)
+{
+	char command[IFNAMSIZ + 1] = {0, };
+	char *ifname;
+	int res = count;
+	struct bonding *bond;
+	struct bonding *nxt;
+
+	down_write(&(bonding_rwsem));
+	sscanf(buffer, "%16s", command); /* IFNAMSIZ*/
+	ifname = command + 1;
+	if ((strlen(command) <= 1) ||
+	    !dev_valid_name(ifname))
+		goto err_no_cmd;
+
+	if (command[0] == '+') {
+
+		/* Check to see if the bond already exists. */
+		list_for_each_entry_safe(bond, nxt, &bond_dev_list, bond_list)
+			if (strnicmp(bond->dev->name, ifname, IFNAMSIZ) == 0) {
+				printk(KERN_ERR DRV_NAME
+					": cannot add bond %s; it already exists\n",
+					ifname);
+				res = -EPERM;
+				goto out;
+			}
+
+		printk(KERN_INFO DRV_NAME
+			": %s is being created...\n", ifname);
+		if (bond_create(ifname, &bonding_defaults, &bond)) {
+			printk(KERN_INFO DRV_NAME
+			": %s interface already exists. Bond creation failed.\n",
+			ifname);
+			res = -EPERM;
+		}
+		goto out;
+	}
+
+	if (command[0] == '-') {
+		list_for_each_entry_safe(bond, nxt, &bond_dev_list, bond_list)
+			if (strnicmp(bond->dev->name, ifname, IFNAMSIZ) == 0) {
+				rtnl_lock();
+				/* check the ref count on the bond's kobject.
+				 * If it's > expected, then there's a file open,
+				 * and we have to fail.
+				 */
+				if (atomic_read(&bond->dev->class_dev.kobj.kref.refcount)
+							> expected_refcount){
+					rtnl_unlock();
+					printk(KERN_INFO DRV_NAME
+						": Unable remove bond %s due to open references.\n",
+						ifname);
+					res = -EPERM;
+					goto out;
+				}
+				printk(KERN_INFO DRV_NAME
+					": %s is being deleted...\n",
+					bond->dev->name);
+				unregister_netdevice(bond->dev);
+				bond_deinit(bond->dev);
+		        	bond_destroy_sysfs_entry(bond);
+				rtnl_unlock();
+				goto out;
+			}
+
+		printk(KERN_ERR DRV_NAME
+			": unable to delete non-existent bond %s\n", ifname);
+		res = -ENODEV;
+		goto out;
+	}
+
+err_no_cmd:
+	printk(KERN_ERR DRV_NAME
+		": no command found in bonding_masters. Use +ifname or -ifname.\n");
+	res = -EPERM;
+
+	/* Always return either count or an error.  If you return 0, you'll
+	 * get called forever, which is bad.
+	 */
+out:
+	up_write(&(bonding_rwsem));
+	return res;
+}
+/* class attribute for bond_masters file.  This ends up in /sys/class/net */
+static CLASS_ATTR(bonding_masters,  S_IWUSR | S_IRUGO,
+		  bonding_show_bonds, bonding_store_bonds);
+
+int bond_create_slave_symlinks(struct net_device *master, struct net_device *slave)
+{
+	char linkname[IFNAMSIZ+7];
+	int ret = 0;
+
+	/* first, create a link from the slave back to the master */
+	ret = sysfs_create_link(&(slave->class_dev.kobj), &(master->class_dev.kobj),
+				"master");
+	if (ret)
+		return ret;
+	/* next, create a link from the master to the slave */
+	sprintf(linkname,"slave_%s",slave->name);
+	ret = sysfs_create_link(&(master->class_dev.kobj), &(slave->class_dev.kobj),
+				linkname);
+	return ret;
+
+}
+
+void bond_destroy_slave_symlinks(struct net_device *master, struct net_device *slave)
+{
+	char linkname[IFNAMSIZ+7];
+
+	sysfs_remove_link(&(slave->class_dev.kobj), "master");
+	sprintf(linkname,"slave_%s",slave->name);
+	sysfs_remove_link(&(master->class_dev.kobj), linkname);
+}
+
+
+/*
+ * Show the slaves in the current bond.
+ */
+static ssize_t bonding_show_slaves(struct class_device *cd, char *buf)
+{
+	struct slave *slave;
+	int i, res = 0;
+	struct bonding *bond = to_bond(cd);
+
+	read_lock_bh(&bond->lock);
+	bond_for_each_slave(bond, slave, i) {
+		if (res > (PAGE_SIZE - IFNAMSIZ)) {
+			/* not enough space for another interface name */
+			if ((PAGE_SIZE - res) > 10)
+				res = PAGE_SIZE - 10;
+			res += sprintf(buf + res, "++more++");
+			break;
+		}
+		res += sprintf(buf + res, "%s ", slave->dev->name);
+	}
+	read_unlock_bh(&bond->lock);
+	res += sprintf(buf + res, "\n");
+	res++;
+	return res;
+}
+
+/*
+ * Set the slaves in the current bond.  The bond interface must be
+ * up for this to succeed.
+ * This function is largely the same flow as bonding_update_bonds().
+ */
+static ssize_t bonding_store_slaves(struct class_device *cd, const char *buffer, size_t count)
+{
+	char command[IFNAMSIZ + 1] = { 0, };
+	char *ifname;
+	int i, res, found, ret = count;
+	struct slave *slave;
+	struct net_device *dev = 0;
+	struct bonding *bond = to_bond(cd);
+
+	/* Quick sanity check -- is the bond interface up? */
+	if (!(bond->dev->flags & IFF_UP)) {
+		printk(KERN_ERR DRV_NAME
+		       ": %s: Unable to update slaves because interface is down.\n",
+		       bond->dev->name);
+		ret = -EPERM;
+		goto out;
+	}
+
+	/* Note:  We can't hold bond->lock here, as bond_create grabs it. */
+
+	sscanf(buffer, "%16s", command); /* IFNAMSIZ*/
+	ifname = command + 1;
+	if ((strlen(command) <= 1) ||
+	    !dev_valid_name(ifname))
+		goto err_no_cmd;
+
+	if (command[0] == '+') {
+
+		/* Got a slave name in ifname.  Is it already in the list? */
+		found = 0;
+		read_lock_bh(&bond->lock);
+		bond_for_each_slave(bond, slave, i)
+			if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0) {
+				printk(KERN_ERR DRV_NAME
+				       ": %s: Interface %s is already enslaved!\n",
+				       bond->dev->name, ifname);
+				ret = -EPERM;
+				read_unlock_bh(&bond->lock);
+				goto out;
+			}
+
+		read_unlock_bh(&bond->lock);
+		printk(KERN_INFO DRV_NAME ": %s: Adding slave %s.\n",
+		       bond->dev->name, ifname);
+		dev = dev_get_by_name(ifname);
+		if (!dev) {
+			printk(KERN_INFO DRV_NAME
+			       ": %s: Interface %s does not exist!\n",
+			       bond->dev->name, ifname);
+			ret = -EPERM;
+			goto out;
+		}
+		else
+			dev_put(dev);
+
+		if (dev->flags & IFF_UP) {
+			printk(KERN_ERR DRV_NAME
+			       ": %s: Error: Unable to enslave %s "
+			       "because it is already up.\n",
+			       bond->dev->name, dev->name);
+			ret = -EPERM;
+			goto out;
+		}
+		/* If this is the first slave, then we need to set
+		   the master's hardware address to be the same as the
+		   slave's. */
+		if (!(*((u32 *) & (bond->dev->dev_addr[0])))) {
+			memcpy(bond->dev->dev_addr, dev->dev_addr,
+			       dev->addr_len);
+		}
+
+		/* Set the slave's MTU to match the bond */
+		if (dev->mtu != bond->dev->mtu) {
+			if (dev->change_mtu) {
+				res = dev->change_mtu(dev,
+						      bond->dev->mtu);
+				if (res) {
+					ret = res;
+					goto out;
+				}
+			} else {
+				dev->mtu = bond->dev->mtu;
+			}
+		}
+		rtnl_lock();
+		res = bond_enslave(bond->dev, dev);
+		rtnl_unlock();
+		if (res) {
+			ret = res;
+		}
+		goto out;
+	}
+
+	if (command[0] == '-') {
+		dev = NULL;
+		bond_for_each_slave(bond, slave, i)
+			if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0) {
+				dev = slave->dev;
+				break;
+			}
+		if (dev) {
+			printk(KERN_INFO DRV_NAME ": %s: Removing slave %s\n",
+				bond->dev->name, dev->name);
+			rtnl_lock();
+			res = bond_release(bond->dev, dev);
+			rtnl_unlock();
+			if (res) {
+				ret = res;
+				goto out;
+			}
+			/* set the slave MTU to the default */
+			if (dev->change_mtu) {
+				dev->change_mtu(dev, 1500);
+			} else {
+				dev->mtu = 1500;
+			}
+		}
+		else {
+			printk(KERN_ERR DRV_NAME ": unable to remove non-existent slave %s for bond %s.\n",
+				ifname, bond->dev->name);
+			ret = -ENODEV;
+		}
+		goto out;
+	}
+
+err_no_cmd:
+	printk(KERN_ERR DRV_NAME ": no command found in slaves file for bond %s. Use +ifname or -ifname.\n", bond->dev->name);
+	ret = -EPERM;
+
+out:
+	return ret;
+}
+
+static CLASS_DEVICE_ATTR(slaves, S_IRUGO | S_IWUSR, bonding_show_slaves, bonding_store_slaves);
+
+/*
+ * Show and set the bonding mode.  The bond interface must be down to
+ * change the mode.
+ */
+static ssize_t bonding_show_mode(struct class_device *cd, char *buf)
+{
+	struct bonding *bond = to_bond(cd);
+
+	return sprintf(buf, "%s %d\n",
+			bond_mode_tbl[bond->params.mode].modename,
+			bond->params.mode) + 1;
+}
+
+static ssize_t bonding_store_mode(struct class_device *cd, const char *buf, size_t count)
+{
+	int new_value, ret = count;
+	struct bonding *bond = to_bond(cd);
+
+	if (bond->dev->flags & IFF_UP) {
+		printk(KERN_ERR DRV_NAME
+		       ": unable to update mode of %s because interface is up.\n",
+		       bond->dev->name);
+		ret = -EPERM;
+		goto out;
+	}
+
+	new_value = bond_parse_parm((char *)buf, bond_mode_tbl);
+	if (new_value < 0)  {
+		printk(KERN_ERR DRV_NAME
+		       ": %s: Ignoring invalid mode value %.*s.\n",
+		       bond->dev->name,
+		       (int)strlen(buf) - 1, buf);
+		ret = -EINVAL;
+		goto out;
+	} else {
+		bond->params.mode = new_value;
+		bond_set_mode_ops(bond, bond->params.mode);
+		printk(KERN_INFO DRV_NAME ": %s: setting mode to %s (%d).\n",
+			bond->dev->name, bond_mode_tbl[new_value].modename, new_value);
+	}
+out:
+	return ret;
+}
+static CLASS_DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, bonding_show_mode, bonding_store_mode);
+
+/*
+ * Show and set the bonding transmit hash method.  The bond interface must be down to
+ * change the xmit hash policy.
+ */
+static ssize_t bonding_show_xmit_hash(struct class_device *cd, char *buf)
+{
+	int count;
+	struct bonding *bond = to_bond(cd);
+
+	if ((bond->params.mode != BOND_MODE_XOR) &&
+	    (bond->params.mode != BOND_MODE_8023AD)) {
+		// Not Applicable
+		count = sprintf(buf, "NA\n") + 1;
+	} else {
+		count = sprintf(buf, "%s %d\n",
+			xmit_hashtype_tbl[bond->params.xmit_policy].modename,
+			bond->params.xmit_policy) + 1;
+	}
+
+	return count;
+}
+
+static ssize_t bonding_store_xmit_hash(struct class_device *cd, const char *buf, size_t count)
+{
+	int new_value, ret = count;
+	struct bonding *bond = to_bond(cd);
+
+	if (bond->dev->flags & IFF_UP) {
+		printk(KERN_ERR DRV_NAME
+		       "%s: Interface is up. Unable to update xmit policy.\n",
+		       bond->dev->name);
+		ret = -EPERM;
+		goto out;
+	}
+
+	if ((bond->params.mode != BOND_MODE_XOR) &&
+	    (bond->params.mode != BOND_MODE_8023AD)) {
+		printk(KERN_ERR DRV_NAME
+		       "%s: Transmit hash policy is irrelevant in this mode.\n",
+		       bond->dev->name);
+		ret = -EPERM;
+		goto out;
+	}
+
+	new_value = bond_parse_parm((char *)buf, xmit_hashtype_tbl);
+	if (new_value < 0)  {
+		printk(KERN_ERR DRV_NAME
+		       ": %s: Ignoring invalid xmit hash policy value %.*s.\n",
+		       bond->dev->name,
+		       (int)strlen(buf) - 1, buf);
+		ret = -EINVAL;
+		goto out;
+	} else {
+		bond->params.xmit_policy = new_value;
+		bond_set_mode_ops(bond, bond->params.mode);
+		printk(KERN_INFO DRV_NAME ": %s: setting xmit hash policy to %s (%d).\n",
+			bond->dev->name, xmit_hashtype_tbl[new_value].modename, new_value);
+	}
+out:
+	return ret;
+}
+static CLASS_DEVICE_ATTR(xmit_hash_policy, S_IRUGO | S_IWUSR, bonding_show_xmit_hash, bonding_store_xmit_hash);
+
+/*
+ * Show and set the arp timer interval.  There are two tricky bits
+ * here.  First, if ARP monitoring is activated, then we must disable
+ * MII monitoring.  Second, if the ARP timer isn't running, we must
+ * start it.
+ */
+static ssize_t bonding_show_arp_interval(struct class_device *cd, char *buf)
+{
+	struct bonding *bond = to_bond(cd);
+
+	return sprintf(buf, "%d\n", bond->params.arp_interval) + 1;
+}
+
+static ssize_t bonding_store_arp_interval(struct class_device *cd, const char *buf, size_t count)
+{
+	int new_value, ret = count;
+	struct bonding *bond = to_bond(cd);
+
+	if (sscanf(buf, "%d", &new_value) != 1) {
+		printk(KERN_ERR DRV_NAME
+		       ": %s: no arp_interval value specified.\n",
+		       bond->dev->name);
+		ret = -EINVAL;
+		goto out;
+	}
+	if (new_value < 0) {
+		printk(KERN_ERR DRV_NAME
+		       ": %s: Invalid arp_interval value %d not in range 1-%d; rejected.\n",
+		       bond->dev->name, new_value, INT_MAX);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	printk(KERN_INFO DRV_NAME
+	       ": %s: Setting ARP monitoring interval to %d.\n",
+	       bond->dev->name, new_value);
+	bond->params.arp_interval = new_value;
+	if (bond->params.miimon) {
+		printk(KERN_INFO DRV_NAME
+		       ": %s: ARP monitoring cannot be used with MII monitoring. "
+		       "%s Disabling MII monitoring.\n",
+		       bond->dev->name, bond->dev->name);
+		bond->params.miimon = 0;
+		/* Kill MII timer, else it brings bond's link down */
+		if (bond->arp_timer.function) {
+			printk(KERN_INFO DRV_NAME
+			": %s: Kill MII timer, else it brings bond's link down...\n",
+		       bond->dev->name);
+			del_timer_sync(&bond->mii_timer);
+		}
+	}
+	if (!bond->params.arp_targets[0]) {
+		printk(KERN_INFO DRV_NAME
+		       ": %s: ARP monitoring has been set up, "
+		       "but no ARP targets have been specified.\n",
+		       bond->dev->name);
+	}
+	if (bond->dev->flags & IFF_UP) {
+		/* If the interface is up, we may need to fire off
+		 * the ARP timer.  If the interface is down, the
+		 * timer will get fired off when the open function
+		 * is called.
+		 */
+		if (bond->arp_timer.function) {
+			/* The timer's already set up, so fire it off */
+			mod_timer(&bond->arp_timer, jiffies + 1);
+		} else {
+			/* Set up the timer. */
+			init_timer(&bond->arp_timer);
+			bond->arp_timer.expires = jiffies + 1;
+			bond->arp_timer.data =
+				(unsigned long) bond->dev;
+			if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) {
+				bond->arp_timer.function =
+					(void *)
+					&bond_activebackup_arp_mon;
+			} else {
+				bond->arp_timer.function =
+					(void *)
+					&bond_loadbalance_arp_mon;
+			}
+			add_timer(&bond->arp_timer);
+		}
+	}
+
+out:
+	return ret;
+}
+static CLASS_DEVICE_ATTR(arp_interval, S_IRUGO | S_IWUSR , bonding_show_arp_interval, bonding_store_arp_interval);
+
+/*
+ * Show and set the arp targets.
+ */
+static ssize_t bonding_show_arp_targets(struct class_device *cd, char *buf)
+{
+	int i, res = 0;
+	struct bonding *bond = to_bond(cd);
+
+	for (i = 0; i < BOND_MAX_ARP_TARGETS; i++) {
+		if (bond->params.arp_targets[i])
+			res += sprintf(buf + res, "%u.%u.%u.%u ",
+			       NIPQUAD(bond->params.arp_targets[i]));
+	}
+	if (res)
+		res--;  /* eat the leftover space */
+	res += sprintf(buf + res, "\n");
+	res++;
+	return res;
+}
+
+static ssize_t bonding_store_arp_targets(struct class_device *cd, const char *buf, size_t count)
+{
+	u32 newtarget;
+	int i = 0, done = 0, ret = count;
+	struct bonding *bond = to_bond(cd);
+	u32 *targets;
+
+	targets = bond->params.arp_targets;
+	newtarget = in_aton(buf + 1);
+	/* look for adds */
+	if (buf[0] == '+') {
+		if ((newtarget == 0) || (newtarget == INADDR_BROADCAST)) {
+			printk(KERN_ERR DRV_NAME
+			       ": %s: invalid ARP target %u.%u.%u.%u specified for addition\n",
+ 			       bond->dev->name, NIPQUAD(newtarget));
+			ret = -EINVAL;
+			goto out;
+		}
+		/* look for an empty slot to put the target in, and check for dupes */
+		for (i = 0; (i < BOND_MAX_ARP_TARGETS); i++) {
+			if (targets[i] == newtarget) { /* duplicate */
+				printk(KERN_ERR DRV_NAME
+				       ": %s: ARP target %u.%u.%u.%u is already present\n",
+				       bond->dev->name, NIPQUAD(newtarget));
+				if (done)
+					targets[i] = 0;
+				ret = -EINVAL;
+				goto out;
+			}
+			if (targets[i] == 0 && !done) {
+				printk(KERN_INFO DRV_NAME
+				       ": %s: adding ARP target %d.%d.%d.%d.\n",
+				       bond->dev->name, NIPQUAD(newtarget));
+				done = 1;
+				targets[i] = newtarget;
+			}
+		}
+		if (!done) {
+			printk(KERN_ERR DRV_NAME
+			       ": %s: ARP target table is full!\n",
+			       bond->dev->name);
+			ret = -EINVAL;
+			goto out;
+		}
+
+	}
+	else if (buf[0] == '-')	{
+		if ((newtarget == 0) || (newtarget == INADDR_BROADCAST)) {
+			printk(KERN_ERR DRV_NAME
+			       ": %s: invalid ARP target %d.%d.%d.%d specified for removal\n",
+			       bond->dev->name, NIPQUAD(newtarget));
+			ret = -EINVAL;
+			goto out;
+		}
+
+		for (i = 0; (i < BOND_MAX_ARP_TARGETS); i++) {
+			if (targets[i] == newtarget) {
+				printk(KERN_INFO DRV_NAME
+				       ": %s: removing ARP target %d.%d.%d.%d.\n",
+				       bond->dev->name, NIPQUAD(newtarget));
+				targets[i] = 0;
+				done = 1;
+			}
+		}
+		if (!done) {
+			printk(KERN_INFO DRV_NAME
+			       ": %s: unable to remove nonexistent ARP target %d.%d.%d.%d.\n",
+			       bond->dev->name, NIPQUAD(newtarget));
+			ret = -EINVAL;
+			goto out;
+		}
+	}
+	else {
+		printk(KERN_ERR DRV_NAME ": no command found in arp_ip_targets file for bond %s. Use +<addr> or -<addr>.\n",
+			bond->dev->name);
+		ret = -EPERM;
+		goto out;
+	}
+
+out:
+	return ret;
+}
+static CLASS_DEVICE_ATTR(arp_ip_target, S_IRUGO | S_IWUSR , bonding_show_arp_targets, bonding_store_arp_targets);
+
+/*
+ * Show and set the up and down delays.  These must be multiples of the
+ * MII monitoring value, and are stored internally as the multiplier.
+ * Thus, we must translate to MS for the real world.
+ */
+static ssize_t bonding_show_downdelay(struct class_device *cd, char *buf)
+{
+	struct bonding *bond = to_bond(cd);
+
+	return sprintf(buf, "%d\n", bond->params.downdelay * bond->params.miimon) + 1;
+}
+
+static ssize_t bonding_store_downdelay(struct class_device *cd, const char *buf, size_t count)
+{
+	int new_value, ret = count;
+	struct bonding *bond = to_bond(cd);
+
+	if (!(bond->params.miimon)) {
+		printk(KERN_ERR DRV_NAME
+		       ": %s: Unable to set down delay as MII monitoring is disabled\n",
+		       bond->dev->name);
+		ret = -EPERM;
+		goto out;
+	}
+
+	if (sscanf(buf, "%d", &new_value) != 1) {
+		printk(KERN_ERR DRV_NAME
+		       ": %s: no down delay value specified.\n",
+		       bond->dev->name);
+		ret = -EINVAL;
+		goto out;
+	}
+	if (new_value < 0) {
+		printk(KERN_ERR DRV_NAME
+		       ": %s: Invalid down delay value %d not in range %d-%d; rejected.\n",
+		       bond->dev->name, new_value, 1, INT_MAX);
+		ret = -EINVAL;
+		goto out;
+	} else {
+		if ((new_value % bond->params.miimon) != 0) {
+			printk(KERN_WARNING DRV_NAME
+			       ": %s: Warning: down delay (%d) is not a multiple "
+			       "of miimon (%d), delay rounded to %d ms\n",
+			       bond->dev->name, new_value, bond->params.miimon,
+			       (new_value / bond->params.miimon) *
+			       bond->params.miimon);
+		}
+		bond->params.downdelay = new_value / bond->params.miimon;
+		printk(KERN_INFO DRV_NAME ": %s: Setting down delay to %d.\n",
+		       bond->dev->name, bond->params.downdelay * bond->params.miimon);
+
+	}
+
+out:
+	return ret;
+}
+static CLASS_DEVICE_ATTR(downdelay, S_IRUGO | S_IWUSR , bonding_show_downdelay, bonding_store_downdelay);
+
+static ssize_t bonding_show_updelay(struct class_device *cd, char *buf)
+{
+	struct bonding *bond = to_bond(cd);
+
+	return sprintf(buf, "%d\n", bond->params.updelay * bond->params.miimon) + 1;
+
+}
+
+static ssize_t bonding_store_updelay(struct class_device *cd, const char *buf, size_t count)
+{
+	int new_value, ret = count;
+	struct bonding *bond = to_bond(cd);
+
+	if (!(bond->params.miimon)) {
+		printk(KERN_ERR DRV_NAME
+		       ": %s: Unable to set up delay as MII monitoring is disabled\n",
+		       bond->dev->name);
+		ret = -EPERM;
+		goto out;
+	}
+
+	if (sscanf(buf, "%d", &new_value) != 1) {
+		printk(KERN_ERR DRV_NAME
+		       ": %s: no up delay value specified.\n",
+		       bond->dev->name);
+		ret = -EINVAL;
+		goto out;
+	}
+	if (new_value < 0) {
+		printk(KERN_ERR DRV_NAME
+		       ": %s: Invalid down delay value %d not in range %d-%d; rejected.\n",
+		       bond->dev->name, new_value, 1, INT_MAX);
+		ret = -EINVAL;
+		goto out;
+	} else {
+		if ((new_value % bond->params.miimon) != 0) {
+			printk(KERN_WARNING DRV_NAME
+			       ": %s: Warning: up delay (%d) is not a multiple "
+			       "of miimon (%d), updelay rounded to %d ms\n",
+			       bond->dev->name, new_value, bond->params.miimon,
+			       (new_value / bond->params.miimon) *
+			       bond->params.miimon);
+		}
+		bond->params.updelay = new_value / bond->params.miimon;
+		printk(KERN_INFO DRV_NAME ": %s: Setting up delay to %d.\n",
+		       bond->dev->name, bond->params.updelay * bond->params.miimon);
+
+	}
+
+out:
+	return ret;
+}
+static CLASS_DEVICE_ATTR(updelay, S_IRUGO | S_IWUSR , bonding_show_updelay, bonding_store_updelay);
+
+/*
+ * Show and set the LACP interval.  Interface must be down, and the mode
+ * must be set to 802.3ad mode.
+ */
+static ssize_t bonding_show_lacp(struct class_device *cd, char *buf)
+{
+	struct bonding *bond = to_bond(cd);
+
+	return sprintf(buf, "%s %d\n",
+		bond_lacp_tbl[bond->params.lacp_fast].modename,
+		bond->params.lacp_fast) + 1;
+}
+
+static ssize_t bonding_store_lacp(struct class_device *cd, const char *buf, size_t count)
+{
+	int new_value, ret = count;
+	struct bonding *bond = to_bond(cd);
+
+	if (bond->dev->flags & IFF_UP) {
+		printk(KERN_ERR DRV_NAME
+		       ": %s: Unable to update LACP rate because interface is up.\n",
+		       bond->dev->name);
+		ret = -EPERM;
+		goto out;
+	}
+
+	if (bond->params.mode != BOND_MODE_8023AD) {
+		printk(KERN_ERR DRV_NAME
+		       ": %s: Unable to update LACP rate because bond is not in 802.3ad mode.\n",
+		       bond->dev->name);
+		ret = -EPERM;
+		goto out;
+	}
+
+	new_value = bond_parse_parm((char *)buf, bond_lacp_tbl);
+
+	if ((new_value == 1) || (new_value == 0)) {
+		bond->params.lacp_fast = new_value;
+		printk(KERN_INFO DRV_NAME
+		       ": %s: Setting LACP rate to %s (%d).\n",
+		       bond->dev->name, bond_lacp_tbl[new_value].modename, new_value);
+	} else {
+		printk(KERN_ERR DRV_NAME
+		       ": %s: Ignoring invalid LACP rate value %.*s.\n",
+		     	bond->dev->name, (int)strlen(buf) - 1, buf);
+		ret = -EINVAL;
+	}
+out:
+	return ret;
+}
+static CLASS_DEVICE_ATTR(lacp_rate, S_IRUGO | S_IWUSR, bonding_show_lacp, bonding_store_lacp);
+
+/*
+ * Show and set the MII monitor interval.  There are two tricky bits
+ * here.  First, if MII monitoring is activated, then we must disable
+ * ARP monitoring.  Second, if the timer isn't running, we must
+ * start it.
+ */
+static ssize_t bonding_show_miimon(struct class_device *cd, char *buf)
+{
+	struct bonding *bond = to_bond(cd);
+
+	return sprintf(buf, "%d\n", bond->params.miimon) + 1;
+}
+
+static ssize_t bonding_store_miimon(struct class_device *cd, const char *buf, size_t count)
+{
+	int new_value, ret = count;
+	struct bonding *bond = to_bond(cd);
+
+	if (sscanf(buf, "%d", &new_value) != 1) {
+		printk(KERN_ERR DRV_NAME
+		       ": %s: no miimon value specified.\n",
+		       bond->dev->name);
+		ret = -EINVAL;
+		goto out;
+	}
+	if (new_value < 0) {
+		printk(KERN_ERR DRV_NAME
+		       ": %s: Invalid miimon value %d not in range %d-%d; rejected.\n",
+		       bond->dev->name, new_value, 1, INT_MAX);
+		ret = -EINVAL;
+		goto out;
+	} else {
+		printk(KERN_INFO DRV_NAME
+		       ": %s: Setting MII monitoring interval to %d.\n",
+		       bond->dev->name, new_value);
+		bond->params.miimon = new_value;
+		if(bond->params.updelay)
+			printk(KERN_INFO DRV_NAME
+			      ": %s: Note: Updating updelay (to %d) "
+			      "since it is a multiple of the miimon value.\n",
+			      bond->dev->name,
+			      bond->params.updelay * bond->params.miimon);
+		if(bond->params.downdelay)
+			printk(KERN_INFO DRV_NAME
+			      ": %s: Note: Updating downdelay (to %d) "
+			      "since it is a multiple of the miimon value.\n",
+			      bond->dev->name,
+			      bond->params.downdelay * bond->params.miimon);
+		if (bond->params.arp_interval) {
+			printk(KERN_INFO DRV_NAME
+			       ": %s: MII monitoring cannot be used with "
+			       "ARP monitoring. Disabling ARP monitoring...\n",
+			       bond->dev->name);
+			bond->params.arp_interval = 0;
+			/* Kill ARP timer, else it brings bond's link down */
+			if (bond->mii_timer.function) {
+				printk(KERN_INFO DRV_NAME
+				": %s: Kill ARP timer, else it brings bond's link down...\n",
+			       bond->dev->name);
+				del_timer_sync(&bond->arp_timer);
+			}
+		}
+
+		if (bond->dev->flags & IFF_UP) {
+			/* If the interface is up, we may need to fire off
+			 * the MII timer. If the interface is down, the
+			 * timer will get fired off when the open function
+			 * is called.
+			 */
+			if (bond->mii_timer.function) {
+				/* The timer's already set up, so fire it off */
+				mod_timer(&bond->mii_timer, jiffies + 1);
+			} else {
+				/* Set up the timer. */
+				init_timer(&bond->mii_timer);
+				bond->mii_timer.expires = jiffies + 1;
+				bond->mii_timer.data =
+					(unsigned long) bond->dev;
+				bond->mii_timer.function =
+					(void *) &bond_mii_monitor;
+				add_timer(&bond->mii_timer);
+			}
+		}
+	}
+out:
+	return ret;
+}
+static CLASS_DEVICE_ATTR(miimon, S_IRUGO | S_IWUSR, bonding_show_miimon, bonding_store_miimon);
+
+/*
+ * Show and set the primary slave.  The store function is much
+ * simpler than bonding_store_slaves function because it only needs to
+ * handle one interface name.
+ * The bond must be a mode that supports a primary for this be
+ * set.
+ */
+static ssize_t bonding_show_primary(struct class_device *cd, char *buf)
+{
+	int count = 0;
+	struct bonding *bond = to_bond(cd);
+
+	if (bond->primary_slave)
+		count = sprintf(buf, "%s\n", bond->primary_slave->dev->name) + 1;
+	else
+		count = sprintf(buf, "\n") + 1;
+
+	return count;
+}
+
+static ssize_t bonding_store_primary(struct class_device *cd, const char *buf, size_t count)
+{
+	int i;
+	struct slave *slave;
+	struct bonding *bond = to_bond(cd);
+
+	write_lock_bh(&bond->lock);
+	if (!USES_PRIMARY(bond->params.mode)) {
+		printk(KERN_INFO DRV_NAME
+		       ": %s: Unable to set primary slave; %s is in mode %d\n",
+		       bond->dev->name, bond->dev->name, bond->params.mode);
+	} else {
+		bond_for_each_slave(bond, slave, i) {
+			if (strnicmp
+			    (slave->dev->name, buf,
+			     strlen(slave->dev->name)) == 0) {
+				printk(KERN_INFO DRV_NAME
+				       ": %s: Setting %s as primary slave.\n",
+				       bond->dev->name, slave->dev->name);
+				bond->primary_slave = slave;
+				bond_select_active_slave(bond);
+				goto out;
+			}
+		}
+
+		/* if we got here, then we didn't match the name of any slave */
+
+		if (strlen(buf) == 0 || buf[0] == '\n') {
+			printk(KERN_INFO DRV_NAME
+			       ": %s: Setting primary slave to None.\n",
+			       bond->dev->name);
+			bond->primary_slave = 0;
+				bond_select_active_slave(bond);
+		} else {
+			printk(KERN_INFO DRV_NAME
+			       ": %s: Unable to set %.*s as primary slave as it is not a slave.\n",
+			       bond->dev->name, (int)strlen(buf) - 1, buf);
+		}
+	}
+out:
+	write_unlock_bh(&bond->lock);
+	return count;
+}
+static CLASS_DEVICE_ATTR(primary, S_IRUGO | S_IWUSR, bonding_show_primary, bonding_store_primary);
+
+/*
+ * Show and set the use_carrier flag.
+ */
+static ssize_t bonding_show_carrier(struct class_device *cd, char *buf)
+{
+	struct bonding *bond = to_bond(cd);
+
+	return sprintf(buf, "%d\n", bond->params.use_carrier) + 1;
+}
+
+static ssize_t bonding_store_carrier(struct class_device *cd, const char *buf, size_t count)
+{
+	int new_value, ret = count;
+	struct bonding *bond = to_bond(cd);
+
+
+	if (sscanf(buf, "%d", &new_value) != 1) {
+		printk(KERN_ERR DRV_NAME
+		       ": %s: no use_carrier value specified.\n",
+		       bond->dev->name);
+		ret = -EINVAL;
+		goto out;
+	}
+	if ((new_value == 0) || (new_value == 1)) {
+		bond->params.use_carrier = new_value;
+		printk(KERN_INFO DRV_NAME ": %s: Setting use_carrier to %d.\n",
+		       bond->dev->name, new_value);
+	} else {
+		printk(KERN_INFO DRV_NAME
+		       ": %s: Ignoring invalid use_carrier value %d.\n",
+		       bond->dev->name, new_value);
+	}
+out:
+	return count;
+}
+static CLASS_DEVICE_ATTR(use_carrier, S_IRUGO | S_IWUSR, bonding_show_carrier, bonding_store_carrier);
+
+
+/*
+ * Show and set currently active_slave.
+ */
+static ssize_t bonding_show_active_slave(struct class_device *cd, char *buf)
+{
+	struct slave *curr;
+	struct bonding *bond = to_bond(cd);
+	int count;
+
+
+	read_lock(&bond->curr_slave_lock);
+	curr = bond->curr_active_slave;
+	read_unlock(&bond->curr_slave_lock);
+
+	if (USES_PRIMARY(bond->params.mode) && curr)
+		count = sprintf(buf, "%s\n", curr->dev->name) + 1;
+	else
+		count = sprintf(buf, "\n") + 1;
+	return count;
+}
+
+static ssize_t bonding_store_active_slave(struct class_device *cd, const char *buf, size_t count)
+{
+	int i;
+	struct slave *slave;
+        struct slave *old_active = NULL;
+        struct slave *new_active = NULL;
+	struct bonding *bond = to_bond(cd);
+
+	write_lock_bh(&bond->lock);
+	if (!USES_PRIMARY(bond->params.mode)) {
+		printk(KERN_INFO DRV_NAME
+		       ": %s: Unable to change active slave; %s is in mode %d\n",
+		       bond->dev->name, bond->dev->name, bond->params.mode);
+	} else {
+		bond_for_each_slave(bond, slave, i) {
+			if (strnicmp
+			    (slave->dev->name, buf,
+			     strlen(slave->dev->name)) == 0) {
+        			old_active = bond->curr_active_slave;
+        			new_active = slave;
+        			if (new_active && (new_active == old_active)) {
+					/* do nothing */
+					printk(KERN_INFO DRV_NAME
+				       	       ": %s: %s is already the current active slave.\n",
+				               bond->dev->name, slave->dev->name);
+					goto out;
+				}
+				else {
+        				if ((new_active) &&
+            				    (old_active) &&
+				            (new_active->link == BOND_LINK_UP) &&
+				            IS_UP(new_active->dev)) {
+						printk(KERN_INFO DRV_NAME
+				       	              ": %s: Setting %s as active slave.\n",
+				                      bond->dev->name, slave->dev->name);
+                				bond_change_active_slave(bond, new_active);
+        				}
+					else {
+						printk(KERN_INFO DRV_NAME
+				       	              ": %s: Could not set %s as active slave; "
+						      "either %s is down or the link is down.\n",
+				                      bond->dev->name, slave->dev->name,
+						      slave->dev->name);
+					}
+					goto out;
+				}
+			}
+		}
+
+		/* if we got here, then we didn't match the name of any slave */
+
+		if (strlen(buf) == 0 || buf[0] == '\n') {
+			printk(KERN_INFO DRV_NAME
+			       ": %s: Setting active slave to None.\n",
+			       bond->dev->name);
+			bond->primary_slave = 0;
+				bond_select_active_slave(bond);
+		} else {
+			printk(KERN_INFO DRV_NAME
+			       ": %s: Unable to set %.*s as active slave as it is not a slave.\n",
+			       bond->dev->name, (int)strlen(buf) - 1, buf);
+		}
+	}
+out:
+	write_unlock_bh(&bond->lock);
+	return count;
+
+}
+static CLASS_DEVICE_ATTR(active_slave, S_IRUGO | S_IWUSR, bonding_show_active_slave, bonding_store_active_slave);
+
+
+/*
+ * Show link status of the bond interface.
+ */
+static ssize_t bonding_show_mii_status(struct class_device *cd, char *buf)
+{
+	struct slave *curr;
+	struct bonding *bond = to_bond(cd);
+
+	read_lock(&bond->curr_slave_lock);
+	curr = bond->curr_active_slave;
+	read_unlock(&bond->curr_slave_lock);
+
+	return sprintf(buf, "%s\n", (curr) ? "up" : "down") + 1;
+}
+static CLASS_DEVICE_ATTR(mii_status, S_IRUGO, bonding_show_mii_status, NULL);
+
+
+/*
+ * Show current 802.3ad aggregator ID.
+ */
+static ssize_t bonding_show_ad_aggregator(struct class_device *cd, char *buf)
+{
+	int count = 0;
+	struct bonding *bond = to_bond(cd);
+
+	if (bond->params.mode == BOND_MODE_8023AD) {
+		struct ad_info ad_info;
+		count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ?  0 : ad_info.aggregator_id) + 1;
+	}
+	else
+		count = sprintf(buf, "\n") + 1;
+
+	return count;
+}
+static CLASS_DEVICE_ATTR(ad_aggregator, S_IRUGO, bonding_show_ad_aggregator, NULL);
+
+
+/*
+ * Show number of active 802.3ad ports.
+ */
+static ssize_t bonding_show_ad_num_ports(struct class_device *cd, char *buf)
+{
+	int count = 0;
+	struct bonding *bond = to_bond(cd);
+
+	if (bond->params.mode == BOND_MODE_8023AD) {
+		struct ad_info ad_info;
+		count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ?  0: ad_info.ports) + 1;
+	}
+	else
+		count = sprintf(buf, "\n") + 1;
+
+	return count;
+}
+static CLASS_DEVICE_ATTR(ad_num_ports, S_IRUGO, bonding_show_ad_num_ports, NULL);
+
+
+/*
+ * Show current 802.3ad actor key.
+ */
+static ssize_t bonding_show_ad_actor_key(struct class_device *cd, char *buf)
+{
+	int count = 0;
+	struct bonding *bond = to_bond(cd);
+
+	if (bond->params.mode == BOND_MODE_8023AD) {
+		struct ad_info ad_info;
+		count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ?  0 : ad_info.actor_key) + 1;
+	}
+	else
+		count = sprintf(buf, "\n") + 1;
+
+	return count;
+}
+static CLASS_DEVICE_ATTR(ad_actor_key, S_IRUGO, bonding_show_ad_actor_key, NULL);
+
+
+/*
+ * Show current 802.3ad partner key.
+ */
+static ssize_t bonding_show_ad_partner_key(struct class_device *cd, char *buf)
+{
+	int count = 0;
+	struct bonding *bond = to_bond(cd);
+
+	if (bond->params.mode == BOND_MODE_8023AD) {
+		struct ad_info ad_info;
+		count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ?  0 : ad_info.partner_key) + 1;
+	}
+	else
+		count = sprintf(buf, "\n") + 1;
+
+	return count;
+}
+static CLASS_DEVICE_ATTR(ad_partner_key, S_IRUGO, bonding_show_ad_partner_key, NULL);
+
+
+/*
+ * Show current 802.3ad partner mac.
+ */
+static ssize_t bonding_show_ad_partner_mac(struct class_device *cd, char *buf)
+{
+	int count = 0;
+	struct bonding *bond = to_bond(cd);
+
+	if (bond->params.mode == BOND_MODE_8023AD) {
+		struct ad_info ad_info;
+		if (!bond_3ad_get_active_agg_info(bond, &ad_info)) {
+			count = sprintf(buf,"%02x:%02x:%02x:%02x:%02x:%02x\n",
+				       ad_info.partner_system[0],
+				       ad_info.partner_system[1],
+				       ad_info.partner_system[2],
+				       ad_info.partner_system[3],
+				       ad_info.partner_system[4],
+				       ad_info.partner_system[5]) + 1;
+		}
+	}
+	else
+		count = sprintf(buf, "\n") + 1;
+
+	return count;
+}
+static CLASS_DEVICE_ATTR(ad_partner_mac, S_IRUGO, bonding_show_ad_partner_mac, NULL);
+
+
+
+static struct attribute *per_bond_attrs[] = {
+	&class_device_attr_slaves.attr,
+	&class_device_attr_mode.attr,
+	&class_device_attr_arp_interval.attr,
+	&class_device_attr_arp_ip_target.attr,
+	&class_device_attr_downdelay.attr,
+	&class_device_attr_updelay.attr,
+	&class_device_attr_lacp_rate.attr,
+	&class_device_attr_xmit_hash_policy.attr,
+	&class_device_attr_miimon.attr,
+	&class_device_attr_primary.attr,
+	&class_device_attr_use_carrier.attr,
+	&class_device_attr_active_slave.attr,
+	&class_device_attr_mii_status.attr,
+	&class_device_attr_ad_aggregator.attr,
+	&class_device_attr_ad_num_ports.attr,
+	&class_device_attr_ad_actor_key.attr,
+	&class_device_attr_ad_partner_key.attr,
+	&class_device_attr_ad_partner_mac.attr,
+	NULL,
+};
+
+static struct attribute_group bonding_group = {
+	.name = "bonding",
+	.attrs = per_bond_attrs,
+};
+
+/*
+ * Initialize sysfs.  This sets up the bonding_masters file in
+ * /sys/class/net.
+ */
+int bond_create_sysfs(void)
+{
+	int ret = 0;
+	struct bonding *firstbond;
+
+	init_rwsem(&bonding_rwsem);
+
+	/* get the netdev class pointer */
+	firstbond = container_of(bond_dev_list.next, struct bonding, bond_list);
+	if (!firstbond)
+		return -ENODEV;
+
+	netdev_class = firstbond->dev->class_dev.class;
+	if (!netdev_class)
+		return -ENODEV;
+
+	ret = class_create_file(netdev_class, &class_attr_bonding_masters);
+
+	return ret;
+
+}
+
+/*
+ * Remove /sys/class/net/bonding_masters.
+ */
+void bond_destroy_sysfs(void)
+{
+	if (netdev_class)
+		class_remove_file(netdev_class, &class_attr_bonding_masters);
+}
+
+/*
+ * Initialize sysfs for each bond.  This sets up and registers
+ * the 'bondctl' directory for each individual bond under /sys/class/net.
+ */
+int bond_create_sysfs_entry(struct bonding *bond)
+{
+	struct net_device *dev = bond->dev;
+	int err;
+
+	err = sysfs_create_group(&(dev->class_dev.kobj), &bonding_group);
+	if (err) {
+		printk(KERN_EMERG "eek! didn't create group!\n");
+	}
+
+	if (expected_refcount < 1)
+		expected_refcount = atomic_read(&bond->dev->class_dev.kobj.kref.refcount);
+
+	return err;
+}
+/*
+ * Remove sysfs entries for each bond.
+ */
+void bond_destroy_sysfs_entry(struct bonding *bond)
+{
+	struct net_device *dev = bond->dev;
+
+	sysfs_remove_group(&(dev->class_dev.kobj), &bonding_group);
+}
+
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index 1433e91db0f7..015c7f1d1bc0 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -10,25 +10,6 @@
  *	This software may be used and distributed according to the terms
  *	of the GNU Public License, incorporated herein by reference.
  *
- *
- * 2003/03/18 - Amir Noam <amir.noam at intel dot com>,
- *		Tsippy Mendelson <tsippy.mendelson at intel dot com> and
- *		Shmulik Hen <shmulik.hen at intel dot com>
- *	- Added support for IEEE 802.3ad Dynamic link aggregation mode.
- *
- * 2003/05/01 - Tsippy Mendelson <tsippy.mendelson at intel dot com> and
- *		Amir Noam <amir.noam at intel dot com>
- *	- Code beautification and style changes (mainly in comments).
- *
- * 2003/05/01 - Shmulik Hen <shmulik.hen at intel dot com>
- *	- Added support for Transmit load balancing mode.
- *
- * 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
- *	- Code cleanup and style changes
- *
- * 2005/05/05 - Jason Gabler <jygabler at lbl dot gov>
- *      - added "xmit_policy" kernel parameter for alternate hashing policy
- *	  support for mode 2
  */
 
 #ifndef _LINUX_BONDING_H
@@ -37,11 +18,12 @@
 #include <linux/timer.h>
 #include <linux/proc_fs.h>
 #include <linux/if_bonding.h>
+#include <linux/kobject.h>
 #include "bond_3ad.h"
 #include "bond_alb.h"
 
-#define DRV_VERSION	"2.6.5"
-#define DRV_RELDATE	"November 4, 2005"
+#define DRV_VERSION	"3.0.0"
+#define DRV_RELDATE	"November 8, 2005"
 #define DRV_NAME	"bonding"
 #define DRV_DESCRIPTION	"Ethernet Channel Bonding Driver"
 
@@ -152,6 +134,11 @@ struct bond_params {
 	u32 arp_targets[BOND_MAX_ARP_TARGETS];
 };
 
+struct bond_parm_tbl {
+	char *modename;
+	int mode;
+};
+
 struct vlan_entry {
 	struct list_head vlan_list;
 	u32 vlan_ip;
@@ -159,7 +146,7 @@ struct vlan_entry {
 };
 
 struct slave {
-	struct net_device *dev; /* first - usefull for panic debug */
+	struct net_device *dev; /* first - useful for panic debug */
 	struct slave *next;
 	struct slave *prev;
 	s16    delay;
@@ -185,7 +172,7 @@ struct slave {
  *    beforehand.
  */
 struct bonding {
-	struct   net_device *dev; /* first - usefull for panic debug */
+	struct   net_device *dev; /* first - useful for panic debug */
 	struct   slave *first_slave;
 	struct   slave *curr_active_slave;
 	struct   slave *current_arp_slave;
@@ -255,6 +242,25 @@ extern inline void bond_set_slave_active_flags(struct slave *slave)
 
 struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr);
 int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev);
+int bond_create(char *name, struct bond_params *params, struct bonding **newbond);
+void bond_deinit(struct net_device *bond_dev);
+int bond_create_sysfs(void);
+void bond_destroy_sysfs(void);
+void bond_destroy_sysfs_entry(struct bonding *bond);
+int bond_create_sysfs_entry(struct bonding *bond);
+int bond_create_slave_symlinks(struct net_device *master, struct net_device *slave);
+void bond_destroy_slave_symlinks(struct net_device *master, struct net_device *slave);
+int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev);
+int bond_release(struct net_device *bond_dev, struct net_device *slave_dev);
+int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev);
+void bond_mii_monitor(struct net_device *bond_dev);
+void bond_loadbalance_arp_mon(struct net_device *bond_dev);
+void bond_activebackup_arp_mon(struct net_device *bond_dev);
+void bond_set_mode_ops(struct bonding *bond, int mode);
+int bond_parse_parm(char *mode_arg, struct bond_parm_tbl *tbl);
+const char *bond_mode_name(int mode);
+void bond_select_active_slave(struct bonding *bond);
+void bond_change_active_slave(struct bonding *bond, struct slave *new_active);
 
 #endif /* _LINUX_BONDING_H */
 
diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c
index 53b41d99b00b..2c5b849b7ba4 100644
--- a/drivers/net/chelsio/sge.c
+++ b/drivers/net/chelsio/sge.c
@@ -1332,8 +1332,8 @@ intr_handler_t t1_select_intr_handler(adapter_t *adapter)
  *
  * This runs with softirqs disabled.
  */
-unsigned int t1_sge_tx(struct sk_buff *skb, struct adapter *adapter,
-		       unsigned int qid, struct net_device *dev)
+static int t1_sge_tx(struct sk_buff *skb, struct adapter *adapter,
+		     unsigned int qid, struct net_device *dev)
 {
 	struct sge *sge = adapter->sge;
 	struct cmdQ *q = &sge->cmdQ[qid];
@@ -1352,9 +1352,10 @@ unsigned int t1_sge_tx(struct sk_buff *skb, struct adapter *adapter,
 			set_bit(dev->if_port, &sge->stopped_tx_queues);
 			sge->stats.cmdQ_full[3]++;
 			spin_unlock(&q->lock);
-			CH_ERR("%s: Tx ring full while queue awake!\n",
-			       adapter->name);
-			return 1;
+			if (!netif_queue_stopped(dev))
+				CH_ERR("%s: Tx ring full while queue awake!\n",
+				       adapter->name);
+			return NETDEV_TX_BUSY;
 		}
 		if (unlikely(credits - count < q->stop_thres)) {
 			sge->stats.cmdQ_full[3]++;
@@ -1389,7 +1390,7 @@ unsigned int t1_sge_tx(struct sk_buff *skb, struct adapter *adapter,
 			writel(F_CMDQ0_ENABLE, adapter->regs + A_SG_DOORBELL);
 		}
 	}
-	return 0;
+	return NETDEV_TX_OK;
 }
 
 #define MK_ETH_TYPE_MSS(type, mss) (((mss) & 0x3FFF) | ((type) << 14))
@@ -1449,7 +1450,7 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		if (unlikely(skb->len < ETH_HLEN ||
 			     skb->len > dev->mtu + eth_hdr_len(skb->data))) {
 			dev_kfree_skb_any(skb);
-			return NET_XMIT_SUCCESS;
+			return NETDEV_TX_OK;
 		}
 
 		/*
@@ -1467,7 +1468,7 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev)
 			skb = skb_realloc_headroom(skb, sizeof(*cpl));
 			dev_kfree_skb_any(orig_skb);
 			if (!skb)
-				return -ENOMEM;
+				return NETDEV_TX_OK;
 		}
 
 		if (!(adapter->flags & UDP_CSUM_CAPABLE) &&
@@ -1475,7 +1476,7 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		    skb->nh.iph->protocol == IPPROTO_UDP)
 			if (unlikely(skb_checksum_help(skb, 0))) {
 				dev_kfree_skb_any(skb);
-				return -ENOMEM;
+				return NETDEV_TX_OK;
 			}
 
 		/* Hmmm, assuming to catch the gratious arp... and we'll use
diff --git a/drivers/net/chelsio/sge.h b/drivers/net/chelsio/sge.h
index 434b25586851..6d0d24a6364f 100644
--- a/drivers/net/chelsio/sge.h
+++ b/drivers/net/chelsio/sge.h
@@ -89,8 +89,6 @@ int t1_sge_configure(struct sge *, struct sge_params *);
 int t1_sge_set_coalesce_params(struct sge *, struct sge_params *);
 void t1_sge_destroy(struct sge *);
 intr_handler_t t1_select_intr_handler(adapter_t *adapter);
-unsigned int t1_sge_tx(struct sk_buff *skb, struct adapter *adapter,
-		       unsigned int qid, struct net_device *netdev);
 int t1_start_xmit(struct sk_buff *skb, struct net_device *dev);
 void t1_set_vlan_accel(struct adapter *adapter, int on_off);
 void t1_sge_start(struct sge *);
diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
index 3f653a93e1bc..e02e9ba2e18b 100644
--- a/drivers/net/e1000/e1000.h
+++ b/drivers/net/e1000/e1000.h
@@ -188,11 +188,13 @@ struct e1000_tx_ring {
 	/* array of buffer information structs */
 	struct e1000_buffer *buffer_info;
 
-	struct e1000_buffer previous_buffer_info;
 	spinlock_t tx_lock;
 	uint16_t tdh;
 	uint16_t tdt;
 	uint64_t pkt;
+
+	boolean_t last_tx_tso;
+
 };
 
 struct e1000_rx_ring {
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
index 8eae8ba27e84..c88f1a3c1b1d 100644
--- a/drivers/net/e1000/e1000_ethtool.c
+++ b/drivers/net/e1000/e1000_ethtool.c
@@ -562,10 +562,29 @@ e1000_get_drvinfo(struct net_device *netdev,
                        struct ethtool_drvinfo *drvinfo)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
+	char firmware_version[32];
+	uint16_t eeprom_data;
 
 	strncpy(drvinfo->driver,  e1000_driver_name, 32);
 	strncpy(drvinfo->version, e1000_driver_version, 32);
-	strncpy(drvinfo->fw_version, "N/A", 32);
+	
+	/* EEPROM image version # is reported as firware version # for
+	 * 8257{1|2|3} controllers */
+	e1000_read_eeprom(&adapter->hw, 5, 1, &eeprom_data);
+	switch (adapter->hw.mac_type) {
+	case e1000_82571:
+	case e1000_82572:
+	case e1000_82573:
+		sprintf(firmware_version, "%d.%d-%d", 
+			(eeprom_data & 0xF000) >> 12,
+			(eeprom_data & 0x0FF0) >> 4,
+			eeprom_data & 0x000F);
+		break;
+	default:
+		sprintf(firmware_version, "n/a");
+	}
+
+	strncpy(drvinfo->fw_version, firmware_version, 32);
 	strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
 	drvinfo->n_stats = E1000_STATS_LEN;
 	drvinfo->testinfo_len = E1000_TEST_LEN;
@@ -960,13 +979,21 @@ e1000_free_desc_rings(struct e1000_adapter *adapter)
 		}
 	}
 
-	if(txdr->desc)
+	if(txdr->desc) {
 		pci_free_consistent(pdev, txdr->size, txdr->desc, txdr->dma);
-	if(rxdr->desc)
+		txdr->desc = NULL;
+	}
+	if(rxdr->desc) {
 		pci_free_consistent(pdev, rxdr->size, rxdr->desc, rxdr->dma);
+		rxdr->desc = NULL;
+	}
 
 	kfree(txdr->buffer_info);
+	txdr->buffer_info = NULL;
+
 	kfree(rxdr->buffer_info);
+	rxdr->buffer_info = NULL;
+
 	return;
 }
 
@@ -1301,21 +1328,32 @@ static int
 e1000_setup_loopback_test(struct e1000_adapter *adapter)
 {
 	uint32_t rctl;
+	struct e1000_hw *hw = &adapter->hw;
 
-	if(adapter->hw.media_type == e1000_media_type_fiber ||
-	   adapter->hw.media_type == e1000_media_type_internal_serdes) {
-		if(adapter->hw.mac_type == e1000_82545 ||
-		   adapter->hw.mac_type == e1000_82546 ||
-		   adapter->hw.mac_type == e1000_82545_rev_3 ||
-		   adapter->hw.mac_type == e1000_82546_rev_3)
+	if (hw->media_type == e1000_media_type_fiber ||
+	   hw->media_type == e1000_media_type_internal_serdes) {
+		switch (hw->mac_type) {
+		case e1000_82545:
+		case e1000_82546:
+		case e1000_82545_rev_3:
+		case e1000_82546_rev_3:
 			return e1000_set_phy_loopback(adapter);
-		else {
-			rctl = E1000_READ_REG(&adapter->hw, RCTL);
+			break;
+		case e1000_82571:
+		case e1000_82572:
+#define E1000_SERDES_LB_ON 0x410
+			e1000_set_phy_loopback(adapter);
+			E1000_WRITE_REG(hw, SCTL, E1000_SERDES_LB_ON);
+			msec_delay(10);
+			return 0;
+			break;
+		default:
+			rctl = E1000_READ_REG(hw, RCTL);
 			rctl |= E1000_RCTL_LBM_TCVR;
-			E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+			E1000_WRITE_REG(hw, RCTL, rctl);
 			return 0;
 		}
-	} else if(adapter->hw.media_type == e1000_media_type_copper)
+	} else if (hw->media_type == e1000_media_type_copper)
 		return e1000_set_phy_loopback(adapter);
 
 	return 7;
@@ -1326,25 +1364,36 @@ e1000_loopback_cleanup(struct e1000_adapter *adapter)
 {
 	uint32_t rctl;
 	uint16_t phy_reg;
+	struct e1000_hw *hw = &adapter->hw;
 
 	rctl = E1000_READ_REG(&adapter->hw, RCTL);
 	rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC);
 	E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
 
-	if(adapter->hw.media_type == e1000_media_type_copper ||
-	   ((adapter->hw.media_type == e1000_media_type_fiber ||
-	     adapter->hw.media_type == e1000_media_type_internal_serdes) &&
-	    (adapter->hw.mac_type == e1000_82545 ||
-	     adapter->hw.mac_type == e1000_82546 ||
-	     adapter->hw.mac_type == e1000_82545_rev_3 ||
-	     adapter->hw.mac_type == e1000_82546_rev_3))) {
-		adapter->hw.autoneg = TRUE;
-		e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg);
-		if(phy_reg & MII_CR_LOOPBACK) {
+	switch (hw->mac_type) {
+	case e1000_82571:
+	case e1000_82572:
+		if (hw->media_type == e1000_media_type_fiber ||
+		   hw->media_type == e1000_media_type_internal_serdes){
+#define E1000_SERDES_LB_OFF 0x400
+			E1000_WRITE_REG(hw, SCTL, E1000_SERDES_LB_OFF);
+			msec_delay(10);
+			break;
+		}
+		/* fall thru for Cu adapters */
+	case e1000_82545:
+	case e1000_82546:
+	case e1000_82545_rev_3:
+	case e1000_82546_rev_3:
+	default:
+		hw->autoneg = TRUE;
+		e1000_read_phy_reg(hw, PHY_CTRL, &phy_reg);
+		if (phy_reg & MII_CR_LOOPBACK) {
 			phy_reg &= ~MII_CR_LOOPBACK;
-			e1000_write_phy_reg(&adapter->hw, PHY_CTRL, phy_reg);
-			e1000_phy_reset(&adapter->hw);
+			e1000_write_phy_reg(hw, PHY_CTRL, phy_reg);
+			e1000_phy_reset(hw);
 		}
+		break;
 	}
 }
 
@@ -1440,9 +1489,11 @@ static int
 e1000_loopback_test(struct e1000_adapter *adapter, uint64_t *data)
 {
 	if((*data = e1000_setup_desc_rings(adapter))) goto err_loopback;
-	if((*data = e1000_setup_loopback_test(adapter))) goto err_loopback;
+	if((*data = e1000_setup_loopback_test(adapter)))
+		goto err_loopback_setup;
 	*data = e1000_run_loopback_test(adapter);
 	e1000_loopback_cleanup(adapter);
+err_loopback_setup:
 	e1000_free_desc_rings(adapter);
 err_loopback:
 	return *data;
@@ -1671,6 +1722,14 @@ e1000_phys_id(struct net_device *netdev, uint32_t data)
 		msleep_interruptible(data * 1000);
 		del_timer_sync(&adapter->blink_timer);
 	}
+	else if(adapter->hw.mac_type < e1000_82573) {
+		E1000_WRITE_REG(&adapter->hw, LEDCTL, (E1000_LEDCTL_LED2_BLINK_RATE |
+			E1000_LEDCTL_LED0_BLINK | E1000_LEDCTL_LED2_BLINK |
+			(E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED2_MODE_SHIFT) |
+			(E1000_LEDCTL_MODE_LINK_ACTIVITY << E1000_LEDCTL_LED0_MODE_SHIFT) |
+			(E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED1_MODE_SHIFT)));
+		msleep_interruptible(data * 1000);
+	}
 	else {
 		E1000_WRITE_REG(&adapter->hw, LEDCTL, (E1000_LEDCTL_LED2_BLINK_RATE |
 			E1000_LEDCTL_LED1_BLINK | E1000_LEDCTL_LED2_BLINK | 
diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c
index a267c5235fc0..136fc031e4ad 100644
--- a/drivers/net/e1000/e1000_hw.c
+++ b/drivers/net/e1000/e1000_hw.c
@@ -563,11 +563,13 @@ e1000_reset_hw(struct e1000_hw *hw)
             msec_delay(20);
             break;
         case e1000_82573:
-            udelay(10);
-            ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
-            ctrl_ext |= E1000_CTRL_EXT_EE_RST;
-            E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
-            E1000_WRITE_FLUSH(hw);
+            if (e1000_is_onboard_nvm_eeprom(hw) == FALSE) {
+                udelay(10);
+                ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+                ctrl_ext |= E1000_CTRL_EXT_EE_RST;
+                E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
+                E1000_WRITE_FLUSH(hw);
+            }
             /* fall through */
         case e1000_82571:
         case e1000_82572:
@@ -844,19 +846,27 @@ e1000_setup_link(struct e1000_hw *hw)
      * control setting, then the variable hw->fc will
      * be initialized based on a value in the EEPROM.
      */
-    if(e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data)) {
-        DEBUGOUT("EEPROM Read Error\n");
-        return -E1000_ERR_EEPROM;
-    }
-
-    if(hw->fc == e1000_fc_default) {
-        if((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == 0)
-            hw->fc = e1000_fc_none;
-        else if((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) ==
-                EEPROM_WORD0F_ASM_DIR)
-            hw->fc = e1000_fc_tx_pause;
-        else
+    if (hw->fc == e1000_fc_default) {
+        switch (hw->mac_type) {
+        case e1000_82573:
             hw->fc = e1000_fc_full;
+            break;
+        default:
+            ret_val = e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG,
+                                        1, &eeprom_data);
+            if (ret_val) {
+                DEBUGOUT("EEPROM Read Error\n");
+                return -E1000_ERR_EEPROM;
+            }
+            if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == 0)
+                hw->fc = e1000_fc_none;
+            else if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) ==
+                    EEPROM_WORD0F_ASM_DIR)
+                hw->fc = e1000_fc_tx_pause;
+            else
+                hw->fc = e1000_fc_full;
+            break;
+        }
     }
 
     /* We want to save off the original Flow Control configuration just
@@ -2962,13 +2972,22 @@ e1000_phy_hw_reset(struct e1000_hw *hw)
     if(hw->mac_type > e1000_82543) {
         /* Read the device control register and assert the E1000_CTRL_PHY_RST
          * bit. Then, take it out of reset.
+         * For pre-e1000_82571 hardware, we delay for 10ms between the assert 
+         * and deassert.  For e1000_82571 hardware and later, we instead delay
+         * for 10ms after the deassertion.
          */
         ctrl = E1000_READ_REG(hw, CTRL);
         E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PHY_RST);
         E1000_WRITE_FLUSH(hw);
-        msec_delay(10);
+        
+        if (hw->mac_type < e1000_82571) 
+            msec_delay(10);
+        
         E1000_WRITE_REG(hw, CTRL, ctrl);
         E1000_WRITE_FLUSH(hw);
+        
+        if (hw->mac_type >= e1000_82571)
+            msec_delay(10);
     } else {
         /* Read the Extended Device Control Register, assert the PHY_RESET_DIR
          * bit to put the PHY into reset. Then, take it out of reset.
@@ -5278,11 +5297,15 @@ e1000_get_bus_info(struct e1000_hw *hw)
         hw->bus_speed = e1000_bus_speed_unknown;
         hw->bus_width = e1000_bus_width_unknown;
         break;
-    case e1000_82571:
     case e1000_82572:
     case e1000_82573:
         hw->bus_type = e1000_bus_type_pci_express;
         hw->bus_speed = e1000_bus_speed_2500;
+        hw->bus_width = e1000_bus_width_pciex_1;
+        break;
+    case e1000_82571:
+        hw->bus_type = e1000_bus_type_pci_express;
+        hw->bus_speed = e1000_bus_speed_2500;
         hw->bus_width = e1000_bus_width_pciex_4;
         break;
     default:
@@ -6650,6 +6673,12 @@ e1000_get_auto_rd_done(struct e1000_hw *hw)
         break;
     }
 
+    /* PHY configuration from NVM just starts after EECD_AUTO_RD sets to high.
+     * Need to wait for PHY configuration completion before accessing NVM
+     * and PHY. */
+    if (hw->mac_type == e1000_82573)
+        msec_delay(25);
+
     return E1000_SUCCESS;
 }
 
diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h
index 76ce12809a11..7caa35748cea 100644
--- a/drivers/net/e1000/e1000_hw.h
+++ b/drivers/net/e1000/e1000_hw.h
@@ -123,6 +123,7 @@ typedef enum {
     e1000_bus_width_32,
     e1000_bus_width_64,
     e1000_bus_width_pciex_1,
+    e1000_bus_width_pciex_2,
     e1000_bus_width_pciex_4,
     e1000_bus_width_reserved
 } e1000_bus_width;
@@ -149,6 +150,7 @@ typedef enum {
     e1000_igp_cable_length_90  = 90,
     e1000_igp_cable_length_100 = 100,
     e1000_igp_cable_length_110 = 110,
+    e1000_igp_cable_length_115 = 115,
     e1000_igp_cable_length_120 = 120,
     e1000_igp_cable_length_130 = 130,
     e1000_igp_cable_length_140 = 140,
@@ -1457,6 +1459,7 @@ struct e1000_hw {
 #define E1000_EECD_AUPDEN    0x00100000 /* Enable Autonomous FLASH update */
 #define E1000_EECD_SHADV     0x00200000 /* Shadow RAM Data Valid */
 #define E1000_EECD_SEC1VAL   0x00400000 /* Sector One Valid */
+#define E1000_EECD_SECVAL_SHIFT      22
 #define E1000_STM_OPCODE     0xDB00
 #define E1000_HICR_FW_RESET  0xC0
 
@@ -1951,7 +1954,6 @@ struct e1000_host_command_info {
 
 #define E1000_MDALIGN          4096
 
-#define E1000_GCR_BEM32                 0x00400000
 #define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000
 /* Function Active and Power State to MNG */
 #define E1000_FACTPS_FUNC0_POWER_STATE_MASK         0x00000003
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index e0ae248b4313..438a931fd55d 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -711,6 +711,7 @@ e1000_probe(struct pci_dev *pdev,
 		break;
 	case e1000_82546:
 	case e1000_82546_rev_3:
+	case e1000_82571:
 		if((E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_FUNC_1)
 		   && (adapter->hw.media_type == e1000_media_type_copper)) {
 			e1000_read_eeprom(&adapter->hw,
@@ -1158,7 +1159,6 @@ e1000_setup_tx_resources(struct e1000_adapter *adapter,
 		return -ENOMEM;
 	}
 	memset(txdr->buffer_info, 0, size);
-	memset(&txdr->previous_buffer_info, 0, sizeof(struct e1000_buffer));
 
 	/* round up to nearest 4K */
 
@@ -1813,11 +1813,6 @@ e1000_clean_tx_ring(struct e1000_adapter *adapter,
 
 	/* Free all the Tx ring sk_buffs */
 
-	if (likely(tx_ring->previous_buffer_info.skb != NULL)) {
-		e1000_unmap_and_free_tx_resource(adapter,
-				&tx_ring->previous_buffer_info);
-	}
-
 	for(i = 0; i < tx_ring->count; i++) {
 		buffer_info = &tx_ring->buffer_info[i];
 		e1000_unmap_and_free_tx_resource(adapter, buffer_info);
@@ -1832,6 +1827,7 @@ e1000_clean_tx_ring(struct e1000_adapter *adapter,
 
 	tx_ring->next_to_use = 0;
 	tx_ring->next_to_clean = 0;
+	tx_ring->last_tx_tso = 0;
 
 	writel(0, adapter->hw.hw_addr + tx_ring->tdh);
 	writel(0, adapter->hw.hw_addr + tx_ring->tdt);
@@ -2437,6 +2433,16 @@ e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
 		buffer_info = &tx_ring->buffer_info[i];
 		size = min(len, max_per_txd);
 #ifdef NETIF_F_TSO
+		/* Workaround for Controller erratum --
+		 * descriptor for non-tso packet in a linear SKB that follows a
+		 * tso gets written back prematurely before the data is fully
+		 * DMAd to the controller */
+		if (!skb->data_len && tx_ring->last_tx_tso &&
+				!skb_shinfo(skb)->tso_size) {
+			tx_ring->last_tx_tso = 0;
+			size -= 4;
+		}
+
 		/* Workaround for premature desc write-backs
 		 * in TSO mode.  Append 4-byte sentinel desc */
 		if(unlikely(mss && !nr_frags && size == len && size > 8))
@@ -2693,6 +2699,14 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 	if(skb->ip_summed == CHECKSUM_HW)
 		count++;
 #endif
+
+#ifdef NETIF_F_TSO
+	/* Controller Erratum workaround */
+	if (!skb->data_len && tx_ring->last_tx_tso &&
+		!skb_shinfo(skb)->tso_size)
+		count++;
+#endif
+
 	count += TXD_USE_COUNT(len, max_txd_pwr);
 
 	if(adapter->pcix_82544)
@@ -2774,9 +2788,10 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 		return NETDEV_TX_OK;
 	}
 
-	if (likely(tso))
+	if (likely(tso)) {
+		tx_ring->last_tx_tso = 1;
 		tx_flags |= E1000_TX_FLAGS_TSO;
-	else if (likely(e1000_tx_csum(adapter, tx_ring, skb)))
+	} else if (likely(e1000_tx_csum(adapter, tx_ring, skb)))
 		tx_flags |= E1000_TX_FLAGS_CSUM;
 
 	/* Old method was to assume IPv4 packet by default if TSO was enabled.
@@ -3227,37 +3242,12 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
 	eop_desc = E1000_TX_DESC(*tx_ring, eop);
 
 	while (eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) {
-		/* Premature writeback of Tx descriptors clear (free buffers
-		 * and unmap pci_mapping) previous_buffer_info */
-		if (likely(tx_ring->previous_buffer_info.skb != NULL)) {
-			e1000_unmap_and_free_tx_resource(adapter,
-					&tx_ring->previous_buffer_info);
-		}
-
 		for(cleaned = FALSE; !cleaned; ) {
 			tx_desc = E1000_TX_DESC(*tx_ring, i);
 			buffer_info = &tx_ring->buffer_info[i];
 			cleaned = (i == eop);
 
-#ifdef NETIF_F_TSO
-			if (!(netdev->features & NETIF_F_TSO)) {
-#endif
-				e1000_unmap_and_free_tx_resource(adapter,
-				                                 buffer_info);
-#ifdef NETIF_F_TSO
-			} else {
-				if (cleaned) {
-					memcpy(&tx_ring->previous_buffer_info,
-					       buffer_info,
-					       sizeof(struct e1000_buffer));
-					memset(buffer_info, 0,
-					       sizeof(struct e1000_buffer));
-				} else {
-					e1000_unmap_and_free_tx_resource(
-					    adapter, buffer_info);
-				}
-			}
-#endif
+			e1000_unmap_and_free_tx_resource(adapter, buffer_info);
 
 			tx_desc->buffer_addr = 0;
 			tx_desc->lower.data = 0;
@@ -3318,12 +3308,6 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
 			netif_stop_queue(netdev);
 		}
 	}
-#ifdef NETIF_F_TSO
-	if (unlikely(!(eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) &&
-	    time_after(jiffies, tx_ring->previous_buffer_info.time_stamp + HZ)))
-		e1000_unmap_and_free_tx_resource(
-		    adapter, &tx_ring->previous_buffer_info);
-#endif
 	return cleaned;
 }
 
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 0f030b73cbb3..146f9513aea5 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -2,7 +2,8 @@
  * drivers/net/gianfar.c
  *
  * Gianfar Ethernet Driver
- * Driver for FEC on MPC8540 and TSEC on MPC8540/MPC8560
+ * This driver is designed for the non-CPM ethernet controllers
+ * on the 85xx and 83xx family of integrated processors
  * Based on 8260_io/fcc_enet.c
  *
  * Author: Andy Fleming
@@ -22,8 +23,6 @@
  *  B-V +1.62
  *
  *  Theory of operation
- *  This driver is designed for the non-CPM ethernet controllers
- *  on the 85xx and 83xx family of integrated processors
  *
  *  The driver is initialized through platform_device.  Structures which
  *  define the configuration needed by the board are defined in a
@@ -110,7 +109,7 @@
 #endif
 
 const char gfar_driver_name[] = "Gianfar Ethernet";
-const char gfar_driver_version[] = "1.2";
+const char gfar_driver_version[] = "1.3";
 
 static int gfar_enet_open(struct net_device *dev);
 static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev);
@@ -139,6 +138,10 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, int l
 static void gfar_vlan_rx_register(struct net_device *netdev,
 		                struct vlan_group *grp);
 static void gfar_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid);
+void gfar_halt(struct net_device *dev);
+void gfar_start(struct net_device *dev);
+static void gfar_clear_exact_match(struct net_device *dev);
+static void gfar_set_mac_for_addr(struct net_device *dev, int num, u8 *addr);
 
 extern struct ethtool_ops gfar_ethtool_ops;
 
@@ -146,12 +149,10 @@ MODULE_AUTHOR("Freescale Semiconductor, Inc");
 MODULE_DESCRIPTION("Gianfar Ethernet Driver");
 MODULE_LICENSE("GPL");
 
-int gfar_uses_fcb(struct gfar_private *priv)
+/* Returns 1 if incoming frames use an FCB */
+static inline int gfar_uses_fcb(struct gfar_private *priv)
 {
-	if (priv->vlan_enable || priv->rx_csum_enable)
-		return 1;
-	else
-		return 0;
+	return (priv->vlan_enable || priv->rx_csum_enable);
 }
 
 /* Set up the ethernet device structure, private data,
@@ -320,15 +321,10 @@ static int gfar_probe(struct platform_device *pdev)
 	else
 		priv->padding = 0;
 
-	dev->hard_header_len += priv->padding;
-
 	if (dev->features & NETIF_F_IP_CSUM)
 		dev->hard_header_len += GMAC_FCB_LEN;
 
 	priv->rx_buffer_size = DEFAULT_RX_BUFFER_SIZE;
-#ifdef CONFIG_GFAR_BUFSTASH
-	priv->rx_stash_size = STASH_LENGTH;
-#endif
 	priv->tx_ring_size = DEFAULT_TX_RING_SIZE;
 	priv->rx_ring_size = DEFAULT_RX_RING_SIZE;
 
@@ -350,6 +346,9 @@ static int gfar_probe(struct platform_device *pdev)
 		goto register_fail;
 	}
 
+	/* Create all the sysfs files */
+	gfar_init_sysfs(dev);
+
 	/* Print out the device info */
 	printk(KERN_INFO DEVICE_NAME, dev->name);
 	for (idx = 0; idx < 6; idx++)
@@ -357,8 +356,7 @@ static int gfar_probe(struct platform_device *pdev)
 	printk("\n");
 
 	/* Even more device info helps when determining which kernel */
-	/* provided which set of benchmarks.  Since this is global for all */
-	/* devices, we only print it once */
+	/* provided which set of benchmarks. */
 #ifdef CONFIG_GFAR_NAPI
 	printk(KERN_INFO "%s: Running with NAPI enabled\n", dev->name);
 #else
@@ -463,19 +461,9 @@ static void init_registers(struct net_device *dev)
 	/* Initialize the max receive buffer length */
 	gfar_write(&priv->regs->mrblr, priv->rx_buffer_size);
 
-#ifdef CONFIG_GFAR_BUFSTASH
-	/* If we are stashing buffers, we need to set the
-	 * extraction length to the size of the buffer */
-	gfar_write(&priv->regs->attreli, priv->rx_stash_size << 16);
-#endif
-
 	/* Initialize the Minimum Frame Length Register */
 	gfar_write(&priv->regs->minflr, MINFLR_INIT_SETTINGS);
 
-	/* Setup Attributes so that snooping is on for rx */
-	gfar_write(&priv->regs->attr, ATTR_INIT_SETTINGS);
-	gfar_write(&priv->regs->attreli, ATTRELI_INIT_SETTINGS);
-
 	/* Assign the TBI an address which won't conflict with the PHYs */
 	gfar_write(&priv->regs->tbipa, TBIPA_VALUE);
 }
@@ -577,8 +565,7 @@ static void free_skb_resources(struct gfar_private *priv)
 		for (i = 0; i < priv->rx_ring_size; i++) {
 			if (priv->rx_skbuff[i]) {
 				dma_unmap_single(NULL, rxbdp->bufPtr,
-						priv->rx_buffer_size
-						+ RXBUF_ALIGNMENT,
+						priv->rx_buffer_size,
 						DMA_FROM_DEVICE);
 
 				dev_kfree_skb_any(priv->rx_skbuff[i]);
@@ -636,6 +623,7 @@ int startup_gfar(struct net_device *dev)
 	struct gfar *regs = priv->regs;
 	int err = 0;
 	u32 rctrl = 0;
+	u32 attrs = 0;
 
 	gfar_write(&regs->imask, IMASK_INIT_CLEAR);
 
@@ -795,18 +783,50 @@ int startup_gfar(struct net_device *dev)
 	if (priv->rx_csum_enable)
 		rctrl |= RCTRL_CHECKSUMMING;
 
-	if (priv->extended_hash)
+	if (priv->extended_hash) {
 		rctrl |= RCTRL_EXTHASH;
 
+		gfar_clear_exact_match(dev);
+		rctrl |= RCTRL_EMEN;
+	}
+
 	if (priv->vlan_enable)
 		rctrl |= RCTRL_VLAN;
 
+	if (priv->padding) {
+		rctrl &= ~RCTRL_PAL_MASK;
+		rctrl |= RCTRL_PADDING(priv->padding);
+	}
+
 	/* Init rctrl based on our settings */
 	gfar_write(&priv->regs->rctrl, rctrl);
 
 	if (dev->features & NETIF_F_IP_CSUM)
 		gfar_write(&priv->regs->tctrl, TCTRL_INIT_CSUM);
 
+	/* Set the extraction length and index */
+	attrs = ATTRELI_EL(priv->rx_stash_size) |
+		ATTRELI_EI(priv->rx_stash_index);
+
+	gfar_write(&priv->regs->attreli, attrs);
+
+	/* Start with defaults, and add stashing or locking
+	 * depending on the approprate variables */
+	attrs = ATTR_INIT_SETTINGS;
+
+	if (priv->bd_stash_en)
+		attrs |= ATTR_BDSTASH;
+
+	if (priv->rx_stash_size != 0)
+		attrs |= ATTR_BUFSTASH;
+
+	gfar_write(&priv->regs->attr, attrs);
+
+	gfar_write(&priv->regs->fifo_tx_thr, priv->fifo_threshold);
+	gfar_write(&priv->regs->fifo_tx_starve, priv->fifo_starve);
+	gfar_write(&priv->regs->fifo_tx_starve_shutoff, priv->fifo_starve_off);
+
+	/* Start the controller */
 	gfar_start(dev);
 
 	return 0;
@@ -851,34 +871,32 @@ static int gfar_enet_open(struct net_device *dev)
 	return err;
 }
 
-static struct txfcb *gfar_add_fcb(struct sk_buff *skb, struct txbd8 *bdp)
+static inline struct txfcb *gfar_add_fcb(struct sk_buff *skb, struct txbd8 *bdp)
 {
 	struct txfcb *fcb = (struct txfcb *)skb_push (skb, GMAC_FCB_LEN);
 
 	memset(fcb, 0, GMAC_FCB_LEN);
 
-	/* Flag the bd so the controller looks for the FCB */
-	bdp->status |= TXBD_TOE;
-
 	return fcb;
 }
 
 static inline void gfar_tx_checksum(struct sk_buff *skb, struct txfcb *fcb)
 {
-	int len;
+	u8 flags = 0;
 
 	/* If we're here, it's a IP packet with a TCP or UDP
 	 * payload.  We set it to checksum, using a pseudo-header
 	 * we provide
 	 */
-	fcb->ip = 1;
-	fcb->tup = 1;
-	fcb->ctu = 1;
-	fcb->nph = 1;
+	flags = TXFCB_DEFAULT;
 
-	/* Notify the controller what the protocol is */
-	if (skb->nh.iph->protocol == IPPROTO_UDP)
-		fcb->udp = 1;
+	/* Tell the controller what the protocol is */
+	/* And provide the already calculated phcs */
+	if (skb->nh.iph->protocol == IPPROTO_UDP) {
+		flags |= TXFCB_UDP;
+		fcb->phcs = skb->h.uh->check;
+	} else
+		fcb->phcs = skb->h.th->check;
 
 	/* l3os is the distance between the start of the
 	 * frame (skb->data) and the start of the IP hdr.
@@ -887,17 +905,12 @@ static inline void gfar_tx_checksum(struct sk_buff *skb, struct txfcb *fcb)
 	fcb->l3os = (u16)(skb->nh.raw - skb->data - GMAC_FCB_LEN);
 	fcb->l4os = (u16)(skb->h.raw - skb->nh.raw);
 
-	len = skb->nh.iph->tot_len - fcb->l4os;
-
-	/* Provide the pseudoheader csum */
-	fcb->phcs = ~csum_tcpudp_magic(skb->nh.iph->saddr,
-			skb->nh.iph->daddr, len,
-			skb->nh.iph->protocol, 0);
+	fcb->flags = flags;
 }
 
-void gfar_tx_vlan(struct sk_buff *skb, struct txfcb *fcb)
+void inline gfar_tx_vlan(struct sk_buff *skb, struct txfcb *fcb)
 {
-	fcb->vln = 1;
+	fcb->flags |= TXFCB_VLN;
 	fcb->vlctl = vlan_tx_tag_get(skb);
 }
 
@@ -908,6 +921,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	struct gfar_private *priv = netdev_priv(dev);
 	struct txfcb *fcb = NULL;
 	struct txbd8 *txbdp;
+	u16 status;
 
 	/* Update transmit stats */
 	priv->stats.tx_bytes += skb->len;
@@ -919,19 +933,22 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	txbdp = priv->cur_tx;
 
 	/* Clear all but the WRAP status flags */
-	txbdp->status &= TXBD_WRAP;
+	status = txbdp->status & TXBD_WRAP;
 
 	/* Set up checksumming */
-	if ((dev->features & NETIF_F_IP_CSUM)
-			&& (CHECKSUM_HW == skb->ip_summed)) {
+	if (likely((dev->features & NETIF_F_IP_CSUM)
+			&& (CHECKSUM_HW == skb->ip_summed))) {
 		fcb = gfar_add_fcb(skb, txbdp);
+		status |= TXBD_TOE;
 		gfar_tx_checksum(skb, fcb);
 	}
 
 	if (priv->vlan_enable &&
 			unlikely(priv->vlgrp && vlan_tx_tag_present(skb))) {
-		if (NULL == fcb)
+		if (unlikely(NULL == fcb)) {
 			fcb = gfar_add_fcb(skb, txbdp);
+			status |= TXBD_TOE;
+		}
 
 		gfar_tx_vlan(skb, fcb);
 	}
@@ -949,14 +966,16 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	    (priv->skb_curtx + 1) & TX_RING_MOD_MASK(priv->tx_ring_size);
 
 	/* Flag the BD as interrupt-causing */
-	txbdp->status |= TXBD_INTERRUPT;
+	status |= TXBD_INTERRUPT;
 
 	/* Flag the BD as ready to go, last in frame, and  */
 	/* in need of CRC */
-	txbdp->status |= (TXBD_READY | TXBD_LAST | TXBD_CRC);
+	status |= (TXBD_READY | TXBD_LAST | TXBD_CRC);
 
 	dev->trans_start = jiffies;
 
+	txbdp->status = status;
+
 	/* If this was the last BD in the ring, the next one */
 	/* is at the beginning of the ring */
 	if (txbdp->status & TXBD_WRAP)
@@ -1010,21 +1029,7 @@ static struct net_device_stats * gfar_get_stats(struct net_device *dev)
 /* Changes the mac address if the controller is not running. */
 int gfar_set_mac_address(struct net_device *dev)
 {
-	struct gfar_private *priv = netdev_priv(dev);
-	int i;
-	char tmpbuf[MAC_ADDR_LEN];
-	u32 tempval;
-
-	/* Now copy it into the mac registers backwards, cuz */
-	/* little endian is silly */
-	for (i = 0; i < MAC_ADDR_LEN; i++)
-		tmpbuf[MAC_ADDR_LEN - 1 - i] = dev->dev_addr[i];
-
-	gfar_write(&priv->regs->macstnaddr1, *((u32 *) (tmpbuf)));
-
-	tempval = *((u32 *) (tmpbuf + 4));
-
-	gfar_write(&priv->regs->macstnaddr2, tempval);
+	gfar_set_mac_for_addr(dev, 0, dev->dev_addr);
 
 	return 0;
 }
@@ -1110,7 +1115,7 @@ static int gfar_change_mtu(struct net_device *dev, int new_mtu)
 	    INCREMENTAL_BUFFER_SIZE;
 
 	/* Only stop and start the controller if it isn't already
-	 * stopped */
+	 * stopped, and we changed something */
 	if ((oldsize != tempsize) && (dev->flags & IFF_UP))
 		stop_gfar(dev);
 
@@ -1220,6 +1225,7 @@ static irqreturn_t gfar_transmit(int irq, void *dev_id, struct pt_regs *regs)
 
 struct sk_buff * gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp)
 {
+	unsigned int alignamount;
 	struct gfar_private *priv = netdev_priv(dev);
 	struct sk_buff *skb = NULL;
 	unsigned int timeout = SKB_ALLOC_TIMEOUT;
@@ -1231,18 +1237,18 @@ struct sk_buff * gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp)
 	if (NULL == skb)
 		return NULL;
 
+	alignamount = RXBUF_ALIGNMENT -
+		(((unsigned) skb->data) & (RXBUF_ALIGNMENT - 1));
+
 	/* We need the data buffer to be aligned properly.  We will reserve
 	 * as many bytes as needed to align the data properly
 	 */
-	skb_reserve(skb,
-		    RXBUF_ALIGNMENT -
-		    (((unsigned) skb->data) & (RXBUF_ALIGNMENT - 1)));
+	skb_reserve(skb, alignamount);
 
 	skb->dev = dev;
 
 	bdp->bufPtr = dma_map_single(NULL, skb->data,
-			priv->rx_buffer_size + RXBUF_ALIGNMENT,
-			DMA_FROM_DEVICE);
+			priv->rx_buffer_size, DMA_FROM_DEVICE);
 
 	bdp->length = 0;
 
@@ -1350,7 +1356,7 @@ static inline void gfar_rx_checksum(struct sk_buff *skb, struct rxfcb *fcb)
 	/* If valid headers were found, and valid sums
 	 * were verified, then we tell the kernel that no
 	 * checksumming is necessary.  Otherwise, it is */
-	if (fcb->cip && !fcb->eip && fcb->ctu && !fcb->etu)
+	if ((fcb->flags & RXFCB_CSUM_MASK) == (RXFCB_CIP | RXFCB_CTU))
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
 	else
 		skb->ip_summed = CHECKSUM_NONE;
@@ -1401,7 +1407,7 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
 		skb->protocol = eth_type_trans(skb, dev);
 
 		/* Send the packet up the stack */
-		if (unlikely(priv->vlgrp && fcb->vln))
+		if (unlikely(priv->vlgrp && (fcb->flags & RXFCB_VLN)))
 			ret = gfar_rx_vlan(skb, priv->vlgrp, fcb->vlctl);
 		else
 			ret = RECEIVE(skb);
@@ -1620,6 +1626,7 @@ static void adjust_link(struct net_device *dev)
 	spin_lock_irqsave(&priv->lock, flags);
 	if (phydev->link) {
 		u32 tempval = gfar_read(&regs->maccfg2);
+		u32 ecntrl = gfar_read(&regs->ecntrl);
 
 		/* Now we make sure that we can be in full duplex mode.
 		 * If not, we operate in half-duplex mode. */
@@ -1644,6 +1651,13 @@ static void adjust_link(struct net_device *dev)
 			case 10:
 				tempval =
 				    ((tempval & ~(MACCFG2_IF)) | MACCFG2_MII);
+
+				/* Reduced mode distinguishes
+				 * between 10 and 100 */
+				if (phydev->speed == SPEED_100)
+					ecntrl |= ECNTRL_R100;
+				else
+					ecntrl &= ~(ECNTRL_R100);
 				break;
 			default:
 				if (netif_msg_link(priv))
@@ -1657,6 +1671,7 @@ static void adjust_link(struct net_device *dev)
 		}
 
 		gfar_write(&regs->maccfg2, tempval);
+		gfar_write(&regs->ecntrl, ecntrl);
 
 		if (!priv->oldlink) {
 			new_state = 1;
@@ -1721,6 +1736,9 @@ static void gfar_set_multi(struct net_device *dev)
 		gfar_write(&regs->gaddr6, 0xffffffff);
 		gfar_write(&regs->gaddr7, 0xffffffff);
 	} else {
+		int em_num;
+		int idx;
+
 		/* zero out the hash */
 		gfar_write(&regs->igaddr0, 0x0);
 		gfar_write(&regs->igaddr1, 0x0);
@@ -1739,18 +1757,47 @@ static void gfar_set_multi(struct net_device *dev)
 		gfar_write(&regs->gaddr6, 0x0);
 		gfar_write(&regs->gaddr7, 0x0);
 
+		/* If we have extended hash tables, we need to
+		 * clear the exact match registers to prepare for
+		 * setting them */
+		if (priv->extended_hash) {
+			em_num = GFAR_EM_NUM + 1;
+			gfar_clear_exact_match(dev);
+			idx = 1;
+		} else {
+			idx = 0;
+			em_num = 0;
+		}
+
 		if(dev->mc_count == 0)
 			return;
 
 		/* Parse the list, and set the appropriate bits */
 		for(mc_ptr = dev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) {
-			gfar_set_hash_for_addr(dev, mc_ptr->dmi_addr);
+			if (idx < em_num) {
+				gfar_set_mac_for_addr(dev, idx,
+						mc_ptr->dmi_addr);
+				idx++;
+			} else
+				gfar_set_hash_for_addr(dev, mc_ptr->dmi_addr);
 		}
 	}
 
 	return;
 }
 
+
+/* Clears each of the exact match registers to zero, so they
+ * don't interfere with normal reception */
+static void gfar_clear_exact_match(struct net_device *dev)
+{
+	int idx;
+	u8 zero_arr[MAC_ADDR_LEN] = {0,0,0,0,0,0};
+
+	for(idx = 1;idx < GFAR_EM_NUM + 1;idx++)
+		gfar_set_mac_for_addr(dev, idx, (u8 *)zero_arr);
+}
+
 /* Set the appropriate hash bit for the given addr */
 /* The algorithm works like so:
  * 1) Take the Destination Address (ie the multicast address), and
@@ -1781,6 +1828,32 @@ static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr)
 	return;
 }
 
+
+/* There are multiple MAC Address register pairs on some controllers
+ * This function sets the numth pair to a given address
+ */
+static void gfar_set_mac_for_addr(struct net_device *dev, int num, u8 *addr)
+{
+	struct gfar_private *priv = netdev_priv(dev);
+	int idx;
+	char tmpbuf[MAC_ADDR_LEN];
+	u32 tempval;
+	u32 *macptr = &priv->regs->macstnaddr1;
+
+	macptr += num*2;
+
+	/* Now copy it into the mac registers backwards, cuz */
+	/* little endian is silly */
+	for (idx = 0; idx < MAC_ADDR_LEN; idx++)
+		tmpbuf[MAC_ADDR_LEN - 1 - idx] = addr[idx];
+
+	gfar_write(macptr, *((u32 *) (tmpbuf)));
+
+	tempval = *((u32 *) (tmpbuf + 4));
+
+	gfar_write(macptr+1, tempval);
+}
+
 /* GFAR error interrupt handler */
 static irqreturn_t gfar_error(int irq, void *dev_id, struct pt_regs *regs)
 {
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index 5065ba82cb76..94a91da84fbb 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -90,12 +90,26 @@ extern const char gfar_driver_version[];
 #define GFAR_RX_MAX_RING_SIZE   256
 #define GFAR_TX_MAX_RING_SIZE   256
 
+#define GFAR_MAX_FIFO_THRESHOLD 511
+#define GFAR_MAX_FIFO_STARVE	511
+#define GFAR_MAX_FIFO_STARVE_OFF 511
+
 #define DEFAULT_RX_BUFFER_SIZE  1536
 #define TX_RING_MOD_MASK(size) (size-1)
 #define RX_RING_MOD_MASK(size) (size-1)
 #define JUMBO_BUFFER_SIZE 9728
 #define JUMBO_FRAME_SIZE 9600
 
+#define DEFAULT_FIFO_TX_THR 0x100
+#define DEFAULT_FIFO_TX_STARVE 0x40
+#define DEFAULT_FIFO_TX_STARVE_OFF 0x80
+#define DEFAULT_BD_STASH 1
+#define DEFAULT_STASH_LENGTH	64
+#define DEFAULT_STASH_INDEX	0
+
+/* The number of Exact Match registers */
+#define GFAR_EM_NUM	15
+
 /* Latency of interface clock in nanoseconds */
 /* Interface clock latency , in this case, means the
  * time described by a value of 1 in the interrupt
@@ -112,11 +126,11 @@ extern const char gfar_driver_version[];
 
 #define DEFAULT_TX_COALESCE 1
 #define DEFAULT_TXCOUNT	16
-#define DEFAULT_TXTIME	400
+#define DEFAULT_TXTIME	4
 
 #define DEFAULT_RX_COALESCE 1
 #define DEFAULT_RXCOUNT	16
-#define DEFAULT_RXTIME	400
+#define DEFAULT_RXTIME	4
 
 #define TBIPA_VALUE		0x1f
 #define MIIMCFG_INIT_VALUE	0x00000007
@@ -147,6 +161,7 @@ extern const char gfar_driver_version[];
 
 #define ECNTRL_INIT_SETTINGS	0x00001000
 #define ECNTRL_TBI_MODE         0x00000020
+#define ECNTRL_R100		0x00000008
 
 #define MRBLR_INIT_SETTINGS	DEFAULT_RX_BUFFER_SIZE
 
@@ -181,10 +196,12 @@ extern const char gfar_driver_version[];
 #define RCTRL_PRSDEP_MASK	0x000000c0
 #define RCTRL_PRSDEP_INIT	0x000000c0
 #define RCTRL_PROM		0x00000008
+#define RCTRL_EMEN		0x00000002
 #define RCTRL_CHECKSUMMING	(RCTRL_IPCSEN \
 		| RCTRL_TUCSEN | RCTRL_PRSDEP_INIT)
 #define RCTRL_EXTHASH		(RCTRL_GHTX)
 #define RCTRL_VLAN		(RCTRL_PRSDEP_INIT)
+#define RCTRL_PADDING(x)	((x << 16) & RCTRL_PAL_MASK)
 
 
 #define RSTAT_CLEAR_RHALT       0x00800000
@@ -251,28 +268,26 @@ extern const char gfar_driver_version[];
 		IMASK_XFUN | IMASK_RXC | IMASK_BABT | IMASK_DPE \
 		| IMASK_PERR)
 
+/* Fifo management */
+#define FIFO_TX_THR_MASK	0x01ff
+#define FIFO_TX_STARVE_MASK	0x01ff
+#define FIFO_TX_STARVE_OFF_MASK	0x01ff
 
 /* Attribute fields */
 
 /* This enables rx snooping for buffers and descriptors */
-#ifdef CONFIG_GFAR_BDSTASH
 #define ATTR_BDSTASH		0x00000800
-#else
-#define ATTR_BDSTASH		0x00000000
-#endif
 
-#ifdef CONFIG_GFAR_BUFSTASH
 #define ATTR_BUFSTASH		0x00004000
-#define STASH_LENGTH		64
-#else
-#define ATTR_BUFSTASH		0x00000000
-#endif
 
 #define ATTR_SNOOPING		0x000000c0
-#define ATTR_INIT_SETTINGS      (ATTR_SNOOPING \
-		| ATTR_BDSTASH | ATTR_BUFSTASH)
+#define ATTR_INIT_SETTINGS      ATTR_SNOOPING
 
 #define ATTRELI_INIT_SETTINGS   0x0
+#define ATTRELI_EL_MASK		0x3fff0000
+#define ATTRELI_EL(x) (x << 16)
+#define ATTRELI_EI_MASK		0x00003fff
+#define ATTRELI_EI(x) (x)
 
 
 /* TxBD status field bits */
@@ -328,6 +343,7 @@ extern const char gfar_driver_version[];
 #define RXFCB_CTU		0x0400
 #define RXFCB_EIP		0x0200
 #define RXFCB_ETU		0x0100
+#define RXFCB_CSUM_MASK		0x0f00
 #define RXFCB_PERR_MASK		0x000c
 #define RXFCB_PERR_BADL3	0x0008
 
@@ -339,14 +355,7 @@ struct txbd8
 };
 
 struct txfcb {
-	u8	vln:1,
-		ip:1,
-		ip6:1,
-		tup:1,
-		udp:1,
-		cip:1,
-		ctu:1,
-		nph:1;
+	u8	flags;
 	u8	reserved;
 	u8	l4os;	/* Level 4 Header Offset */
 	u8	l3os; 	/* Level 3 Header Offset */
@@ -362,14 +371,7 @@ struct rxbd8
 };
 
 struct rxfcb {
-	u16	vln:1,
-		ip:1,
-		ip6:1,
-		tup:1,
-		cip:1,
-		ctu:1,
-		eip:1,
-		etu:1;
+	u16	flags;
 	u8	rq;	/* Receive Queue index */
 	u8	pro;	/* Layer 4 Protocol */
 	u16	reserved;
@@ -688,12 +690,17 @@ struct gfar_private {
 	spinlock_t lock;
 	unsigned int rx_buffer_size;
 	unsigned int rx_stash_size;
+	unsigned int rx_stash_index;
 	unsigned int tx_ring_size;
 	unsigned int rx_ring_size;
+	unsigned int fifo_threshold;
+	unsigned int fifo_starve;
+	unsigned int fifo_starve_off;
 
 	unsigned char vlan_enable:1,
 		rx_csum_enable:1,
-		extended_hash:1;
+		extended_hash:1,
+		bd_stash_en:1;
 	unsigned short padding;
 	struct vlan_group *vlgrp;
 	/* Info structure initialized by board setup code */
@@ -731,6 +738,6 @@ extern void stop_gfar(struct net_device *dev);
 extern void gfar_halt(struct net_device *dev);
 extern void gfar_phy_test(struct mii_bus *bus, struct phy_device *phydev,
 		int enable, u32 regnum, u32 read);
-void gfar_setup_stashing(struct net_device *dev);
+void gfar_init_sysfs(struct net_device *dev);
 
 #endif /* __GIANFAR_H */
diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c
index cfa3cd7c91a0..765e810620fe 100644
--- a/drivers/net/gianfar_ethtool.c
+++ b/drivers/net/gianfar_ethtool.c
@@ -125,7 +125,7 @@ static char stat_gstrings[][ETH_GSTRING_LEN] = {
 static void gfar_gstrings(struct net_device *dev, u32 stringset, u8 * buf)
 {
 	struct gfar_private *priv = netdev_priv(dev);
-	
+
 	if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON)
 		memcpy(buf, stat_gstrings, GFAR_STATS_LEN * ETH_GSTRING_LEN);
 	else
diff --git a/drivers/net/gianfar_mii.h b/drivers/net/gianfar_mii.h
index e85eb216fb5b..d527cf2f9c1d 100644
--- a/drivers/net/gianfar_mii.h
+++ b/drivers/net/gianfar_mii.h
@@ -24,6 +24,7 @@
 #define MII_READ_COMMAND       0x00000001
 
 #define GFAR_SUPPORTED (SUPPORTED_10baseT_Half \
+		| SUPPORTED_10baseT_Full \
 		| SUPPORTED_100baseT_Half \
 		| SUPPORTED_100baseT_Full \
 		| SUPPORTED_Autoneg \
diff --git a/drivers/net/gianfar_sysfs.c b/drivers/net/gianfar_sysfs.c
new file mode 100644
index 000000000000..10d34cb19192
--- /dev/null
+++ b/drivers/net/gianfar_sysfs.c
@@ -0,0 +1,311 @@
+/*
+ * drivers/net/gianfar_sysfs.c
+ *
+ * Gianfar Ethernet Driver
+ * This driver is designed for the non-CPM ethernet controllers
+ * on the 85xx and 83xx family of integrated processors
+ * Based on 8260_io/fcc_enet.c
+ *
+ * Author: Andy Fleming
+ * Maintainer: Kumar Gala (kumar.gala@freescale.com)
+ *
+ * Copyright (c) 2002-2005 Freescale Semiconductor, 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.
+ *
+ * Sysfs file creation and management
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/etherdevice.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/device.h>
+
+#include <asm/uaccess.h>
+#include <linux/module.h>
+#include <linux/version.h>
+
+#include "gianfar.h"
+
+#define GFAR_ATTR(_name) \
+static ssize_t gfar_show_##_name(struct class_device *cdev, char *buf); \
+static ssize_t gfar_set_##_name(struct class_device *cdev, \
+		const char *buf, size_t count); \
+static CLASS_DEVICE_ATTR(_name, 0644, gfar_show_##_name, gfar_set_##_name)
+
+#define GFAR_CREATE_FILE(_dev, _name) \
+	class_device_create_file(&_dev->class_dev, &class_device_attr_##_name)
+
+GFAR_ATTR(bd_stash);
+GFAR_ATTR(rx_stash_size);
+GFAR_ATTR(rx_stash_index);
+GFAR_ATTR(fifo_threshold);
+GFAR_ATTR(fifo_starve);
+GFAR_ATTR(fifo_starve_off);
+
+#define to_net_dev(cd) container_of(cd, struct net_device, class_dev)
+
+static ssize_t gfar_show_bd_stash(struct class_device *cdev, char *buf)
+{
+	struct net_device *dev = to_net_dev(cdev);
+	struct gfar_private *priv = netdev_priv(dev);
+
+	return sprintf(buf, "%s\n", priv->bd_stash_en? "on" : "off");
+}
+
+static ssize_t gfar_set_bd_stash(struct class_device *cdev,
+		const char *buf, size_t count)
+{
+	struct net_device *dev = to_net_dev(cdev);
+	struct gfar_private *priv = netdev_priv(dev);
+	int new_setting = 0;
+	u32 temp;
+	unsigned long flags;
+
+	/* Find out the new setting */
+	if (!strncmp("on", buf, count-1) || !strncmp("1", buf, count-1))
+		new_setting = 1;
+	else if (!strncmp("off", buf, count-1) || !strncmp("0", buf, count-1))
+		new_setting = 0;
+	else
+		return count;
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	/* Set the new stashing value */
+	priv->bd_stash_en = new_setting;
+
+	temp = gfar_read(&priv->regs->attr);
+	
+	if (new_setting)
+		temp |= ATTR_BDSTASH;
+	else
+		temp &= ~(ATTR_BDSTASH);
+
+	gfar_write(&priv->regs->attr, temp);
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	return count;
+}
+
+static ssize_t gfar_show_rx_stash_size(struct class_device *cdev, char *buf)
+{
+	struct net_device *dev = to_net_dev(cdev);
+	struct gfar_private *priv = netdev_priv(dev);
+
+	return sprintf(buf, "%d\n", priv->rx_stash_size);
+}
+
+static ssize_t gfar_set_rx_stash_size(struct class_device *cdev,
+		const char *buf, size_t count)
+{
+	struct net_device *dev = to_net_dev(cdev);
+	struct gfar_private *priv = netdev_priv(dev);
+	unsigned int length = simple_strtoul(buf, NULL, 0);
+	u32 temp;
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	if (length > priv->rx_buffer_size)
+		return count;
+
+	if (length == priv->rx_stash_size)
+		return count;
+
+	priv->rx_stash_size = length;
+
+	temp = gfar_read(&priv->regs->attreli);
+	temp &= ~ATTRELI_EL_MASK;
+	temp |= ATTRELI_EL(length);
+	gfar_write(&priv->regs->attreli, temp);
+
+	/* Turn stashing on/off as appropriate */
+	temp = gfar_read(&priv->regs->attr);
+
+	if (length)
+		temp |= ATTR_BUFSTASH;
+	else
+		temp &= ~(ATTR_BUFSTASH);
+
+	gfar_write(&priv->regs->attr, temp);
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	return count;
+}
+
+
+/* Stashing will only be enabled when rx_stash_size != 0 */
+static ssize_t gfar_show_rx_stash_index(struct class_device *cdev, char *buf)
+{
+	struct net_device *dev = to_net_dev(cdev);
+	struct gfar_private *priv = netdev_priv(dev);
+
+	return sprintf(buf, "%d\n", priv->rx_stash_index);
+}
+
+static ssize_t gfar_set_rx_stash_index(struct class_device *cdev,
+		const char *buf, size_t count)
+{
+	struct net_device *dev = to_net_dev(cdev);
+	struct gfar_private *priv = netdev_priv(dev);
+	unsigned short index = simple_strtoul(buf, NULL, 0);
+	u32 temp;
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	if (index > priv->rx_stash_size)
+		return count;
+
+	if (index == priv->rx_stash_index)
+		return count;
+
+	priv->rx_stash_index = index;
+
+	temp = gfar_read(&priv->regs->attreli);
+	temp &= ~ATTRELI_EI_MASK;
+	temp |= ATTRELI_EI(index);
+	gfar_write(&priv->regs->attreli, flags);
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	return count;
+}
+
+static ssize_t gfar_show_fifo_threshold(struct class_device *cdev, char *buf)
+{
+	struct net_device *dev = to_net_dev(cdev);
+	struct gfar_private *priv = netdev_priv(dev);
+
+	return sprintf(buf, "%d\n", priv->fifo_threshold);
+}
+
+static ssize_t gfar_set_fifo_threshold(struct class_device *cdev,
+		const char *buf, size_t count)
+{
+	struct net_device *dev = to_net_dev(cdev);
+	struct gfar_private *priv = netdev_priv(dev);
+	unsigned int length = simple_strtoul(buf, NULL, 0);
+	u32 temp;
+	unsigned long flags;
+
+	if (length > GFAR_MAX_FIFO_THRESHOLD)
+		return count;
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	priv->fifo_threshold = length;
+
+	temp = gfar_read(&priv->regs->fifo_tx_thr);
+	temp &= ~FIFO_TX_THR_MASK;
+	temp |= length;
+	gfar_write(&priv->regs->fifo_tx_thr, temp);
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	return count;
+}
+
+static ssize_t gfar_show_fifo_starve(struct class_device *cdev, char *buf)
+{
+	struct net_device *dev = to_net_dev(cdev);
+	struct gfar_private *priv = netdev_priv(dev);
+
+	return sprintf(buf, "%d\n", priv->fifo_starve);
+}
+
+
+static ssize_t gfar_set_fifo_starve(struct class_device *cdev,
+		const char *buf, size_t count)
+{
+	struct net_device *dev = to_net_dev(cdev);
+	struct gfar_private *priv = netdev_priv(dev);
+	unsigned int num = simple_strtoul(buf, NULL, 0);
+	u32 temp;
+	unsigned long flags;
+
+	if (num > GFAR_MAX_FIFO_STARVE)
+		return count;
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	priv->fifo_starve = num;
+
+	temp = gfar_read(&priv->regs->fifo_tx_starve);
+	temp &= ~FIFO_TX_STARVE_MASK;
+	temp |= num;
+	gfar_write(&priv->regs->fifo_tx_starve, temp);
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	return count;
+}
+
+static ssize_t gfar_show_fifo_starve_off(struct class_device *cdev, char *buf)
+{
+	struct net_device *dev = to_net_dev(cdev);
+	struct gfar_private *priv = netdev_priv(dev);
+
+	return sprintf(buf, "%d\n", priv->fifo_starve_off);
+}
+
+static ssize_t gfar_set_fifo_starve_off(struct class_device *cdev,
+		const char *buf, size_t count)
+{
+	struct net_device *dev = to_net_dev(cdev);
+	struct gfar_private *priv = netdev_priv(dev);
+	unsigned int num = simple_strtoul(buf, NULL, 0);
+	u32 temp;
+	unsigned long flags;
+
+	if (num > GFAR_MAX_FIFO_STARVE_OFF)
+		return count;
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	priv->fifo_starve_off = num;
+
+	temp = gfar_read(&priv->regs->fifo_tx_starve_shutoff);
+	temp &= ~FIFO_TX_STARVE_OFF_MASK;
+	temp |= num;
+	gfar_write(&priv->regs->fifo_tx_starve_shutoff, temp);
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	return count;
+}
+
+void gfar_init_sysfs(struct net_device *dev)
+{
+	struct gfar_private *priv = netdev_priv(dev);
+
+	/* Initialize the default values */
+	priv->rx_stash_size = DEFAULT_STASH_LENGTH;
+	priv->rx_stash_index = DEFAULT_STASH_INDEX;
+	priv->fifo_threshold = DEFAULT_FIFO_TX_THR;
+	priv->fifo_starve = DEFAULT_FIFO_TX_STARVE;
+	priv->fifo_starve_off = DEFAULT_FIFO_TX_STARVE_OFF;
+	priv->bd_stash_en = DEFAULT_BD_STASH;
+
+	/* Create our sysfs files */
+	GFAR_CREATE_FILE(dev, bd_stash);
+	GFAR_CREATE_FILE(dev, rx_stash_size);
+	GFAR_CREATE_FILE(dev, rx_stash_index);
+	GFAR_CREATE_FILE(dev, fifo_threshold);
+	GFAR_CREATE_FILE(dev, fifo_starve);
+	GFAR_CREATE_FILE(dev, fifo_starve_off);
+
+}
diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
index c22c0517883c..fa176ffb4ad5 100644
--- a/drivers/net/irda/irda-usb.c
+++ b/drivers/net/irda/irda-usb.c
@@ -1539,7 +1539,6 @@ static void irda_usb_disconnect(struct usb_interface *intf)
  * USB device callbacks
  */
 static struct usb_driver irda_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "irda-usb",
 	.probe		= irda_usb_probe,
 	.disconnect	= irda_usb_disconnect,
diff --git a/drivers/net/irda/stir4200.c b/drivers/net/irda/stir4200.c
index 3961a754e920..31867e4b891b 100644
--- a/drivers/net/irda/stir4200.c
+++ b/drivers/net/irda/stir4200.c
@@ -1152,7 +1152,6 @@ static int stir_resume(struct usb_interface *intf)
  * USB device callbacks
  */
 static struct usb_driver irda_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "stir4200",
 	.probe		= stir_probe,
 	.disconnect	= stir_disconnect,
diff --git a/drivers/net/ixp2000/Kconfig b/drivers/net/ixp2000/Kconfig
new file mode 100644
index 000000000000..2fec2415651f
--- /dev/null
+++ b/drivers/net/ixp2000/Kconfig
@@ -0,0 +1,6 @@
+config ENP2611_MSF_NET
+	tristate "Radisys ENP2611 MSF network interface support"
+	depends on ARCH_ENP2611
+	help
+	  This is a driver for the MSF network interface unit in
+	  the IXP2400 on the Radisys ENP2611 platform.
diff --git a/drivers/net/ixp2000/Makefile b/drivers/net/ixp2000/Makefile
new file mode 100644
index 000000000000..fd38351ceaa7
--- /dev/null
+++ b/drivers/net/ixp2000/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_ENP2611_MSF_NET) += enp2611_mod.o
+
+enp2611_mod-objs := caleb.o enp2611.o ixp2400-msf.o ixpdev.o pm3386.o
diff --git a/drivers/net/ixp2000/caleb.c b/drivers/net/ixp2000/caleb.c
new file mode 100644
index 000000000000..3595e107df22
--- /dev/null
+++ b/drivers/net/ixp2000/caleb.c
@@ -0,0 +1,137 @@
+/*
+ * Helper functions for the SPI-3 bridge FPGA on the Radisys ENP2611
+ * Copyright (C) 2004, 2005 Lennert Buytenhek <buytenh@wantstofly.org>
+ * Dedicated to Marija Kulikova.
+ *
+ * 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/config.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include "caleb.h"
+
+#define CALEB_IDLO		0x00
+#define CALEB_IDHI		0x01
+#define CALEB_RID		0x02
+#define CALEB_RESET		0x03
+#define CALEB_INTREN0		0x04
+#define CALEB_INTREN1		0x05
+#define CALEB_INTRSTAT0		0x06
+#define CALEB_INTRSTAT1		0x07
+#define CALEB_PORTEN		0x08
+#define CALEB_BURST		0x09
+#define CALEB_PORTPAUS		0x0A
+#define CALEB_PORTPAUSD		0x0B
+#define CALEB_PHY0RX		0x10
+#define CALEB_PHY1RX		0x11
+#define CALEB_PHY0TX		0x12
+#define CALEB_PHY1TX		0x13
+#define CALEB_IXPRX_HI_CNTR	0x15
+#define CALEB_PHY0RX_HI_CNTR	0x16
+#define CALEB_PHY1RX_HI_CNTR	0x17
+#define CALEB_IXPRX_CNTR	0x18
+#define CALEB_PHY0RX_CNTR	0x19
+#define CALEB_PHY1RX_CNTR	0x1A
+#define CALEB_IXPTX_CNTR	0x1B
+#define CALEB_PHY0TX_CNTR	0x1C
+#define CALEB_PHY1TX_CNTR	0x1D
+#define CALEB_DEBUG0		0x1E
+#define CALEB_DEBUG1		0x1F
+
+
+static u8 caleb_reg_read(int reg)
+{
+	u8 value;
+
+	value = *((volatile u8 *)(ENP2611_CALEB_VIRT_BASE + reg));
+
+//	printk(KERN_INFO "caleb_reg_read(%d) = %.2x\n", reg, value);
+
+	return value;
+}
+
+static void caleb_reg_write(int reg, u8 value)
+{
+	u8 dummy;
+
+//	printk(KERN_INFO "caleb_reg_write(%d, %.2x)\n", reg, value);
+
+	*((volatile u8 *)(ENP2611_CALEB_VIRT_BASE + reg)) = value;
+
+	dummy = *((volatile u8 *)ENP2611_CALEB_VIRT_BASE);
+	__asm__ __volatile__("mov %0, %0" : "+r" (dummy));
+}
+
+
+void caleb_reset(void)
+{
+	/*
+	 * Perform a chip reset.
+	 */
+	caleb_reg_write(CALEB_RESET, 0x02);
+	udelay(1);
+
+	/*
+	 * Enable all interrupt sources.  This is needed to get
+	 * meaningful results out of the status bits (register 6
+	 * and 7.)
+	 */
+	caleb_reg_write(CALEB_INTREN0, 0xff);
+	caleb_reg_write(CALEB_INTREN1, 0x07);
+
+	/*
+	 * Set RX and TX FIFO thresholds to 1.5kb.
+	 */
+	caleb_reg_write(CALEB_PHY0RX, 0x11);
+	caleb_reg_write(CALEB_PHY1RX, 0x11);
+	caleb_reg_write(CALEB_PHY0TX, 0x11);
+	caleb_reg_write(CALEB_PHY1TX, 0x11);
+
+	/*
+	 * Program SPI-3 burst size.
+	 */
+	caleb_reg_write(CALEB_BURST, 0);	// 64-byte RBUF mpackets
+//	caleb_reg_write(CALEB_BURST, 1);	// 128-byte RBUF mpackets
+//	caleb_reg_write(CALEB_BURST, 2);	// 256-byte RBUF mpackets
+}
+
+void caleb_enable_rx(int port)
+{
+	u8 temp;
+
+	temp = caleb_reg_read(CALEB_PORTEN);
+	temp |= 1 << port;
+	caleb_reg_write(CALEB_PORTEN, temp);
+}
+
+void caleb_disable_rx(int port)
+{
+	u8 temp;
+
+	temp = caleb_reg_read(CALEB_PORTEN);
+	temp &= ~(1 << port);
+	caleb_reg_write(CALEB_PORTEN, temp);
+}
+
+void caleb_enable_tx(int port)
+{
+	u8 temp;
+
+	temp = caleb_reg_read(CALEB_PORTEN);
+	temp |= 1 << (port + 4);
+	caleb_reg_write(CALEB_PORTEN, temp);
+}
+
+void caleb_disable_tx(int port)
+{
+	u8 temp;
+
+	temp = caleb_reg_read(CALEB_PORTEN);
+	temp &= ~(1 << (port + 4));
+	caleb_reg_write(CALEB_PORTEN, temp);
+}
diff --git a/drivers/net/ixp2000/caleb.h b/drivers/net/ixp2000/caleb.h
new file mode 100644
index 000000000000..e93a1ef5b8a3
--- /dev/null
+++ b/drivers/net/ixp2000/caleb.h
@@ -0,0 +1,22 @@
+/*
+ * Helper functions for the SPI-3 bridge FPGA on the Radisys ENP2611
+ * Copyright (C) 2004, 2005 Lennert Buytenhek <buytenh@wantstofly.org>
+ * Dedicated to Marija Kulikova.
+ *
+ * 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 __CALEB_H
+#define __CALEB_H
+
+void caleb_reset(void);
+void caleb_enable_rx(int port);
+void caleb_disable_rx(int port);
+void caleb_enable_tx(int port);
+void caleb_disable_tx(int port);
+
+
+#endif
diff --git a/drivers/net/ixp2000/enp2611.c b/drivers/net/ixp2000/enp2611.c
new file mode 100644
index 000000000000..d82651a97bae
--- /dev/null
+++ b/drivers/net/ixp2000/enp2611.c
@@ -0,0 +1,245 @@
+/*
+ * IXP2400 MSF network device driver for the Radisys ENP2611
+ * Copyright (C) 2004, 2005 Lennert Buytenhek <buytenh@wantstofly.org>
+ * Dedicated to Marija Kulikova.
+ *
+ * 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/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/init.h>
+#include <linux/moduleparam.h>
+#include <asm/arch/uengine.h>
+#include <asm/mach-types.h>
+#include <asm/io.h>
+#include "ixpdev.h"
+#include "caleb.h"
+#include "ixp2400-msf.h"
+#include "pm3386.h"
+
+/***********************************************************************
+ * The Radisys ENP2611 is a PCI form factor board with three SFP GBIC
+ * slots, connected via two PMC/Sierra 3386s and an SPI-3 bridge FPGA
+ * to the IXP2400.
+ *
+ *                +-------------+
+ * SFP GBIC #0 ---+             |       +---------+
+ *                |  PM3386 #0  +-------+         |
+ * SFP GBIC #1 ---+             |       | "Caleb" |         +---------+
+ *                +-------------+       |         |         |         |
+ *                                      | SPI-3   +---------+ IXP2400 |
+ *                +-------------+       | bridge  |         |         |
+ * SFP GBIC #2 ---+             |       | FPGA    |         +---------+
+ *                |  PM3386 #1  +-------+         |
+ *                |             |       +---------+
+ *                +-------------+
+ *              ^                   ^                  ^
+ *              | 1.25Gbaud         | 104MHz           | 104MHz
+ *              | SERDES ea.        | SPI-3 ea.        | SPI-3
+ *
+ ***********************************************************************/
+static struct ixp2400_msf_parameters enp2611_msf_parameters =
+{
+	.rx_mode =		IXP2400_RX_MODE_UTOPIA_POS |
+				IXP2400_RX_MODE_1x32 |
+				IXP2400_RX_MODE_MPHY |
+				IXP2400_RX_MODE_MPHY_32 |
+				IXP2400_RX_MODE_MPHY_POLLED_STATUS |
+				IXP2400_RX_MODE_MPHY_LEVEL3 |
+				IXP2400_RX_MODE_RBUF_SIZE_64,
+
+	.rxclk01_multiplier =	IXP2400_PLL_MULTIPLIER_16,
+
+	.rx_poll_ports =	3,
+
+	.rx_channel_mode = {
+		IXP2400_PORT_RX_MODE_MASTER |
+		IXP2400_PORT_RX_MODE_POS_PHY |
+		IXP2400_PORT_RX_MODE_POS_PHY_L3 |
+		IXP2400_PORT_RX_MODE_ODD_PARITY |
+		IXP2400_PORT_RX_MODE_2_CYCLE_DECODE,
+
+		IXP2400_PORT_RX_MODE_MASTER |
+		IXP2400_PORT_RX_MODE_POS_PHY |
+		IXP2400_PORT_RX_MODE_POS_PHY_L3 |
+		IXP2400_PORT_RX_MODE_ODD_PARITY |
+		IXP2400_PORT_RX_MODE_2_CYCLE_DECODE,
+
+		IXP2400_PORT_RX_MODE_MASTER |
+		IXP2400_PORT_RX_MODE_POS_PHY |
+		IXP2400_PORT_RX_MODE_POS_PHY_L3 |
+		IXP2400_PORT_RX_MODE_ODD_PARITY |
+		IXP2400_PORT_RX_MODE_2_CYCLE_DECODE,
+
+		IXP2400_PORT_RX_MODE_MASTER |
+		IXP2400_PORT_RX_MODE_POS_PHY |
+		IXP2400_PORT_RX_MODE_POS_PHY_L3 |
+		IXP2400_PORT_RX_MODE_ODD_PARITY |
+		IXP2400_PORT_RX_MODE_2_CYCLE_DECODE
+	},
+
+	.tx_mode =		IXP2400_TX_MODE_UTOPIA_POS |
+				IXP2400_TX_MODE_1x32 |
+				IXP2400_TX_MODE_MPHY |
+				IXP2400_TX_MODE_MPHY_32 |
+				IXP2400_TX_MODE_MPHY_POLLED_STATUS |
+				IXP2400_TX_MODE_MPHY_LEVEL3 |
+				IXP2400_TX_MODE_TBUF_SIZE_64,
+
+	.txclk01_multiplier =	IXP2400_PLL_MULTIPLIER_16,
+
+	.tx_poll_ports =	3,
+
+	.tx_channel_mode = {
+		IXP2400_PORT_TX_MODE_MASTER |
+		IXP2400_PORT_TX_MODE_POS_PHY |
+		IXP2400_PORT_TX_MODE_ODD_PARITY |
+		IXP2400_PORT_TX_MODE_2_CYCLE_DECODE,
+
+		IXP2400_PORT_TX_MODE_MASTER |
+		IXP2400_PORT_TX_MODE_POS_PHY |
+		IXP2400_PORT_TX_MODE_ODD_PARITY |
+		IXP2400_PORT_TX_MODE_2_CYCLE_DECODE,
+
+		IXP2400_PORT_TX_MODE_MASTER |
+		IXP2400_PORT_TX_MODE_POS_PHY |
+		IXP2400_PORT_TX_MODE_ODD_PARITY |
+		IXP2400_PORT_TX_MODE_2_CYCLE_DECODE,
+
+		IXP2400_PORT_TX_MODE_MASTER |
+		IXP2400_PORT_TX_MODE_POS_PHY |
+		IXP2400_PORT_TX_MODE_ODD_PARITY |
+		IXP2400_PORT_TX_MODE_2_CYCLE_DECODE
+	}
+};
+
+struct enp2611_ixpdev_priv
+{
+	struct ixpdev_priv		ixpdev_priv;
+	struct net_device_stats		stats;
+};
+
+static struct net_device *nds[3];
+static struct timer_list link_check_timer;
+
+static struct net_device_stats *enp2611_get_stats(struct net_device *dev)
+{
+	struct enp2611_ixpdev_priv *ip = netdev_priv(dev);
+
+	pm3386_get_stats(ip->ixpdev_priv.channel, &(ip->stats));
+
+	return &(ip->stats);
+}
+
+/* @@@ Poll the SFP moddef0 line too.  */
+/* @@@ Try to use the pm3386 DOOL interrupt as well.  */
+static void enp2611_check_link_status(unsigned long __dummy)
+{
+	int i;
+
+	for (i = 0; i < 3; i++) {
+		struct net_device *dev;
+		int status;
+
+		dev = nds[i];
+
+		status = pm3386_is_link_up(i);
+		if (status && !netif_carrier_ok(dev)) {
+			/* @@@ Should report autonegotiation status.  */
+			printk(KERN_INFO "%s: NIC Link is Up\n", dev->name);
+
+			pm3386_enable_tx(i);
+			caleb_enable_tx(i);
+			netif_carrier_on(dev);
+		} else if (!status && netif_carrier_ok(dev)) {
+			printk(KERN_INFO "%s: NIC Link is Down\n", dev->name);
+
+			netif_carrier_off(dev);
+			caleb_disable_tx(i);
+			pm3386_disable_tx(i);
+		}
+	}
+
+	link_check_timer.expires = jiffies + HZ / 10;
+	add_timer(&link_check_timer);
+}
+
+static void enp2611_set_port_admin_status(int port, int up)
+{
+	if (up) {
+		caleb_enable_rx(port);
+
+		pm3386_set_carrier(port, 1);
+		pm3386_enable_rx(port);
+	} else {
+		caleb_disable_tx(port);
+		pm3386_disable_tx(port);
+		/* @@@ Flush out pending packets.  */
+		pm3386_set_carrier(port, 0);
+
+		pm3386_disable_rx(port);
+		caleb_disable_rx(port);
+	}
+}
+
+static int __init enp2611_init_module(void)
+{ 
+	int i;
+
+	if (!machine_is_enp2611())
+		return -ENODEV;
+
+	caleb_reset();
+	pm3386_reset();
+
+	for (i = 0; i < 3; i++) {
+		nds[i] = ixpdev_alloc(i, sizeof(struct enp2611_ixpdev_priv));
+		if (nds[i] == NULL) {
+			while (--i >= 0)
+				free_netdev(nds[i]);
+			return -ENOMEM;
+		}
+
+		SET_MODULE_OWNER(nds[i]);
+		nds[i]->get_stats = enp2611_get_stats;
+		pm3386_init_port(i);
+		pm3386_get_mac(i, nds[i]->dev_addr);
+	}
+
+	ixp2400_msf_init(&enp2611_msf_parameters);
+
+	if (ixpdev_init(3, nds, enp2611_set_port_admin_status)) {
+		for (i = 0; i < 3; i++)
+			free_netdev(nds[i]);
+		return -EINVAL;
+	}
+
+	init_timer(&link_check_timer);
+	link_check_timer.function = enp2611_check_link_status;
+	link_check_timer.expires = jiffies;
+	add_timer(&link_check_timer);
+
+	return 0;
+}
+
+static void __exit enp2611_cleanup_module(void)
+{
+	int i;
+
+	del_timer_sync(&link_check_timer);
+
+	ixpdev_deinit();
+	for (i = 0; i < 3; i++)
+		free_netdev(nds[i]);
+}
+
+module_init(enp2611_init_module);
+module_exit(enp2611_cleanup_module);
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/ixp2000/ixp2400-msf.c b/drivers/net/ixp2000/ixp2400-msf.c
new file mode 100644
index 000000000000..48a3a891d3a4
--- /dev/null
+++ b/drivers/net/ixp2000/ixp2400-msf.c
@@ -0,0 +1,213 @@
+/*
+ * Generic library functions for the MSF (Media and Switch Fabric) unit
+ * found on the Intel IXP2400 network processor.
+ *
+ * Copyright (C) 2004, 2005 Lennert Buytenhek <buytenh@wantstofly.org>
+ * Dedicated to Marija Kulikova.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of the
+ * License, or (at your option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <asm/hardware.h>
+#include <asm/arch/ixp2000-regs.h>
+#include <asm/delay.h>
+#include <asm/io.h>
+#include "ixp2400-msf.h"
+
+/*
+ * This is the Intel recommended PLL init procedure as described on
+ * page 340 of the IXP2400/IXP2800 Programmer's Reference Manual.
+ */
+static void ixp2400_pll_init(struct ixp2400_msf_parameters *mp)
+{
+	int rx_dual_clock;
+	int tx_dual_clock;
+	u32 value;
+
+	/*
+	 * If the RX mode is not 1x32, we have to enable both RX PLLs
+	 * (#0 and #1.)  The same thing for the TX direction.
+	 */
+	rx_dual_clock = !!(mp->rx_mode & IXP2400_RX_MODE_WIDTH_MASK);
+	tx_dual_clock = !!(mp->tx_mode & IXP2400_TX_MODE_WIDTH_MASK);
+
+	/*
+	 * Read initial value.
+	 */
+	value = ixp2000_reg_read(IXP2000_MSF_CLK_CNTRL);
+
+	/*
+	 * Put PLLs in powerdown and bypass mode.
+	 */
+	value |= 0x0000f0f0;
+	ixp2000_reg_write(IXP2000_MSF_CLK_CNTRL, value);
+
+	/*
+	 * Set single or dual clock mode bits.
+	 */
+	value &= ~0x03000000;
+	value |= (rx_dual_clock << 24) | (tx_dual_clock << 25);
+
+	/*
+	 * Set multipliers.
+	 */
+	value &= ~0x00ff0000;
+	value |= mp->rxclk01_multiplier << 16;
+	value |= mp->rxclk23_multiplier << 18;
+	value |= mp->txclk01_multiplier << 20;
+	value |= mp->txclk23_multiplier << 22;
+
+	/*
+	 * And write value.
+	 */
+	ixp2000_reg_write(IXP2000_MSF_CLK_CNTRL, value);
+
+	/*
+	 * Disable PLL bypass mode.
+	 */
+	value &= ~(0x00005000 | rx_dual_clock << 13 | tx_dual_clock << 15);
+	ixp2000_reg_write(IXP2000_MSF_CLK_CNTRL, value);
+
+	/*
+	 * Turn on PLLs.
+	 */
+	value &= ~(0x00000050 | rx_dual_clock << 5 | tx_dual_clock << 7);
+	ixp2000_reg_write(IXP2000_MSF_CLK_CNTRL, value);
+
+	/*
+	 * Wait for PLLs to lock.  There are lock status bits, but IXP2400
+	 * erratum #65 says that these lock bits should not be relied upon
+	 * as they might not accurately reflect the true state of the PLLs.
+	 */
+	udelay(100);
+}
+
+/*
+ * Needed according to p480 of Programmer's Reference Manual.
+ */
+static void ixp2400_msf_free_rbuf_entries(struct ixp2400_msf_parameters *mp)
+{
+	int size_bits;
+	int i;
+
+	/*
+	 * Work around IXP2400 erratum #69 (silent RBUF-to-DRAM transfer
+	 * corruption) in the Intel-recommended way: do not add the RBUF
+	 * elements susceptible to corruption to the freelist.
+	 */
+	size_bits = mp->rx_mode & IXP2400_RX_MODE_RBUF_SIZE_MASK;
+	if (size_bits == IXP2400_RX_MODE_RBUF_SIZE_64) {
+		for (i = 1; i < 128; i++) {
+			if (i == 9 || i == 18 || i == 27)
+				continue;
+			ixp2000_reg_write(IXP2000_MSF_RBUF_ELEMENT_DONE, i);
+		}
+	} else if (size_bits == IXP2400_RX_MODE_RBUF_SIZE_128) {
+		for (i = 1; i < 64; i++) {
+			if (i == 4 || i == 9 || i == 13)
+				continue;
+			ixp2000_reg_write(IXP2000_MSF_RBUF_ELEMENT_DONE, i);
+		}
+	} else if (size_bits == IXP2400_RX_MODE_RBUF_SIZE_256) {
+		for (i = 1; i < 32; i++) {
+			if (i == 2 || i == 4 || i == 6)
+				continue;
+			ixp2000_reg_write(IXP2000_MSF_RBUF_ELEMENT_DONE, i);
+		}
+	}
+}
+
+static u32 ixp2400_msf_valid_channels(u32 reg)
+{
+	u32 channels;
+
+	channels = 0;
+	switch (reg & IXP2400_RX_MODE_WIDTH_MASK) {
+	case IXP2400_RX_MODE_1x32:
+		channels = 0x1;
+		if (reg & IXP2400_RX_MODE_MPHY &&
+		    !(reg & IXP2400_RX_MODE_MPHY_32))
+			channels = 0xf;
+		break;
+
+	case IXP2400_RX_MODE_2x16:
+		channels = 0x5;
+		break;
+
+	case IXP2400_RX_MODE_4x8:
+		channels = 0xf;
+		break;
+
+	case IXP2400_RX_MODE_1x16_2x8:
+		channels = 0xd;
+		break;
+	}
+
+	return channels;
+}
+
+static void ixp2400_msf_enable_rx(struct ixp2400_msf_parameters *mp)
+{
+	u32 value;
+
+	value = ixp2000_reg_read(IXP2000_MSF_RX_CONTROL) & 0x0fffffff;
+	value |= ixp2400_msf_valid_channels(mp->rx_mode) << 28;
+	ixp2000_reg_write(IXP2000_MSF_RX_CONTROL, value);
+}
+
+static void ixp2400_msf_enable_tx(struct ixp2400_msf_parameters *mp)
+{
+	u32 value;
+
+	value = ixp2000_reg_read(IXP2000_MSF_TX_CONTROL) & 0x0fffffff;
+	value |= ixp2400_msf_valid_channels(mp->tx_mode) << 28;
+	ixp2000_reg_write(IXP2000_MSF_TX_CONTROL, value);
+}
+
+
+void ixp2400_msf_init(struct ixp2400_msf_parameters *mp)
+{
+	u32 value;
+	int i;
+
+	/*
+	 * Init the RX/TX PLLs based on the passed parameter block.
+	 */
+	ixp2400_pll_init(mp);
+
+	/*
+	 * Reset MSF.  Bit 7 in IXP_RESET_0 resets the MSF.
+	 */
+	value = ixp2000_reg_read(IXP2000_RESET0);
+	ixp2000_reg_write(IXP2000_RESET0, value | 0x80);
+	ixp2000_reg_write(IXP2000_RESET0, value & ~0x80);
+
+	/*
+	 * Initialise the RX section.
+	 */
+	ixp2000_reg_write(IXP2000_MSF_RX_MPHY_POLL_LIMIT, mp->rx_poll_ports - 1);
+	ixp2000_reg_write(IXP2000_MSF_RX_CONTROL, mp->rx_mode);
+	for (i = 0; i < 4; i++) {
+		ixp2000_reg_write(IXP2000_MSF_RX_UP_CONTROL_0 + i,
+						mp->rx_channel_mode[i]);
+	}
+	ixp2400_msf_free_rbuf_entries(mp);
+	ixp2400_msf_enable_rx(mp);
+
+	/*
+	 * Initialise the TX section.
+	 */
+	ixp2000_reg_write(IXP2000_MSF_TX_MPHY_POLL_LIMIT, mp->tx_poll_ports - 1);
+	ixp2000_reg_write(IXP2000_MSF_TX_CONTROL, mp->tx_mode);
+	for (i = 0; i < 4; i++) {
+		ixp2000_reg_write(IXP2000_MSF_TX_UP_CONTROL_0 + i,
+						mp->tx_channel_mode[i]);
+	}
+	ixp2400_msf_enable_tx(mp);
+}
diff --git a/drivers/net/ixp2000/ixp2400-msf.h b/drivers/net/ixp2000/ixp2400-msf.h
new file mode 100644
index 000000000000..3ac1af2771da
--- /dev/null
+++ b/drivers/net/ixp2000/ixp2400-msf.h
@@ -0,0 +1,115 @@
+/*
+ * Generic library functions for the MSF (Media and Switch Fabric) unit
+ * found on the Intel IXP2400 network processor.
+ *
+ * Copyright (C) 2004, 2005 Lennert Buytenhek <buytenh@wantstofly.org>
+ * Dedicated to Marija Kulikova.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of the
+ * License, or (at your option) any later version.
+ */
+
+#ifndef __IXP2400_MSF_H
+#define __IXP2400_MSF_H
+
+struct ixp2400_msf_parameters
+{
+	u32				rx_mode;
+	unsigned			rxclk01_multiplier:2;
+	unsigned			rxclk23_multiplier:2;
+	unsigned			rx_poll_ports:6;
+	u32				rx_channel_mode[4];
+
+	u32				tx_mode;
+	unsigned			txclk01_multiplier:2;
+	unsigned			txclk23_multiplier:2;
+	unsigned			tx_poll_ports:6;
+	u32				tx_channel_mode[4];
+};
+
+void ixp2400_msf_init(struct ixp2400_msf_parameters *mp);
+
+#define IXP2400_PLL_MULTIPLIER_48		0x00
+#define IXP2400_PLL_MULTIPLIER_24		0x01
+#define IXP2400_PLL_MULTIPLIER_16		0x02
+#define IXP2400_PLL_MULTIPLIER_12		0x03
+
+#define IXP2400_RX_MODE_CSIX			0x00400000
+#define IXP2400_RX_MODE_UTOPIA_POS		0x00000000
+#define IXP2400_RX_MODE_WIDTH_MASK		0x00300000
+#define IXP2400_RX_MODE_1x16_2x8		0x00300000
+#define IXP2400_RX_MODE_4x8			0x00200000
+#define IXP2400_RX_MODE_2x16			0x00100000
+#define IXP2400_RX_MODE_1x32			0x00000000
+#define IXP2400_RX_MODE_MPHY			0x00080000
+#define IXP2400_RX_MODE_SPHY			0x00000000
+#define IXP2400_RX_MODE_MPHY_32			0x00040000
+#define IXP2400_RX_MODE_MPHY_4			0x00000000
+#define IXP2400_RX_MODE_MPHY_POLLED_STATUS	0x00020000
+#define IXP2400_RX_MODE_MPHY_DIRECT_STATUS	0x00000000
+#define IXP2400_RX_MODE_CBUS_FULL_DUPLEX	0x00010000
+#define IXP2400_RX_MODE_CBUS_SIMPLEX		0x00000000
+#define IXP2400_RX_MODE_MPHY_LEVEL2		0x00004000
+#define IXP2400_RX_MODE_MPHY_LEVEL3		0x00000000
+#define IXP2400_RX_MODE_CBUS_8BIT		0x00002000
+#define IXP2400_RX_MODE_CBUS_4BIT		0x00000000
+#define IXP2400_RX_MODE_CSIX_SINGLE_FREELIST	0x00000200
+#define IXP2400_RX_MODE_CSIX_SPLIT_FREELISTS	0x00000000
+#define IXP2400_RX_MODE_RBUF_SIZE_MASK		0x0000000c
+#define IXP2400_RX_MODE_RBUF_SIZE_256		0x00000008
+#define IXP2400_RX_MODE_RBUF_SIZE_128		0x00000004
+#define IXP2400_RX_MODE_RBUF_SIZE_64		0x00000000
+
+#define IXP2400_PORT_RX_MODE_SLAVE		0x00000040
+#define IXP2400_PORT_RX_MODE_MASTER		0x00000000
+#define IXP2400_PORT_RX_MODE_POS_PHY_L3		0x00000020
+#define IXP2400_PORT_RX_MODE_POS_PHY_L2		0x00000000
+#define IXP2400_PORT_RX_MODE_POS_PHY		0x00000010
+#define IXP2400_PORT_RX_MODE_UTOPIA		0x00000000
+#define IXP2400_PORT_RX_MODE_EVEN_PARITY	0x0000000c
+#define IXP2400_PORT_RX_MODE_ODD_PARITY		0x00000008
+#define IXP2400_PORT_RX_MODE_NO_PARITY		0x00000000
+#define IXP2400_PORT_RX_MODE_UTOPIA_BIG_CELLS	0x00000002
+#define IXP2400_PORT_RX_MODE_UTOPIA_NORMAL_CELLS	0x00000000
+#define IXP2400_PORT_RX_MODE_2_CYCLE_DECODE	0x00000001
+#define IXP2400_PORT_RX_MODE_1_CYCLE_DECODE	0x00000000
+
+#define IXP2400_TX_MODE_CSIX			0x00400000
+#define IXP2400_TX_MODE_UTOPIA_POS		0x00000000
+#define IXP2400_TX_MODE_WIDTH_MASK		0x00300000
+#define IXP2400_TX_MODE_1x16_2x8		0x00300000
+#define IXP2400_TX_MODE_4x8			0x00200000
+#define IXP2400_TX_MODE_2x16			0x00100000
+#define IXP2400_TX_MODE_1x32			0x00000000
+#define IXP2400_TX_MODE_MPHY			0x00080000
+#define IXP2400_TX_MODE_SPHY			0x00000000
+#define IXP2400_TX_MODE_MPHY_32			0x00040000
+#define IXP2400_TX_MODE_MPHY_4			0x00000000
+#define IXP2400_TX_MODE_MPHY_POLLED_STATUS	0x00020000
+#define IXP2400_TX_MODE_MPHY_DIRECT_STATUS	0x00000000
+#define IXP2400_TX_MODE_CBUS_FULL_DUPLEX	0x00010000
+#define IXP2400_TX_MODE_CBUS_SIMPLEX		0x00000000
+#define IXP2400_TX_MODE_MPHY_LEVEL2		0x00004000
+#define IXP2400_TX_MODE_MPHY_LEVEL3		0x00000000
+#define IXP2400_TX_MODE_CBUS_8BIT		0x00002000
+#define IXP2400_TX_MODE_CBUS_4BIT		0x00000000
+#define IXP2400_TX_MODE_TBUF_SIZE_MASK		0x0000000c
+#define IXP2400_TX_MODE_TBUF_SIZE_256		0x00000008
+#define IXP2400_TX_MODE_TBUF_SIZE_128		0x00000004
+#define IXP2400_TX_MODE_TBUF_SIZE_64		0x00000000
+
+#define IXP2400_PORT_TX_MODE_SLAVE		0x00000040
+#define IXP2400_PORT_TX_MODE_MASTER		0x00000000
+#define IXP2400_PORT_TX_MODE_POS_PHY		0x00000010
+#define IXP2400_PORT_TX_MODE_UTOPIA		0x00000000
+#define IXP2400_PORT_TX_MODE_EVEN_PARITY	0x0000000c
+#define IXP2400_PORT_TX_MODE_ODD_PARITY		0x00000008
+#define IXP2400_PORT_TX_MODE_NO_PARITY		0x00000000
+#define IXP2400_PORT_TX_MODE_UTOPIA_BIG_CELLS	0x00000002
+#define IXP2400_PORT_TX_MODE_2_CYCLE_DECODE	0x00000001
+#define IXP2400_PORT_TX_MODE_1_CYCLE_DECODE	0x00000000
+
+
+#endif
diff --git a/drivers/net/ixp2000/ixp2400_rx.uc b/drivers/net/ixp2000/ixp2400_rx.uc
new file mode 100644
index 000000000000..42a73e357afa
--- /dev/null
+++ b/drivers/net/ixp2000/ixp2400_rx.uc
@@ -0,0 +1,408 @@
+/*
+ * RX ucode for the Intel IXP2400 in POS-PHY mode.
+ * Copyright (C) 2004, 2005 Lennert Buytenhek
+ * Dedicated to Marija Kulikova.
+ *
+ * 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.
+ *
+ * Assumptions made in this code:
+ * - The IXP2400 MSF is configured for POS-PHY mode, in a mode where
+ *   only one full element list is used.  This includes, for example,
+ *   1x32 SPHY and 1x32 MPHY32, but not 4x8 SPHY or 1x32 MPHY4.  (This
+ *   is not an exhaustive list.)
+ * - The RBUF uses 64-byte mpackets.
+ * - RX descriptors reside in SRAM, and have the following format:
+ *	struct rx_desc
+ *	{
+ *	// to uengine
+ *		u32	buf_phys_addr;
+ *		u32	buf_length;
+ *
+ *	// from uengine
+ *		u32	channel;
+ *		u32	pkt_length;
+ *	};
+ * - Packet data resides in DRAM.
+ * - Packet buffer addresses are 8-byte aligned.
+ * - Scratch ring 0 is rx_pending.
+ * - Scratch ring 1 is rx_done, and has status condition 'full'.
+ * - The host triggers rx_done flush and rx_pending refill on seeing INTA.
+ * - This code is run on all eight threads of the microengine it runs on.
+ *
+ * Local memory is used for per-channel RX state.
+ */
+
+#define RX_THREAD_FREELIST_0		0x0030
+#define RBUF_ELEMENT_DONE		0x0044
+
+#define CHANNEL_FLAGS			*l$index0[0]
+#define CHANNEL_FLAG_RECEIVING		1
+#define PACKET_LENGTH			*l$index0[1]
+#define PACKET_CHECKSUM			*l$index0[2]
+#define BUFFER_HANDLE			*l$index0[3]
+#define BUFFER_START			*l$index0[4]
+#define BUFFER_LENGTH			*l$index0[5]
+
+#define CHANNEL_STATE_SIZE		24	// in bytes
+#define CHANNEL_STATE_SHIFT		5	// ceil(log2(state size))
+
+
+	.sig volatile sig1
+	.sig volatile sig2
+	.sig volatile sig3
+
+	.sig mpacket_arrived
+	.reg add_to_rx_freelist
+	.reg read $rsw0, $rsw1
+	.xfer_order $rsw0 $rsw1
+
+	.reg zero
+
+	/*
+	 * Initialise add_to_rx_freelist.
+	 */
+	.begin
+		.reg temp
+		.reg temp2
+
+		immed[add_to_rx_freelist, RX_THREAD_FREELIST_0]
+		immed_w1[add_to_rx_freelist, (&$rsw0 | (&mpacket_arrived << 12))]
+
+		local_csr_rd[ACTIVE_CTX_STS]
+		immed[temp, 0]
+		alu[temp2, temp, and, 0x1f]
+		alu_shf[add_to_rx_freelist, add_to_rx_freelist, or, temp2, <<20]
+		alu[temp2, temp, and, 0x80]
+		alu_shf[add_to_rx_freelist, add_to_rx_freelist, or, temp2, <<18]
+	.end
+
+	immed[zero, 0]
+
+	/*
+	 * Skip context 0 initialisation?
+	 */
+	.begin
+		br!=ctx[0, mpacket_receive_loop#]
+	.end
+
+	/*
+	 * Initialise local memory.
+	 */
+	.begin
+		.reg addr
+		.reg temp
+
+		immed[temp, 0]
+	init_local_mem_loop#:
+		alu_shf[addr, --, b, temp, <<CHANNEL_STATE_SHIFT]
+		local_csr_wr[ACTIVE_LM_ADDR_0, addr]
+		nop
+		nop
+		nop
+
+		immed[CHANNEL_FLAGS, 0]
+
+		alu[temp, temp, +, 1]
+		alu[--, temp, and, 0x20]
+		beq[init_local_mem_loop#]
+	.end
+
+	/*
+	 * Initialise signal pipeline.
+	 */
+	.begin
+		local_csr_wr[SAME_ME_SIGNAL, (&sig1 << 3)]
+		.set_sig sig1
+
+		local_csr_wr[SAME_ME_SIGNAL, (&sig2 << 3)]
+		.set_sig sig2
+
+		local_csr_wr[SAME_ME_SIGNAL, (&sig3 << 3)]
+		.set_sig sig3
+	.end
+
+mpacket_receive_loop#:
+	/*
+	 * Synchronise and wait for mpacket.
+	 */
+	.begin
+		ctx_arb[sig1]
+		local_csr_wr[SAME_ME_SIGNAL, (0x80 | (&sig1 << 3))]
+
+		msf[fast_wr, --, add_to_rx_freelist, 0]
+		.set_sig mpacket_arrived
+		ctx_arb[mpacket_arrived]
+		.set $rsw0 $rsw1
+	.end
+
+	/*
+	 * We halt if we see {inbparerr,parerr,null,soperror}.
+	 */
+	.begin
+		alu_shf[--, 0x1b, and, $rsw0, >>8]
+		bne[abort_rswerr#]
+	.end
+
+	/*
+	 * Point local memory pointer to this channel's state area.
+	 */
+	.begin
+		.reg chanaddr
+
+		alu[chanaddr, $rsw0, and, 0x1f]
+		alu_shf[chanaddr, --, b, chanaddr, <<CHANNEL_STATE_SHIFT]
+		local_csr_wr[ACTIVE_LM_ADDR_0, chanaddr]
+		nop
+		nop
+		nop
+	.end
+
+	/*
+	 * Check whether we received a SOP mpacket while we were already
+	 * working on a packet, or a non-SOP mpacket while there was no
+	 * packet pending.  (SOP == RECEIVING -> abort)  If everything's
+	 * okay, update the RECEIVING flag to reflect our new state.
+	 */
+	.begin
+		.reg temp
+		.reg eop
+
+		#if CHANNEL_FLAG_RECEIVING != 1
+		#error CHANNEL_FLAG_RECEIVING is not 1
+		#endif
+
+		alu_shf[temp, 1, and, $rsw0, >>15]
+		alu[temp, temp, xor, CHANNEL_FLAGS]
+		alu[--, temp, and, CHANNEL_FLAG_RECEIVING]
+		beq[abort_proterr#]
+
+		alu_shf[eop, 1, and, $rsw0, >>14]
+		alu[CHANNEL_FLAGS, temp, xor, eop]
+	.end
+
+	/*
+	 * Copy the mpacket into the right spot, and in case of EOP,
+	 * write back the descriptor and pass the packet on.
+	 */
+	.begin
+		.reg buffer_offset
+		.reg _packet_length
+		.reg _packet_checksum
+		.reg _buffer_handle
+		.reg _buffer_start
+		.reg _buffer_length
+
+		/*
+		 * Determine buffer_offset, _packet_length and
+		 * _packet_checksum.
+		 */
+		.begin
+			.reg temp
+
+			alu[--, 1, and, $rsw0, >>15]
+			beq[not_sop#]
+
+			immed[PACKET_LENGTH, 0]
+			immed[PACKET_CHECKSUM, 0]
+
+		not_sop#:
+			alu[buffer_offset, --, b, PACKET_LENGTH]
+			alu_shf[temp, 0xff, and, $rsw0, >>16]
+			alu[_packet_length, buffer_offset, +, temp]
+			alu[PACKET_LENGTH, --, b, _packet_length]
+
+			immed[temp, 0xffff]
+			alu[temp, $rsw1, and, temp]
+			alu[_packet_checksum, PACKET_CHECKSUM, +, temp]
+			alu[PACKET_CHECKSUM, --, b, _packet_checksum]
+		.end
+
+		/*
+		 * Allocate buffer in case of SOP.
+		 */
+		.begin
+			.reg temp
+
+			alu[temp, 1, and, $rsw0, >>15]
+			beq[skip_buffer_alloc#]
+
+			.begin
+				.sig zzz
+				.reg read $stemp $stemp2
+				.xfer_order $stemp $stemp2
+
+			rx_nobufs#:
+				scratch[get, $stemp, zero, 0, 1], ctx_swap[zzz]
+				alu[_buffer_handle, --, b, $stemp]
+				beq[rx_nobufs#]
+
+				sram[read, $stemp, _buffer_handle, 0, 2],
+								ctx_swap[zzz]
+				alu[_buffer_start, --, b, $stemp]
+				alu[_buffer_length, --, b, $stemp2]
+			.end
+
+		skip_buffer_alloc#:
+		.end
+
+		/*
+		 * Resynchronise.
+		 */
+		.begin
+			ctx_arb[sig2]
+			local_csr_wr[SAME_ME_SIGNAL, (0x80 | (&sig2 << 3))]
+		.end
+
+		/*
+		 * Synchronise buffer state.
+		 */
+		.begin
+			.reg temp
+
+			alu[temp, 1, and, $rsw0, >>15]
+			beq[copy_from_local_mem#]
+
+			alu[BUFFER_HANDLE, --, b, _buffer_handle]
+			alu[BUFFER_START, --, b, _buffer_start]
+			alu[BUFFER_LENGTH, --, b, _buffer_length]
+			br[sync_state_done#]
+
+		copy_from_local_mem#:
+			alu[_buffer_handle, --, b, BUFFER_HANDLE]
+			alu[_buffer_start, --, b, BUFFER_START]
+			alu[_buffer_length, --, b, BUFFER_LENGTH]
+
+		sync_state_done#:
+		.end
+
+#if 0
+		/*
+		 * Debug buffer state management.
+		 */
+		.begin
+			.reg temp
+
+			alu[temp, 1, and, $rsw0, >>14]
+			beq[no_poison#]
+			immed[BUFFER_HANDLE, 0xdead]
+			immed[BUFFER_START, 0xdead]
+			immed[BUFFER_LENGTH, 0xdead]
+		no_poison#:
+
+			immed[temp, 0xdead]
+			alu[--, _buffer_handle, -, temp]
+			beq[state_corrupted#]
+			alu[--, _buffer_start, -, temp]
+			beq[state_corrupted#]
+			alu[--, _buffer_length, -, temp]
+			beq[state_corrupted#]
+		.end
+#endif
+
+		/*
+		 * Check buffer length.
+		 */
+		.begin
+			alu[--, _buffer_length, -, _packet_length]
+			blo[buffer_overflow#]
+		.end
+
+		/*
+		 * Copy the mpacket and give back the RBUF element.
+		 */
+		.begin
+			.reg element
+			.reg xfer_size
+			.reg temp
+			.sig copy_sig
+
+			alu_shf[element, 0x7f, and, $rsw0, >>24]
+			alu_shf[xfer_size, 0xff, and, $rsw0, >>16]
+
+			alu[xfer_size, xfer_size, -, 1]
+			alu_shf[xfer_size, 0x10, or, xfer_size, >>3]
+			alu_shf[temp, 0x10, or, xfer_size, <<21]
+			alu_shf[temp, temp, or, element, <<11]
+			alu_shf[--, temp, or, 1, <<18]
+
+			dram[rbuf_rd, --, _buffer_start, buffer_offset, max_8],
+						indirect_ref, sig_done[copy_sig]
+			ctx_arb[copy_sig]
+
+			alu[temp, RBUF_ELEMENT_DONE, or, element, <<16]
+			msf[fast_wr, --, temp, 0]
+		.end
+
+		/*
+		 * If EOP, write back the packet descriptor.
+		 */
+		.begin
+			.reg write $stemp $stemp2
+			.xfer_order $stemp $stemp2
+			.sig zzz
+
+			alu_shf[--, 1, and, $rsw0, >>14]
+			beq[no_writeback#]
+
+			alu[$stemp, $rsw0, and, 0x1f]
+			alu[$stemp2, --, b, _packet_length]
+			sram[write, $stemp, _buffer_handle, 8, 2], ctx_swap[zzz]
+
+		no_writeback#:
+		.end
+
+		/*
+		 * Resynchronise.
+		 */
+		.begin
+			ctx_arb[sig3]
+			local_csr_wr[SAME_ME_SIGNAL, (0x80 | (&sig3 << 3))]
+		.end
+
+		/*
+		 * If EOP, put the buffer back onto the scratch ring.
+		 */
+		.begin
+			.reg write $stemp
+			.sig zzz
+
+			br_inp_state[SCR_Ring1_Status, rx_done_ring_overflow#]
+
+			alu_shf[--, 1, and, $rsw0, >>14]
+			beq[mpacket_receive_loop#]
+
+			alu[--, 1, and, $rsw0, >>10]
+			bne[rxerr#]
+
+			alu[$stemp, --, b, _buffer_handle]
+			scratch[put, $stemp, zero, 4, 1], ctx_swap[zzz]
+			cap[fast_wr, 0, XSCALE_INT_A]
+			br[mpacket_receive_loop#]
+
+		rxerr#:
+			alu[$stemp, --, b, _buffer_handle]
+			scratch[put, $stemp, zero, 0, 1], ctx_swap[zzz]
+			br[mpacket_receive_loop#]
+		.end
+	.end
+
+
+abort_rswerr#:
+	halt
+
+abort_proterr#:
+	halt
+
+state_corrupted#:
+	halt
+
+buffer_overflow#:
+	halt
+
+rx_done_ring_overflow#:
+	halt
+
+
diff --git a/drivers/net/ixp2000/ixp2400_rx.ucode b/drivers/net/ixp2000/ixp2400_rx.ucode
new file mode 100644
index 000000000000..e8aee2f81aad
--- /dev/null
+++ b/drivers/net/ixp2000/ixp2400_rx.ucode
@@ -0,0 +1,130 @@
+static struct ixp2000_uengine_code ixp2400_rx =
+{
+	.cpu_model_bitmask	= 0x000003fe,
+	.cpu_min_revision	= 0,
+	.cpu_max_revision	= 255,
+
+	.uengine_parameters	= IXP2000_UENGINE_8_CONTEXTS |
+				  IXP2000_UENGINE_PRN_UPDATE_EVERY |
+				  IXP2000_UENGINE_NN_FROM_PREVIOUS |
+				  IXP2000_UENGINE_ASSERT_EMPTY_AT_0 |
+				  IXP2000_UENGINE_LM_ADDR1_PER_CONTEXT |
+				  IXP2000_UENGINE_LM_ADDR0_PER_CONTEXT,
+
+	.initial_reg_values	= (struct ixp2000_reg_value []) {
+		{ -1, -1 }
+	},
+
+	.num_insns		= 109,
+	.insns			= (u8 []) {
+		0xf0, 0x00, 0x0c, 0xc0, 0x05,
+		0xf4, 0x44, 0x0c, 0x00, 0x05,
+		0xfc, 0x04, 0x4c, 0x00, 0x00,
+		0xf0, 0x00, 0x00, 0x3b, 0x00,
+		0xb4, 0x40, 0xf0, 0x3b, 0x1f,
+		0x8a, 0xc0, 0x50, 0x3e, 0x05,
+		0xb4, 0x40, 0xf0, 0x3b, 0x80,
+		0x9a, 0xe0, 0x00, 0x3e, 0x05,
+		0xf0, 0x00, 0x00, 0x07, 0x00,
+		0xd8, 0x05, 0xc0, 0x00, 0x11,
+		0xf0, 0x00, 0x00, 0x0f, 0x00,
+		0x91, 0xb0, 0x20, 0x0e, 0x00,
+		0xfc, 0x06, 0x60, 0x0b, 0x00,
+		0xf0, 0x00, 0x0c, 0x03, 0x00,
+		0xf0, 0x00, 0x0c, 0x03, 0x00,
+		0xf0, 0x00, 0x0c, 0x03, 0x00,
+		0xf0, 0x00, 0x0c, 0x02, 0x00,
+		0xb0, 0xc0, 0x30, 0x0f, 0x01,
+		0xa4, 0x70, 0x00, 0x0f, 0x20,
+		0xd8, 0x02, 0xc0, 0x01, 0x00,
+		0xfc, 0x10, 0xac, 0x23, 0x08,
+		0xfc, 0x10, 0xac, 0x43, 0x10,
+		0xfc, 0x10, 0xac, 0x63, 0x18,
+		0xe0, 0x00, 0x00, 0x00, 0x02,
+		0xfc, 0x10, 0xae, 0x23, 0x88,
+		0x3d, 0x00, 0x04, 0x03, 0x20,
+		0xe0, 0x00, 0x00, 0x00, 0x10,
+		0x84, 0x82, 0x02, 0x01, 0x3b,
+		0xd8, 0x1a, 0x00, 0x01, 0x01,
+		0xb4, 0x00, 0x8c, 0x7d, 0x80,
+		0x91, 0xb0, 0x80, 0x22, 0x00,
+		0xfc, 0x06, 0x60, 0x23, 0x00,
+		0xf0, 0x00, 0x0c, 0x03, 0x00,
+		0xf0, 0x00, 0x0c, 0x03, 0x00,
+		0xf0, 0x00, 0x0c, 0x03, 0x00,
+		0x94, 0xf0, 0x92, 0x01, 0x21,
+		0xac, 0x40, 0x60, 0x26, 0x00,
+		0xa4, 0x30, 0x0c, 0x04, 0x06,
+		0xd8, 0x1a, 0x40, 0x01, 0x00,
+		0x94, 0xe0, 0xa2, 0x01, 0x21,
+		0xac, 0x20, 0x00, 0x28, 0x06,
+		0x84, 0xf2, 0x02, 0x01, 0x21,
+		0xd8, 0x0b, 0x40, 0x01, 0x00,
+		0xf0, 0x00, 0x0c, 0x02, 0x01,
+		0xf0, 0x00, 0x0c, 0x02, 0x02,
+		0xa0, 0x00, 0x08, 0x04, 0x00,
+		0x95, 0x00, 0xc6, 0x01, 0xff,
+		0xa0, 0x80, 0x10, 0x30, 0x00,
+		0xa0, 0x60, 0x1c, 0x00, 0x01,
+		0xf0, 0x0f, 0xf0, 0x33, 0xff,
+		0xb4, 0x00, 0xc0, 0x31, 0x81,
+		0xb0, 0x80, 0xb0, 0x32, 0x02,
+		0xa0, 0x20, 0x20, 0x2c, 0x00,
+		0x94, 0xf0, 0xd2, 0x01, 0x21,
+		0xd8, 0x0f, 0x40, 0x01, 0x00,
+		0x19, 0x40, 0x10, 0x04, 0x20,
+		0xa0, 0x00, 0x26, 0x04, 0x00,
+		0xd8, 0x0d, 0xc0, 0x01, 0x00,
+		0x00, 0x42, 0x10, 0x80, 0x02,
+		0xb0, 0x00, 0x46, 0x04, 0x00,
+		0xb0, 0x00, 0x56, 0x08, 0x00,
+		0xe0, 0x00, 0x00, 0x00, 0x04,
+		0xfc, 0x10, 0xae, 0x43, 0x90,
+		0x84, 0xf0, 0x32, 0x01, 0x21,
+		0xd8, 0x11, 0x40, 0x01, 0x00,
+		0xa0, 0x60, 0x3c, 0x00, 0x02,
+		0xa0, 0x20, 0x40, 0x10, 0x00,
+		0xa0, 0x20, 0x50, 0x14, 0x00,
+		0xd8, 0x12, 0x00, 0x00, 0x18,
+		0xa0, 0x00, 0x28, 0x0c, 0x00,
+		0xb0, 0x00, 0x48, 0x10, 0x00,
+		0xb0, 0x00, 0x58, 0x14, 0x00,
+		0xaa, 0xf0, 0x00, 0x14, 0x01,
+		0xd8, 0x1a, 0xc0, 0x01, 0x05,
+		0x85, 0x80, 0x42, 0x01, 0xff,
+		0x95, 0x00, 0x66, 0x01, 0xff,
+		0xba, 0xc0, 0x60, 0x1b, 0x01,
+		0x9a, 0x30, 0x60, 0x19, 0x30,
+		0x9a, 0xb0, 0x70, 0x1a, 0x30,
+		0x9b, 0x50, 0x78, 0x1e, 0x04,
+		0x8a, 0xe2, 0x08, 0x1e, 0x21,
+		0x6a, 0x4e, 0x00, 0x13, 0x00,
+		0xe0, 0x00, 0x00, 0x00, 0x30,
+		0x9b, 0x00, 0x7a, 0x92, 0x04,
+		0x3d, 0x00, 0x04, 0x1f, 0x20,
+		0x84, 0xe2, 0x02, 0x01, 0x21,
+		0xd8, 0x16, 0x80, 0x01, 0x00,
+		0xa4, 0x18, 0x0c, 0x7d, 0x80,
+		0xa0, 0x58, 0x1c, 0x00, 0x01,
+		0x01, 0x42, 0x00, 0xa0, 0x02,
+		0xe0, 0x00, 0x00, 0x00, 0x08,
+		0xfc, 0x10, 0xae, 0x63, 0x98,
+		0xd8, 0x1b, 0x00, 0xc2, 0x14,
+		0x84, 0xe2, 0x02, 0x01, 0x21,
+		0xd8, 0x05, 0xc0, 0x01, 0x00,
+		0x84, 0xa2, 0x02, 0x01, 0x21,
+		0xd8, 0x19, 0x40, 0x01, 0x01,
+		0xa0, 0x58, 0x0c, 0x00, 0x02,
+		0x1a, 0x40, 0x00, 0x04, 0x24,
+		0x33, 0x00, 0x01, 0x2f, 0x20,
+		0xd8, 0x05, 0xc0, 0x00, 0x18,
+		0xa0, 0x58, 0x0c, 0x00, 0x02,
+		0x1a, 0x40, 0x00, 0x04, 0x20,
+		0xd8, 0x05, 0xc0, 0x00, 0x18,
+		0xe0, 0x00, 0x02, 0x00, 0x00,
+		0xe0, 0x00, 0x02, 0x00, 0x00,
+		0xe0, 0x00, 0x02, 0x00, 0x00,
+		0xe0, 0x00, 0x02, 0x00, 0x00,
+		0xe0, 0x00, 0x02, 0x00, 0x00,
+	}
+};
diff --git a/drivers/net/ixp2000/ixp2400_tx.uc b/drivers/net/ixp2000/ixp2400_tx.uc
new file mode 100644
index 000000000000..d090d1884fb7
--- /dev/null
+++ b/drivers/net/ixp2000/ixp2400_tx.uc
@@ -0,0 +1,272 @@
+/*
+ * TX ucode for the Intel IXP2400 in POS-PHY mode.
+ * Copyright (C) 2004, 2005 Lennert Buytenhek
+ * Dedicated to Marija Kulikova.
+ *
+ * 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.
+ *
+ * Assumptions made in this code:
+ * - The IXP2400 MSF is configured for POS-PHY mode, in a mode where
+ *   only one TBUF partition is used.  This includes, for example,
+ *   1x32 SPHY and 1x32 MPHY32, but not 4x8 SPHY or 1x32 MPHY4. (This
+ *   is not an exhaustive list.)
+ * - The TBUF uses 64-byte mpackets.
+ * - TX descriptors reside in SRAM, and have the following format:
+ *	struct tx_desc
+ *	{
+ *	// to uengine
+ *		u32	buf_phys_addr;
+ *		u32	pkt_length;
+ *		u32	channel;
+ *	};
+ * - Packet data resides in DRAM.
+ * - Packet buffer addresses are 8-byte aligned.
+ * - Scratch ring 2 is tx_pending.
+ * - Scratch ring 3 is tx_done, and has status condition 'full'.
+ * - This code is run on all eight threads of the microengine it runs on.
+ */
+
+#define TX_SEQUENCE_0		0x0060
+#define TBUF_CTRL		0x1800
+
+#define PARTITION_SIZE		128
+#define PARTITION_THRESH	96
+
+
+	.sig volatile sig1
+	.sig volatile sig2
+	.sig volatile sig3
+
+	.reg @old_tx_seq_0
+	.reg @mpkts_in_flight
+	.reg @next_tbuf_mpacket
+
+	.reg @buffer_handle
+	.reg @buffer_start
+	.reg @packet_length
+	.reg @channel
+	.reg @packet_offset
+
+	.reg zero
+
+	immed[zero, 0]
+
+	/*
+	 * Skip context 0 initialisation?
+	 */
+	.begin
+		br!=ctx[0, mpacket_tx_loop#]
+	.end
+
+	/*
+	 * Wait until all pending TBUF elements have been transmitted.
+	 */
+	.begin
+		.reg read $tx
+		.sig zzz
+
+	loop_empty#:
+		msf[read, $tx, zero, TX_SEQUENCE_0, 1], ctx_swap[zzz]
+		alu_shf[--, --, b, $tx, >>31]
+		beq[loop_empty#]
+
+		alu[@old_tx_seq_0, --, b, $tx]
+	.end
+
+	immed[@mpkts_in_flight, 0]
+	alu[@next_tbuf_mpacket, @old_tx_seq_0, and, (PARTITION_SIZE - 1)]
+
+	immed[@buffer_handle, 0]
+
+	/*
+	 * Initialise signal pipeline.
+	 */
+	.begin
+		local_csr_wr[SAME_ME_SIGNAL, (&sig1 << 3)]
+		.set_sig sig1
+
+		local_csr_wr[SAME_ME_SIGNAL, (&sig2 << 3)]
+		.set_sig sig2
+
+		local_csr_wr[SAME_ME_SIGNAL, (&sig3 << 3)]
+		.set_sig sig3
+	.end
+
+mpacket_tx_loop#:
+	.begin
+		.reg tbuf_element_index
+		.reg buffer_handle
+		.reg sop_eop
+		.reg packet_data
+		.reg channel
+		.reg mpacket_size
+
+		/*
+		 * If there is no packet currently being transmitted,
+		 * dequeue the next TX descriptor, and fetch the buffer
+		 * address, packet length and destination channel number.
+		 */
+		.begin
+			.reg read $stemp $stemp2 $stemp3
+			.xfer_order $stemp $stemp2 $stemp3
+			.sig zzz
+
+			ctx_arb[sig1]
+
+			alu[--, --, b, @buffer_handle]
+			bne[already_got_packet#]
+
+		tx_nobufs#:
+			scratch[get, $stemp, zero, 8, 1], ctx_swap[zzz]
+			alu[@buffer_handle, --, b, $stemp]
+			beq[tx_nobufs#]
+
+			sram[read, $stemp, $stemp, 0, 3], ctx_swap[zzz]
+			alu[@buffer_start, --, b, $stemp]
+			alu[@packet_length, --, b, $stemp2]
+			beq[zero_byte_packet#]
+			alu[@channel, --, b, $stemp3]
+			immed[@packet_offset, 0]
+
+		already_got_packet#:
+			local_csr_wr[SAME_ME_SIGNAL, (0x80 | (&sig1 << 3))]
+		.end
+
+		/*
+		 * Determine tbuf element index, SOP/EOP flags, mpacket
+		 * offset and mpacket size and cache buffer_handle and
+		 * channel number.
+		 */
+		.begin
+			alu[tbuf_element_index, --, b, @next_tbuf_mpacket]
+			alu[@next_tbuf_mpacket, @next_tbuf_mpacket, +, 1]
+			alu[@next_tbuf_mpacket, @next_tbuf_mpacket, and,
+							(PARTITION_SIZE - 1)]
+
+			alu[buffer_handle, --, b, @buffer_handle]
+			immed[@buffer_handle, 0]
+
+			immed[sop_eop, 1]
+
+			alu[packet_data, --, b, @packet_offset]
+			bne[no_sop#]
+			alu[sop_eop, sop_eop, or, 2]
+		no_sop#:
+			alu[packet_data, packet_data, +, @buffer_start]
+
+			alu[channel, --, b, @channel]
+
+			alu[mpacket_size, @packet_length, -, @packet_offset]
+			alu[--, 64, -, mpacket_size]
+			bhs[eop#]
+			alu[@buffer_handle, --, b, buffer_handle]
+			immed[mpacket_size, 64]
+			alu[sop_eop, sop_eop, and, 2]
+		eop#:
+
+			alu[@packet_offset, @packet_offset, +, mpacket_size]
+		.end
+
+		/*
+		 * Wait until there's enough space in the TBUF.
+		 */
+		.begin
+			.reg read $tx
+			.reg temp
+			.sig zzz
+
+			ctx_arb[sig2]
+
+			br[test_space#]
+
+		loop_space#:
+			msf[read, $tx, zero, TX_SEQUENCE_0, 1], ctx_swap[zzz]
+
+			alu[temp, $tx, -, @old_tx_seq_0]
+			alu[temp, temp, and, 0xff]
+			alu[@mpkts_in_flight, @mpkts_in_flight, -, temp]
+
+			alu[@old_tx_seq_0, --, b, $tx]
+
+		test_space#:
+			alu[--, PARTITION_THRESH, -, @mpkts_in_flight]
+			blo[loop_space#]
+
+			alu[@mpkts_in_flight, @mpkts_in_flight, +, 1]
+
+			local_csr_wr[SAME_ME_SIGNAL, (0x80 | (&sig2 << 3))]
+		.end
+
+		/*
+		 * Copy the packet data to the TBUF.
+		 */
+		.begin
+			.reg temp
+			.sig copy_sig
+
+			alu[temp, mpacket_size, -, 1]
+			alu_shf[temp, 0x10, or, temp, >>3]
+			alu_shf[temp, 0x10, or, temp, <<21]
+			alu_shf[temp, temp, or, tbuf_element_index, <<11]
+			alu_shf[--, temp, or, 1, <<18]
+
+			dram[tbuf_wr, --, packet_data, 0, max_8],
+					indirect_ref, sig_done[copy_sig]
+			ctx_arb[copy_sig]
+		.end
+
+		/*
+		 * Mark TBUF element as ready-to-be-transmitted.
+		 */
+		.begin
+			.reg write $tsw $tsw2
+			.xfer_order $tsw $tsw2
+			.reg temp
+			.sig zzz
+
+			alu_shf[temp, channel, or, mpacket_size, <<24]
+			alu_shf[$tsw, temp, or, sop_eop, <<8]
+			immed[$tsw2, 0]
+
+			immed[temp, TBUF_CTRL]
+			alu_shf[temp, temp, or, tbuf_element_index, <<3]
+			msf[write, $tsw, temp, 0, 2], ctx_swap[zzz]
+		.end
+
+		/*
+		 * Resynchronise.
+		 */
+		.begin
+			ctx_arb[sig3]
+			local_csr_wr[SAME_ME_SIGNAL, (0x80 | (&sig3 << 3))]
+		.end
+
+		/*
+		 * If this was an EOP mpacket, recycle the TX buffer
+	 	 * and signal the host.
+		 */
+		.begin
+			.reg write $stemp
+			.sig zzz
+
+			alu[--, sop_eop, and, 1]
+			beq[mpacket_tx_loop#]
+
+		tx_done_ring_full#:
+			br_inp_state[SCR_Ring3_Status, tx_done_ring_full#]
+
+			alu[$stemp, --, b, buffer_handle]
+			scratch[put, $stemp, zero, 12, 1], ctx_swap[zzz]
+			cap[fast_wr, 0, XSCALE_INT_A]
+			br[mpacket_tx_loop#]
+		.end
+	.end
+
+
+zero_byte_packet#:
+	halt
+
+
diff --git a/drivers/net/ixp2000/ixp2400_tx.ucode b/drivers/net/ixp2000/ixp2400_tx.ucode
new file mode 100644
index 000000000000..a433e24b0a51
--- /dev/null
+++ b/drivers/net/ixp2000/ixp2400_tx.ucode
@@ -0,0 +1,98 @@
+static struct ixp2000_uengine_code ixp2400_tx =
+{
+	.cpu_model_bitmask	= 0x000003fe,
+	.cpu_min_revision	= 0,
+	.cpu_max_revision	= 255,
+
+	.uengine_parameters	= IXP2000_UENGINE_8_CONTEXTS |
+				  IXP2000_UENGINE_PRN_UPDATE_EVERY |
+				  IXP2000_UENGINE_NN_FROM_PREVIOUS |
+				  IXP2000_UENGINE_ASSERT_EMPTY_AT_0 |
+				  IXP2000_UENGINE_LM_ADDR1_PER_CONTEXT |
+				  IXP2000_UENGINE_LM_ADDR0_PER_CONTEXT,
+
+	.initial_reg_values	= (struct ixp2000_reg_value []) {
+		{ -1, -1 }
+	},
+
+	.num_insns		= 77,
+	.insns			= (u8 []) {
+		0xf0, 0x00, 0x00, 0x07, 0x00,
+		0xd8, 0x03, 0x00, 0x00, 0x11,
+		0x3c, 0x40, 0x00, 0x04, 0xe0,
+		0x81, 0xf2, 0x02, 0x01, 0x00,
+		0xd8, 0x00, 0x80, 0x01, 0x00,
+		0xb0, 0x08, 0x06, 0x00, 0x00,
+		0xf0, 0x00, 0x0c, 0x00, 0x80,
+		0xb4, 0x49, 0x02, 0x03, 0x7f,
+		0xf0, 0x00, 0x02, 0x83, 0x00,
+		0xfc, 0x10, 0xac, 0x23, 0x08,
+		0xfc, 0x10, 0xac, 0x43, 0x10,
+		0xfc, 0x10, 0xac, 0x63, 0x18,
+		0xe0, 0x00, 0x00, 0x00, 0x02,
+		0xa0, 0x30, 0x02, 0x80, 0x00,
+		0xd8, 0x06, 0x00, 0x01, 0x01,
+		0x19, 0x40, 0x00, 0x04, 0x28,
+		0xb0, 0x0a, 0x06, 0x00, 0x00,
+		0xd8, 0x03, 0xc0, 0x01, 0x00,
+		0x00, 0x44, 0x00, 0x80, 0x80,
+		0xa0, 0x09, 0x06, 0x00, 0x00,
+		0xb0, 0x0b, 0x06, 0x04, 0x00,
+		0xd8, 0x13, 0x00, 0x01, 0x00,
+		0xb0, 0x0c, 0x06, 0x08, 0x00,
+		0xf0, 0x00, 0x0c, 0x00, 0xa0,
+		0xfc, 0x10, 0xae, 0x23, 0x88,
+		0xa0, 0x00, 0x12, 0x40, 0x00,
+		0xb0, 0xc9, 0x02, 0x43, 0x01,
+		0xb4, 0x49, 0x02, 0x43, 0x7f,
+		0xb0, 0x00, 0x22, 0x80, 0x00,
+		0xf0, 0x00, 0x02, 0x83, 0x00,
+		0xf0, 0x00, 0x0c, 0x04, 0x02,
+		0xb0, 0x40, 0x6c, 0x00, 0xa0,
+		0xd8, 0x08, 0x80, 0x01, 0x01,
+		0xaa, 0x00, 0x2c, 0x08, 0x02,
+		0xa0, 0xc0, 0x30, 0x18, 0x90,
+		0xa0, 0x00, 0x43, 0x00, 0x00,
+		0xba, 0xc0, 0x32, 0xc0, 0xa0,
+		0xaa, 0xb0, 0x00, 0x0f, 0x40,
+		0xd8, 0x0a, 0x80, 0x01, 0x04,
+		0xb0, 0x0a, 0x00, 0x08, 0x00,
+		0xf0, 0x00, 0x00, 0x0f, 0x40,
+		0xa4, 0x00, 0x2c, 0x08, 0x02,
+		0xa0, 0x8a, 0x00, 0x0c, 0xa0,
+		0xe0, 0x00, 0x00, 0x00, 0x04,
+		0xd8, 0x0c, 0x80, 0x00, 0x18,
+		0x3c, 0x40, 0x00, 0x04, 0xe0,
+		0xba, 0x80, 0x42, 0x01, 0x80,
+		0xb4, 0x40, 0x40, 0x13, 0xff,
+		0xaa, 0x88, 0x00, 0x10, 0x80,
+		0xb0, 0x08, 0x06, 0x00, 0x00,
+		0xaa, 0xf0, 0x0d, 0x80, 0x80,
+		0xd8, 0x0b, 0x40, 0x01, 0x05,
+		0xa0, 0x88, 0x0c, 0x04, 0x80,
+		0xfc, 0x10, 0xae, 0x43, 0x90,
+		0xba, 0xc0, 0x50, 0x0f, 0x01,
+		0x9a, 0x30, 0x50, 0x15, 0x30,
+		0x9a, 0xb0, 0x50, 0x16, 0x30,
+		0x9b, 0x50, 0x58, 0x16, 0x01,
+		0x8a, 0xe2, 0x08, 0x16, 0x21,
+		0x6b, 0x4e, 0x00, 0x83, 0x03,
+		0xe0, 0x00, 0x00, 0x00, 0x30,
+		0x9a, 0x80, 0x70, 0x0e, 0x04,
+		0x8b, 0x88, 0x08, 0x1e, 0x02,
+		0xf0, 0x00, 0x0c, 0x01, 0x81,
+		0xf0, 0x01, 0x80, 0x1f, 0x00,
+		0x9b, 0xd0, 0x78, 0x1e, 0x01,
+		0x3d, 0x42, 0x00, 0x1c, 0x20,
+		0xe0, 0x00, 0x00, 0x00, 0x08,
+		0xfc, 0x10, 0xae, 0x63, 0x98,
+		0xa4, 0x30, 0x0c, 0x04, 0x02,
+		0xd8, 0x03, 0x00, 0x01, 0x00,
+		0xd8, 0x11, 0xc1, 0x42, 0x14,
+		0xa0, 0x18, 0x00, 0x08, 0x00,
+		0x1a, 0x40, 0x00, 0x04, 0x2c,
+		0x33, 0x00, 0x01, 0x2f, 0x20,
+		0xd8, 0x03, 0x00, 0x00, 0x18,
+		0xe0, 0x00, 0x02, 0x00, 0x00,
+	}
+};
diff --git a/drivers/net/ixp2000/ixpdev.c b/drivers/net/ixp2000/ixpdev.c
new file mode 100644
index 000000000000..09f03f493bea
--- /dev/null
+++ b/drivers/net/ixp2000/ixpdev.c
@@ -0,0 +1,421 @@
+/*
+ * IXP2000 MSF network device driver
+ * Copyright (C) 2004, 2005 Lennert Buytenhek <buytenh@wantstofly.org>
+ * Dedicated to Marija Kulikova.
+ *
+ * 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/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/init.h>
+#include <linux/moduleparam.h>
+#include <asm/arch/uengine.h>
+#include <asm/mach-types.h>
+#include <asm/io.h>
+#include "ixp2400_rx.ucode"
+#include "ixp2400_tx.ucode"
+#include "ixpdev_priv.h"
+#include "ixpdev.h"
+
+#define DRV_MODULE_VERSION	"0.2"
+
+static int nds_count;
+static struct net_device **nds;
+static int nds_open;
+static void (*set_port_admin_status)(int port, int up);
+
+static struct ixpdev_rx_desc * const rx_desc =
+	(struct ixpdev_rx_desc *)(IXP2000_SRAM0_VIRT_BASE + RX_BUF_DESC_BASE);
+static struct ixpdev_tx_desc * const tx_desc =
+	(struct ixpdev_tx_desc *)(IXP2000_SRAM0_VIRT_BASE + TX_BUF_DESC_BASE);
+static int tx_pointer;
+
+
+static int ixpdev_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct ixpdev_priv *ip = netdev_priv(dev);
+	struct ixpdev_tx_desc *desc;
+	int entry;
+
+	if (unlikely(skb->len > PAGE_SIZE)) {
+		/* @@@ Count drops.  */
+		dev_kfree_skb(skb);
+		return 0;
+	}
+
+	entry = tx_pointer;
+	tx_pointer = (tx_pointer + 1) % TX_BUF_COUNT;
+
+	desc = tx_desc + entry;
+	desc->pkt_length = skb->len;
+	desc->channel = ip->channel;
+
+	skb_copy_and_csum_dev(skb, phys_to_virt(desc->buf_addr));
+	dev_kfree_skb(skb);
+
+	ixp2000_reg_write(RING_TX_PENDING,
+		TX_BUF_DESC_BASE + (entry * sizeof(struct ixpdev_tx_desc)));
+
+	dev->trans_start = jiffies;
+
+	local_irq_disable();
+	ip->tx_queue_entries++;
+	if (ip->tx_queue_entries == TX_BUF_COUNT_PER_CHAN)
+		netif_stop_queue(dev);
+	local_irq_enable();
+
+	return 0;
+}
+
+
+static int ixpdev_rx(struct net_device *dev, int *budget)
+{
+	while (*budget > 0) {
+		struct ixpdev_rx_desc *desc;
+		struct sk_buff *skb;
+		void *buf;
+		u32 _desc;
+
+		_desc = ixp2000_reg_read(RING_RX_DONE);
+		if (_desc == 0)
+			return 0;
+
+		desc = rx_desc +
+			((_desc - RX_BUF_DESC_BASE) / sizeof(struct ixpdev_rx_desc));
+		buf = phys_to_virt(desc->buf_addr);
+
+		if (desc->pkt_length < 4 || desc->pkt_length > PAGE_SIZE) {
+			printk(KERN_ERR "ixp2000: rx err, length %d\n",
+					desc->pkt_length);
+			goto err;
+		}
+
+		if (desc->channel < 0 || desc->channel >= nds_count) {
+			printk(KERN_ERR "ixp2000: rx err, channel %d\n",
+					desc->channel);
+			goto err;
+		}
+
+		/* @@@ Make FCS stripping configurable.  */
+		desc->pkt_length -= 4;
+
+		if (unlikely(!netif_running(nds[desc->channel])))
+			goto err;
+
+		skb = dev_alloc_skb(desc->pkt_length + 2);
+		if (likely(skb != NULL)) {
+			skb->dev = nds[desc->channel];
+			skb_reserve(skb, 2);
+			eth_copy_and_sum(skb, buf, desc->pkt_length, 0);
+			skb_put(skb, desc->pkt_length);
+			skb->protocol = eth_type_trans(skb, skb->dev);
+
+			skb->dev->last_rx = jiffies;
+
+			netif_receive_skb(skb);
+		}
+
+err:
+		ixp2000_reg_write(RING_RX_PENDING, _desc);
+		dev->quota--;
+		(*budget)--;
+	}
+
+	return 1;
+}
+
+/* dev always points to nds[0].  */
+static int ixpdev_poll(struct net_device *dev, int *budget)
+{
+	/* @@@ Have to stop polling when nds[0] is administratively
+	 * downed while we are polling.  */
+	do {
+		ixp2000_reg_write(IXP2000_IRQ_THD_RAW_STATUS_A_0, 0x00ff);
+
+		if (ixpdev_rx(dev, budget))
+			return 1;
+	} while (ixp2000_reg_read(IXP2000_IRQ_THD_RAW_STATUS_A_0) & 0x00ff);
+
+	netif_rx_complete(dev);
+	ixp2000_reg_write(IXP2000_IRQ_THD_ENABLE_SET_A_0, 0x00ff);
+
+	return 0;
+}
+
+static void ixpdev_tx_complete(void)
+{
+	int channel;
+	u32 wake;
+
+	wake = 0;
+	while (1) {
+		struct ixpdev_priv *ip;
+		u32 desc;
+		int entry;
+
+		desc = ixp2000_reg_read(RING_TX_DONE);
+		if (desc == 0)
+			break;
+
+		/* @@@ Check whether entries come back in order.  */
+		entry = (desc - TX_BUF_DESC_BASE) / sizeof(struct ixpdev_tx_desc);
+		channel = tx_desc[entry].channel;
+
+		if (channel < 0 || channel >= nds_count) {
+			printk(KERN_ERR "ixp2000: txcomp channel index "
+					"out of bounds (%d, %.8i, %d)\n",
+					channel, (unsigned int)desc, entry);
+			continue;
+		}
+
+		ip = netdev_priv(nds[channel]);
+		if (ip->tx_queue_entries == TX_BUF_COUNT_PER_CHAN)
+			wake |= 1 << channel;
+		ip->tx_queue_entries--;
+	}
+
+	for (channel = 0; wake != 0; channel++) {
+		if (wake & (1 << channel)) {
+			netif_wake_queue(nds[channel]);
+			wake &= ~(1 << channel);
+		}
+	}
+}
+
+static irqreturn_t ixpdev_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	u32 status;
+
+	status = ixp2000_reg_read(IXP2000_IRQ_THD_STATUS_A_0);
+	if (status == 0)
+		return IRQ_NONE;
+
+	/*
+	 * Any of the eight receive units signaled RX?
+	 */
+	if (status & 0x00ff) {
+		ixp2000_reg_wrb(IXP2000_IRQ_THD_ENABLE_CLEAR_A_0, 0x00ff);
+		if (likely(__netif_rx_schedule_prep(nds[0]))) {
+			__netif_rx_schedule(nds[0]);
+		} else {
+			printk(KERN_CRIT "ixp2000: irq while polling!!\n");
+		}
+	}
+
+	/*
+	 * Any of the eight transmit units signaled TXdone?
+	 */
+	if (status & 0xff00) {
+		ixp2000_reg_wrb(IXP2000_IRQ_THD_RAW_STATUS_A_0, 0xff00);
+		ixpdev_tx_complete();
+	}
+
+	return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void ixpdev_poll_controller(struct net_device *dev)
+{
+	disable_irq(IRQ_IXP2000_THDA0);
+	ixpdev_interrupt(IRQ_IXP2000_THDA0, dev, NULL);
+	enable_irq(IRQ_IXP2000_THDA0);
+}
+#endif
+
+static int ixpdev_open(struct net_device *dev)
+{
+	struct ixpdev_priv *ip = netdev_priv(dev);
+	int err;
+
+	if (!nds_open++) {
+		err = request_irq(IRQ_IXP2000_THDA0, ixpdev_interrupt,
+					SA_SHIRQ, "ixp2000_eth", nds);
+		if (err) {
+			nds_open--;
+			return err;
+		}
+
+		ixp2000_reg_write(IXP2000_IRQ_THD_ENABLE_SET_A_0, 0xffff);
+	}
+
+	set_port_admin_status(ip->channel, 1);
+	netif_start_queue(dev);
+
+	return 0;
+}
+
+static int ixpdev_close(struct net_device *dev)
+{
+	struct ixpdev_priv *ip = netdev_priv(dev);
+
+	netif_stop_queue(dev);
+	set_port_admin_status(ip->channel, 0);
+
+	if (!--nds_open) {
+		ixp2000_reg_write(IXP2000_IRQ_THD_ENABLE_CLEAR_A_0, 0xffff);
+		free_irq(IRQ_IXP2000_THDA0, nds);
+	}
+
+	return 0;
+}
+
+struct net_device *ixpdev_alloc(int channel, int sizeof_priv)
+{
+	struct net_device *dev;
+	struct ixpdev_priv *ip;
+
+	dev = alloc_etherdev(sizeof_priv);
+	if (dev == NULL)
+		return NULL;
+
+	dev->hard_start_xmit = ixpdev_xmit;
+	dev->poll = ixpdev_poll;
+	dev->open = ixpdev_open;
+	dev->stop = ixpdev_close;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = ixpdev_poll_controller;
+#endif
+
+	dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM;
+	dev->weight = 64;
+
+	ip = netdev_priv(dev);
+	ip->channel = channel;
+	ip->tx_queue_entries = 0;
+
+	return dev;
+}
+
+int ixpdev_init(int __nds_count, struct net_device **__nds,
+		void (*__set_port_admin_status)(int port, int up))
+{
+	int i;
+	int err;
+
+	if (RX_BUF_COUNT > 192 || TX_BUF_COUNT > 192) {
+		static void __too_many_rx_or_tx_buffers(void);
+		__too_many_rx_or_tx_buffers();
+	}
+
+	printk(KERN_INFO "IXP2000 MSF ethernet driver %s\n", DRV_MODULE_VERSION);
+
+	nds_count = __nds_count;
+	nds = __nds;
+	set_port_admin_status = __set_port_admin_status;
+
+	for (i = 0; i < RX_BUF_COUNT; i++) {
+		void *buf;
+
+		buf = (void *)get_zeroed_page(GFP_KERNEL);
+		if (buf == NULL) {
+			err = -ENOMEM;
+			while (--i >= 0)
+				free_page((unsigned long)phys_to_virt(rx_desc[i].buf_addr));
+			goto err_out;
+		}
+		rx_desc[i].buf_addr = virt_to_phys(buf);
+		rx_desc[i].buf_length = PAGE_SIZE;
+	}
+
+	/* @@@ Maybe we shouldn't be preallocating TX buffers.  */
+	for (i = 0; i < TX_BUF_COUNT; i++) {
+		void *buf;
+
+		buf = (void *)get_zeroed_page(GFP_KERNEL);
+		if (buf == NULL) {
+			err = -ENOMEM;
+			while (--i >= 0)
+				free_page((unsigned long)phys_to_virt(tx_desc[i].buf_addr));
+			goto err_free_rx;
+		}
+		tx_desc[i].buf_addr = virt_to_phys(buf);
+	}
+
+	/* 256 entries, ring status set means 'empty', base address 0x0000.  */
+	ixp2000_reg_write(RING_RX_PENDING_BASE, 0x44000000);
+	ixp2000_reg_write(RING_RX_PENDING_HEAD, 0x00000000);
+	ixp2000_reg_write(RING_RX_PENDING_TAIL, 0x00000000);
+
+	/* 256 entries, ring status set means 'full', base address 0x0400.  */
+	ixp2000_reg_write(RING_RX_DONE_BASE, 0x40000400);
+	ixp2000_reg_write(RING_RX_DONE_HEAD, 0x00000000);
+	ixp2000_reg_write(RING_RX_DONE_TAIL, 0x00000000);
+
+	for (i = 0; i < RX_BUF_COUNT; i++) {
+		ixp2000_reg_write(RING_RX_PENDING,
+			RX_BUF_DESC_BASE + (i * sizeof(struct ixpdev_rx_desc)));
+	}
+
+	ixp2000_uengine_load(0, &ixp2400_rx);
+	ixp2000_uengine_start_contexts(0, 0xff);
+
+	/* 256 entries, ring status set means 'empty', base address 0x0800.  */
+	ixp2000_reg_write(RING_TX_PENDING_BASE, 0x44000800);
+	ixp2000_reg_write(RING_TX_PENDING_HEAD, 0x00000000);
+	ixp2000_reg_write(RING_TX_PENDING_TAIL, 0x00000000);
+
+	/* 256 entries, ring status set means 'full', base address 0x0c00.  */
+	ixp2000_reg_write(RING_TX_DONE_BASE, 0x40000c00);
+	ixp2000_reg_write(RING_TX_DONE_HEAD, 0x00000000);
+	ixp2000_reg_write(RING_TX_DONE_TAIL, 0x00000000);
+
+	ixp2000_uengine_load(1, &ixp2400_tx);
+	ixp2000_uengine_start_contexts(1, 0xff);
+
+	for (i = 0; i < nds_count; i++) {
+		err = register_netdev(nds[i]);
+		if (err) {
+			while (--i >= 0)
+				unregister_netdev(nds[i]);
+			goto err_free_tx;
+		}
+	}
+
+	for (i = 0; i < nds_count; i++) {
+		printk(KERN_INFO "%s: IXP2000 MSF ethernet (port %d), "
+			"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x.\n", nds[i]->name, i,
+			nds[i]->dev_addr[0], nds[i]->dev_addr[1],
+			nds[i]->dev_addr[2], nds[i]->dev_addr[3],
+			nds[i]->dev_addr[4], nds[i]->dev_addr[5]);
+	}
+
+	return 0;
+
+err_free_tx:
+	for (i = 0; i < TX_BUF_COUNT; i++)
+		free_page((unsigned long)phys_to_virt(tx_desc[i].buf_addr));
+
+err_free_rx:
+	for (i = 0; i < RX_BUF_COUNT; i++)
+		free_page((unsigned long)phys_to_virt(rx_desc[i].buf_addr));
+
+err_out:
+	return err;
+} 
+
+void ixpdev_deinit(void)
+{
+	int i;
+
+	/* @@@ Flush out pending packets.  */
+
+	for (i = 0; i < nds_count; i++)
+		unregister_netdev(nds[i]);
+
+	ixp2000_uengine_stop_contexts(1, 0xff);
+	ixp2000_uengine_stop_contexts(0, 0xff);
+	ixp2000_uengine_reset(0x3);
+
+	for (i = 0; i < TX_BUF_COUNT; i++)
+		free_page((unsigned long)phys_to_virt(tx_desc[i].buf_addr));
+
+	for (i = 0; i < RX_BUF_COUNT; i++)
+		free_page((unsigned long)phys_to_virt(rx_desc[i].buf_addr));
+}
diff --git a/drivers/net/ixp2000/ixpdev.h b/drivers/net/ixp2000/ixpdev.h
new file mode 100644
index 000000000000..bd686cb63058
--- /dev/null
+++ b/drivers/net/ixp2000/ixpdev.h
@@ -0,0 +1,27 @@
+/*
+ * IXP2000 MSF network device driver
+ * Copyright (C) 2004, 2005 Lennert Buytenhek <buytenh@wantstofly.org>
+ * Dedicated to Marija Kulikova.
+ *
+ * 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 __IXPDEV_H
+#define __IXPDEV_H
+
+struct ixpdev_priv
+{
+	int	channel;
+	int	tx_queue_entries;
+};
+
+struct net_device *ixpdev_alloc(int channel, int sizeof_priv);
+int ixpdev_init(int num_ports, struct net_device **nds,
+		void (*set_port_admin_status)(int port, int up));
+void ixpdev_deinit(void);
+
+
+#endif
diff --git a/drivers/net/ixp2000/ixpdev_priv.h b/drivers/net/ixp2000/ixpdev_priv.h
new file mode 100644
index 000000000000..86aa08ea0c33
--- /dev/null
+++ b/drivers/net/ixp2000/ixpdev_priv.h
@@ -0,0 +1,57 @@
+/*
+ * IXP2000 MSF network device driver
+ * Copyright (C) 2004, 2005 Lennert Buytenhek <buytenh@wantstofly.org>
+ * Dedicated to Marija Kulikova.
+ *
+ * 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 __IXPDEV_PRIV_H
+#define __IXPDEV_PRIV_H
+
+#define RX_BUF_DESC_BASE	0x00001000
+#define RX_BUF_COUNT		((3 * PAGE_SIZE) / (4 * sizeof(struct ixpdev_rx_desc)))
+#define TX_BUF_DESC_BASE	0x00002000
+#define TX_BUF_COUNT		((3 * PAGE_SIZE) / (4 * sizeof(struct ixpdev_tx_desc)))
+#define TX_BUF_COUNT_PER_CHAN	(TX_BUF_COUNT / 4)
+
+#define RING_RX_PENDING		((u32 *)IXP2000_SCRATCH_RING_VIRT_BASE)
+#define RING_RX_DONE		((u32 *)(IXP2000_SCRATCH_RING_VIRT_BASE + 4))
+#define RING_TX_PENDING		((u32 *)(IXP2000_SCRATCH_RING_VIRT_BASE + 8))
+#define RING_TX_DONE		((u32 *)(IXP2000_SCRATCH_RING_VIRT_BASE + 12))
+
+#define SCRATCH_REG(x)		((u32 *)(IXP2000_GLOBAL_REG_VIRT_BASE | 0x0800 | (x)))
+#define RING_RX_PENDING_BASE	SCRATCH_REG(0x00)
+#define RING_RX_PENDING_HEAD	SCRATCH_REG(0x04)
+#define RING_RX_PENDING_TAIL	SCRATCH_REG(0x08)
+#define RING_RX_DONE_BASE	SCRATCH_REG(0x10)
+#define RING_RX_DONE_HEAD	SCRATCH_REG(0x14)
+#define RING_RX_DONE_TAIL	SCRATCH_REG(0x18)
+#define RING_TX_PENDING_BASE	SCRATCH_REG(0x20)
+#define RING_TX_PENDING_HEAD	SCRATCH_REG(0x24)
+#define RING_TX_PENDING_TAIL	SCRATCH_REG(0x28)
+#define RING_TX_DONE_BASE	SCRATCH_REG(0x30)
+#define RING_TX_DONE_HEAD	SCRATCH_REG(0x34)
+#define RING_TX_DONE_TAIL	SCRATCH_REG(0x38)
+
+struct ixpdev_rx_desc
+{
+	u32	buf_addr;
+	u32	buf_length;
+	u32	channel;
+	u32	pkt_length;
+};
+
+struct ixpdev_tx_desc
+{
+	u32	buf_addr;
+	u32	pkt_length;
+	u32	channel;
+	u32	unused;
+};
+
+
+#endif
diff --git a/drivers/net/ixp2000/pm3386.c b/drivers/net/ixp2000/pm3386.c
new file mode 100644
index 000000000000..5c7ab7564053
--- /dev/null
+++ b/drivers/net/ixp2000/pm3386.c
@@ -0,0 +1,334 @@
+/*
+ * Helper functions for the PM3386s on the Radisys ENP2611
+ * Copyright (C) 2004, 2005 Lennert Buytenhek <buytenh@wantstofly.org>
+ * Dedicated to Marija Kulikova.
+ *
+ * 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/config.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <asm/io.h>
+#include "pm3386.h"
+
+/*
+ * Read from register 'reg' of PM3386 device 'pm'.
+ */
+static u16 pm3386_reg_read(int pm, int reg)
+{
+	void *_reg;
+	u16 value;
+
+	_reg = (void *)ENP2611_PM3386_0_VIRT_BASE;
+	if (pm == 1)
+		_reg = (void *)ENP2611_PM3386_1_VIRT_BASE;
+
+	value = *((volatile u16 *)(_reg + (reg << 1)));
+
+//	printk(KERN_INFO "pm3386_reg_read(%d, %.3x) = %.8x\n", pm, reg, value);
+
+	return value;
+}
+
+/*
+ * Write to register 'reg' of PM3386 device 'pm', and perform
+ * a readback from the identification register.
+ */
+static void pm3386_reg_write(int pm, int reg, u16 value)
+{
+	void *_reg;
+	u16 dummy;
+
+//	printk(KERN_INFO "pm3386_reg_write(%d, %.3x, %.8x)\n", pm, reg, value);
+
+	_reg = (void *)ENP2611_PM3386_0_VIRT_BASE;
+	if (pm == 1)
+		_reg = (void *)ENP2611_PM3386_1_VIRT_BASE;
+
+	*((volatile u16 *)(_reg + (reg << 1))) = value;
+
+	dummy = *((volatile u16 *)_reg);
+	__asm__ __volatile__("mov %0, %0" : "+r" (dummy));
+}
+
+/*
+ * Read from port 'port' register 'reg', where the registers
+ * for the different ports are 'spacing' registers apart.
+ */
+static u16 pm3386_port_reg_read(int port, int _reg, int spacing)
+{
+	int reg;
+
+	reg = _reg;
+	if (port & 1)
+		reg += spacing;
+
+	return pm3386_reg_read(port >> 1, reg);
+}
+
+/*
+ * Write to port 'port' register 'reg', where the registers
+ * for the different ports are 'spacing' registers apart.
+ */
+static void pm3386_port_reg_write(int port, int _reg, int spacing, u16 value)
+{
+	int reg;
+
+	reg = _reg;
+	if (port & 1)
+		reg += spacing;
+
+	pm3386_reg_write(port >> 1, reg, value);
+}
+
+
+void pm3386_reset(void)
+{
+	u8 mac[3][6];
+
+	/* Save programmed MAC addresses.  */
+	pm3386_get_mac(0, mac[0]);
+	pm3386_get_mac(1, mac[1]);
+	pm3386_get_mac(2, mac[2]);
+
+	/* Assert analog and digital reset.  */
+	pm3386_reg_write(0, 0x002, 0x0060);
+	pm3386_reg_write(1, 0x002, 0x0060);
+	mdelay(1);
+
+	/* Deassert analog reset.  */
+	pm3386_reg_write(0, 0x002, 0x0062);
+	pm3386_reg_write(1, 0x002, 0x0062);
+	mdelay(10);
+
+	/* Deassert digital reset.  */
+	pm3386_reg_write(0, 0x002, 0x0063);
+	pm3386_reg_write(1, 0x002, 0x0063);
+	mdelay(10);
+
+	/* Restore programmed MAC addresses.  */
+	pm3386_set_mac(0, mac[0]);
+	pm3386_set_mac(1, mac[1]);
+	pm3386_set_mac(2, mac[2]);
+
+	/* Disable carrier on all ports.  */
+	pm3386_set_carrier(0, 0);
+	pm3386_set_carrier(1, 0);
+	pm3386_set_carrier(2, 0);
+}
+
+static u16 swaph(u16 x)
+{
+	return ((x << 8) | (x >> 8)) & 0xffff;
+}
+
+void pm3386_init_port(int port)
+{
+	int pm = port >> 1;
+
+	/*
+	 * Work around ENP2611 bootloader programming MAC address
+	 * in reverse.
+	 */
+	if (pm3386_port_reg_read(port, 0x30a, 0x100) == 0x0000 &&
+	    (pm3386_port_reg_read(port, 0x309, 0x100) & 0xff00) == 0x5000) {
+		u16 temp[3];
+
+		temp[0] = pm3386_port_reg_read(port, 0x308, 0x100);
+		temp[1] = pm3386_port_reg_read(port, 0x309, 0x100);
+		temp[2] = pm3386_port_reg_read(port, 0x30a, 0x100);
+		pm3386_port_reg_write(port, 0x308, 0x100, swaph(temp[2]));
+		pm3386_port_reg_write(port, 0x309, 0x100, swaph(temp[1]));
+		pm3386_port_reg_write(port, 0x30a, 0x100, swaph(temp[0]));
+	}
+
+	/*
+	 * Initialise narrowbanding mode.  See application note 2010486
+	 * for more information.  (@@@ We also need to issue a reset
+	 * when ROOL or DOOL are detected.)
+	 */
+	pm3386_port_reg_write(port, 0x708, 0x10, 0xd055);
+	udelay(500);
+	pm3386_port_reg_write(port, 0x708, 0x10, 0x5055);
+
+	/*
+	 * SPI-3 ingress block.  Set 64 bytes SPI-3 burst size
+	 * towards SPI-3 bridge.
+	 */
+	pm3386_port_reg_write(port, 0x122, 0x20, 0x0002);
+
+	/*
+	 * Enable ingress protocol checking, and soft reset the
+	 * SPI-3 ingress block.
+	 */
+	pm3386_reg_write(pm, 0x103, 0x0003);
+	while (!(pm3386_reg_read(pm, 0x103) & 0x80))
+		;
+
+	/*
+	 * SPI-3 egress block.  Gather 12288 bytes of the current
+	 * packet in the TX fifo before initiating transmit on the
+	 * SERDES interface.  (Prevents TX underflows.)
+	 */
+	pm3386_port_reg_write(port, 0x221, 0x20, 0x0007);
+
+	/*
+	 * Enforce odd parity from the SPI-3 bridge, and soft reset
+	 * the SPI-3 egress block.
+	 */
+	pm3386_reg_write(pm, 0x203, 0x000d & ~(4 << (port & 1)));
+	while ((pm3386_reg_read(pm, 0x203) & 0x000c) != 0x000c)
+		;
+
+	/*
+	 * EGMAC block.  Set this channels to reject long preambles,
+	 * not send or transmit PAUSE frames, enable preamble checking,
+	 * disable frame length checking, enable FCS appending, enable
+	 * TX frame padding.
+	 */
+	pm3386_port_reg_write(port, 0x302, 0x100, 0x0113);
+
+	/*
+	 * Soft reset the EGMAC block.
+	 */
+	pm3386_port_reg_write(port, 0x301, 0x100, 0x8000);
+	pm3386_port_reg_write(port, 0x301, 0x100, 0x0000);
+
+	/*
+	 * Auto-sense autonegotiation status.
+	 */
+	pm3386_port_reg_write(port, 0x306, 0x100, 0x0100);
+
+	/*
+	 * Allow reception of jumbo frames.
+	 */
+	pm3386_port_reg_write(port, 0x310, 0x100, 9018);
+
+	/*
+	 * Allow transmission of jumbo frames.
+	 */
+	pm3386_port_reg_write(port, 0x336, 0x100, 9018);
+
+	/* @@@ Should set 0x337/0x437 (RX forwarding threshold.)  */
+
+	/*
+	 * Set autonegotiation parameters to 'no PAUSE, full duplex.'
+	 */
+	pm3386_port_reg_write(port, 0x31c, 0x100, 0x0020);
+
+	/*
+	 * Enable and restart autonegotiation.
+	 */
+	pm3386_port_reg_write(port, 0x318, 0x100, 0x0003);
+	pm3386_port_reg_write(port, 0x318, 0x100, 0x0002);
+}
+
+void pm3386_get_mac(int port, u8 *mac)
+{
+	u16 temp;
+
+	temp = pm3386_port_reg_read(port, 0x308, 0x100);
+	mac[0] = temp & 0xff;
+	mac[1] = (temp >> 8) & 0xff;
+
+	temp = pm3386_port_reg_read(port, 0x309, 0x100);
+	mac[2] = temp & 0xff;
+	mac[3] = (temp >> 8) & 0xff;
+
+	temp = pm3386_port_reg_read(port, 0x30a, 0x100);
+	mac[4] = temp & 0xff;
+	mac[5] = (temp >> 8) & 0xff;
+}
+
+void pm3386_set_mac(int port, u8 *mac)
+{
+	pm3386_port_reg_write(port, 0x308, 0x100, (mac[1] << 8) | mac[0]);
+	pm3386_port_reg_write(port, 0x309, 0x100, (mac[3] << 8) | mac[2]);
+	pm3386_port_reg_write(port, 0x30a, 0x100, (mac[5] << 8) | mac[4]);
+}
+
+static u32 pm3386_get_stat(int port, u16 base)
+{
+	u32 value;
+
+	value = pm3386_port_reg_read(port, base, 0x100);
+	value |= pm3386_port_reg_read(port, base + 1, 0x100) << 16;
+
+	return value;
+}
+
+void pm3386_get_stats(int port, struct net_device_stats *stats)
+{
+	/*
+	 * Snapshot statistics counters.
+	 */
+	pm3386_port_reg_write(port, 0x500, 0x100, 0x0001);
+	while (pm3386_port_reg_read(port, 0x500, 0x100) & 0x0001)
+		;
+
+	memset(stats, 0, sizeof(*stats));
+
+	stats->rx_packets = pm3386_get_stat(port, 0x510);
+	stats->tx_packets = pm3386_get_stat(port, 0x590);
+	stats->rx_bytes = pm3386_get_stat(port, 0x514);
+	stats->tx_bytes = pm3386_get_stat(port, 0x594);
+	/* @@@ Add other stats.  */
+}
+
+void pm3386_set_carrier(int port, int state)
+{
+	pm3386_port_reg_write(port, 0x703, 0x10, state ? 0x1001 : 0x0000);
+}
+
+int pm3386_is_link_up(int port)
+{
+	u16 temp;
+
+	temp = pm3386_port_reg_read(port, 0x31a, 0x100);
+	temp = pm3386_port_reg_read(port, 0x31a, 0x100);
+
+	return !!(temp & 0x0002);
+}
+
+void pm3386_enable_rx(int port)
+{
+	u16 temp;
+
+	temp = pm3386_port_reg_read(port, 0x303, 0x100);
+	temp |= 0x1000;
+	pm3386_port_reg_write(port, 0x303, 0x100, temp);
+}
+
+void pm3386_disable_rx(int port)
+{
+	u16 temp;
+
+	temp = pm3386_port_reg_read(port, 0x303, 0x100);
+	temp &= 0xefff;
+	pm3386_port_reg_write(port, 0x303, 0x100, temp);
+}
+
+void pm3386_enable_tx(int port)
+{
+	u16 temp;
+
+	temp = pm3386_port_reg_read(port, 0x303, 0x100);
+	temp |= 0x4000;
+	pm3386_port_reg_write(port, 0x303, 0x100, temp);
+}
+
+void pm3386_disable_tx(int port)
+{
+	u16 temp;
+
+	temp = pm3386_port_reg_read(port, 0x303, 0x100);
+	temp &= 0xbfff;
+	pm3386_port_reg_write(port, 0x303, 0x100, temp);
+}
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/ixp2000/pm3386.h b/drivers/net/ixp2000/pm3386.h
new file mode 100644
index 000000000000..fe92bb056ac4
--- /dev/null
+++ b/drivers/net/ixp2000/pm3386.h
@@ -0,0 +1,28 @@
+/*
+ * Helper functions for the PM3386s on the Radisys ENP2611
+ * Copyright (C) 2004, 2005 Lennert Buytenhek <buytenh@wantstofly.org>
+ * Dedicated to Marija Kulikova.
+ *
+ * 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 __PM3386_H
+#define __PM3386_H
+
+void pm3386_reset(void);
+void pm3386_init_port(int port);
+void pm3386_get_mac(int port, u8 *mac);
+void pm3386_set_mac(int port, u8 *mac);
+void pm3386_get_stats(int port, struct net_device_stats *stats);
+void pm3386_set_carrier(int port, int state);
+int pm3386_is_link_up(int port);
+void pm3386_enable_rx(int port);
+void pm3386_disable_rx(int port);
+void pm3386_enable_tx(int port);
+void pm3386_disable_tx(int port);
+
+
+#endif
diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c
index f857ae94d261..b0c3b6ab6263 100644
--- a/drivers/net/ns83820.c
+++ b/drivers/net/ns83820.c
@@ -115,6 +115,7 @@
 #include <linux/ethtool.h>
 #include <linux/timer.h>
 #include <linux/if_vlan.h>
+#include <linux/rtnetlink.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c
index 71fd41122c91..48774efeec71 100644
--- a/drivers/net/pcmcia/3c574_cs.c
+++ b/drivers/net/pcmcia/3c574_cs.c
@@ -227,8 +227,6 @@ static char mii_preamble_required = 0;
 
 static void tc574_config(dev_link_t *link);
 static void tc574_release(dev_link_t *link);
-static int tc574_event(event_t event, int priority,
-					   event_callback_args_t *args);
 
 static void mdio_sync(kio_addr_t ioaddr, int bits);
 static int mdio_read(kio_addr_t ioaddr, int phy_id, int location);
@@ -250,12 +248,7 @@ static int el3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static struct ethtool_ops netdev_ethtool_ops;
 static void set_rx_mode(struct net_device *dev);
 
-static dev_info_t dev_info = "3c574_cs";
-
-static dev_link_t *tc574_attach(void);
-static void tc574_detach(dev_link_t *);
-
-static dev_link_t *dev_list;
+static void tc574_detach(struct pcmcia_device *p_dev);
 
 /*
 	tc574_attach() creates an "instance" of the driver, allocating
@@ -263,20 +256,18 @@ static dev_link_t *dev_list;
 	with Card Services.
 */
 
-static dev_link_t *tc574_attach(void)
+static int tc574_attach(struct pcmcia_device *p_dev)
 {
 	struct el3_private *lp;
-	client_reg_t client_reg;
 	dev_link_t *link;
 	struct net_device *dev;
-	int ret;
 
 	DEBUG(0, "3c574_attach()\n");
 
 	/* Create the PC card device object. */
 	dev = alloc_etherdev(sizeof(struct el3_private));
 	if (!dev)
-		return NULL;
+		return -ENOMEM;
 	lp = netdev_priv(dev);
 	link = &lp->link;
 	link->priv = dev;
@@ -307,20 +298,13 @@ static dev_link_t *tc574_attach(void)
 	dev->watchdog_timeo = TX_TIMEOUT;
 #endif
 
-	/* Register with Card Services */
-	link->next = dev_list;
-	dev_list = link;
-	client_reg.dev_info = &dev_info;
-	client_reg.Version = 0x0210;
-	client_reg.event_callback_args.client_data = link;
-	ret = pcmcia_register_client(&link->handle, &client_reg);
-	if (ret != 0) {
-		cs_error(link->handle, RegisterClient, ret);
-		tc574_detach(link);
-		return NULL;
-	}
+	link->handle = p_dev;
+	p_dev->instance = link;
 
-	return link;
+	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+	tc574_config(link);
+
+	return 0;
 } /* tc574_attach */
 
 /*
@@ -332,30 +316,19 @@ static dev_link_t *tc574_attach(void)
 
 */
 
-static void tc574_detach(dev_link_t *link)
+static void tc574_detach(struct pcmcia_device *p_dev)
 {
+	dev_link_t *link = dev_to_instance(p_dev);
 	struct net_device *dev = link->priv;
-	dev_link_t **linkp;
 
 	DEBUG(0, "3c574_detach(0x%p)\n", link);
 
-	/* Locate device structure */
-	for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
-		if (*linkp == link) break;
-	if (*linkp == NULL)
-		return;
-
 	if (link->dev)
 		unregister_netdev(dev);
 
 	if (link->state & DEV_CONFIG)
 		tc574_release(link);
 
-	if (link->handle)
-		pcmcia_deregister_client(link->handle);
-
-	/* Unlink device structure, free bits */
-	*linkp = link->next;
 	free_netdev(dev);
 } /* tc574_detach */
 
@@ -547,56 +520,37 @@ static void tc574_release(dev_link_t *link)
 	link->state &= ~DEV_CONFIG;
 }
 
-/*
-	The card status event handler.  Mostly, this schedules other
-	stuff to run after an event is received.  A CARD_REMOVAL event
-	also sets some flags to discourage the net drivers from trying
-	to talk to the card any more.
-*/
-
-static int tc574_event(event_t event, int priority,
-					   event_callback_args_t *args)
+static int tc574_suspend(struct pcmcia_device *p_dev)
 {
-	dev_link_t *link = args->client_data;
+	dev_link_t *link = dev_to_instance(p_dev);
 	struct net_device *dev = link->priv;
 
-	DEBUG(1, "3c574_event(0x%06x)\n", event);
-
-	switch (event) {
-	case CS_EVENT_CARD_REMOVAL:
-		link->state &= ~DEV_PRESENT;
-		if (link->state & DEV_CONFIG)
+	link->state |= DEV_SUSPEND;
+	if (link->state & DEV_CONFIG) {
+		if (link->open)
 			netif_device_detach(dev);
-		break;
-	case CS_EVENT_CARD_INSERTION:
-		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-		tc574_config(link);
-		break;
-	case CS_EVENT_PM_SUSPEND:
-		link->state |= DEV_SUSPEND;
-		/* Fall through... */
-	case CS_EVENT_RESET_PHYSICAL:
-		if (link->state & DEV_CONFIG) {
-			if (link->open)
-				netif_device_detach(dev);
-			pcmcia_release_configuration(link->handle);
-		}
-		break;
-	case CS_EVENT_PM_RESUME:
-		link->state &= ~DEV_SUSPEND;
-		/* Fall through... */
-	case CS_EVENT_CARD_RESET:
-		if (link->state & DEV_CONFIG) {
-			pcmcia_request_configuration(link->handle, &link->conf);
-			if (link->open) {
-				tc574_reset(dev);
-				netif_device_attach(dev);
-			}
+		pcmcia_release_configuration(link->handle);
+	}
+
+	return 0;
+}
+
+static int tc574_resume(struct pcmcia_device *p_dev)
+{
+	dev_link_t *link = dev_to_instance(p_dev);
+	struct net_device *dev = link->priv;
+
+	link->state &= ~DEV_SUSPEND;
+	if (link->state & DEV_CONFIG) {
+		pcmcia_request_configuration(link->handle, &link->conf);
+		if (link->open) {
+			tc574_reset(dev);
+			netif_device_attach(dev);
 		}
-		break;
 	}
+
 	return 0;
-} /* tc574_event */
+}
 
 static void dump_status(struct net_device *dev)
 {
@@ -1292,10 +1246,11 @@ static struct pcmcia_driver tc574_driver = {
 	.drv		= {
 		.name	= "3c574_cs",
 	},
-	.attach		= tc574_attach,
-	.event		= tc574_event,
-	.detach		= tc574_detach,
+	.probe		= tc574_attach,
+	.remove		= tc574_detach,
 	.id_table       = tc574_ids,
+	.suspend	= tc574_suspend,
+	.resume		= tc574_resume,
 };
 
 static int __init init_tc574(void)
@@ -1306,7 +1261,6 @@ static int __init init_tc574(void)
 static void __exit exit_tc574(void)
 {
 	pcmcia_unregister_driver(&tc574_driver);
-	BUG_ON(dev_list != NULL);
 }
 
 module_init(init_tc574);
diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c
index d83fdd8c1943..1c3c9c666f74 100644
--- a/drivers/net/pcmcia/3c589_cs.c
+++ b/drivers/net/pcmcia/3c589_cs.c
@@ -143,8 +143,6 @@ DRV_NAME ".c " DRV_VERSION " 2001/10/13 00:08:50 (David Hinds)";
 
 static void tc589_config(dev_link_t *link);
 static void tc589_release(dev_link_t *link);
-static int tc589_event(event_t event, int priority,
-		       event_callback_args_t *args);
 
 static u16 read_eeprom(kio_addr_t ioaddr, int index);
 static void tc589_reset(struct net_device *dev);
@@ -161,12 +159,7 @@ static void el3_tx_timeout(struct net_device *dev);
 static void set_multicast_list(struct net_device *dev);
 static struct ethtool_ops netdev_ethtool_ops;
 
-static dev_info_t dev_info = "3c589_cs";
-
-static dev_link_t *tc589_attach(void);
-static void tc589_detach(dev_link_t *);
-
-static dev_link_t *dev_list;
+static void tc589_detach(struct pcmcia_device *p_dev);
 
 /*======================================================================
 
@@ -176,20 +169,18 @@ static dev_link_t *dev_list;
 
 ======================================================================*/
 
-static dev_link_t *tc589_attach(void)
+static int tc589_attach(struct pcmcia_device *p_dev)
 {
     struct el3_private *lp;
-    client_reg_t client_reg;
     dev_link_t *link;
     struct net_device *dev;
-    int ret;
 
     DEBUG(0, "3c589_attach()\n");
-    
+
     /* Create new ethernet device */
     dev = alloc_etherdev(sizeof(struct el3_private));
     if (!dev)
-	 return NULL;
+	 return -ENOMEM;
     lp = netdev_priv(dev);
     link = &lp->link;
     link->priv = dev;
@@ -206,7 +197,7 @@ static dev_link_t *tc589_attach(void)
     link->conf.IntType = INT_MEMORY_AND_IO;
     link->conf.ConfigIndex = 1;
     link->conf.Present = PRESENT_OPTION;
-    
+
     /* The EL3-specific entries in the device structure. */
     SET_MODULE_OWNER(dev);
     dev->hard_start_xmit = &el3_start_xmit;
@@ -221,20 +212,13 @@ static dev_link_t *tc589_attach(void)
 #endif
     SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
 
-    /* Register with Card Services */
-    link->next = dev_list;
-    dev_list = link;
-    client_reg.dev_info = &dev_info;
-    client_reg.Version = 0x0210;
-    client_reg.event_callback_args.client_data = link;
-    ret = pcmcia_register_client(&link->handle, &client_reg);
-    if (ret != 0) {
-	cs_error(link->handle, RegisterClient, ret);
-	tc589_detach(link);
-	return NULL;
-    }
-    
-    return link;
+    link->handle = p_dev;
+    p_dev->instance = link;
+
+    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+    tc589_config(link);
+
+    return 0;
 } /* tc589_attach */
 
 /*======================================================================
@@ -246,30 +230,19 @@ static dev_link_t *tc589_attach(void)
 
 ======================================================================*/
 
-static void tc589_detach(dev_link_t *link)
+static void tc589_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     struct net_device *dev = link->priv;
-    dev_link_t **linkp;
-    
+
     DEBUG(0, "3c589_detach(0x%p)\n", link);
-    
-    /* Locate device structure */
-    for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
-	if (*linkp == link) break;
-    if (*linkp == NULL)
-	return;
 
     if (link->dev)
 	unregister_netdev(dev);
 
     if (link->state & DEV_CONFIG)
 	tc589_release(link);
-    
-    if (link->handle)
-	pcmcia_deregister_client(link->handle);
-    
-    /* Unlink device structure, free bits */
-    *linkp = link->next;
+
     free_netdev(dev);
 } /* tc589_detach */
 
@@ -421,58 +394,37 @@ static void tc589_release(dev_link_t *link)
     link->state &= ~DEV_CONFIG;
 }
 
-/*======================================================================
-
-    The card status event handler.  Mostly, this schedules other
-    stuff to run after an event is received.  A CARD_REMOVAL event
-    also sets some flags to discourage the net drivers from trying
-    to talk to the card any more.
-    
-======================================================================*/
-
-static int tc589_event(event_t event, int priority,
-		       event_callback_args_t *args)
+static int tc589_suspend(struct pcmcia_device *p_dev)
 {
-    dev_link_t *link = args->client_data;
-    struct net_device *dev = link->priv;
-    
-    DEBUG(1, "3c589_event(0x%06x)\n", event);
-    
-    switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-	link->state &= ~DEV_PRESENT;
-	if (link->state & DEV_CONFIG)
-	    netif_device_detach(dev);
-	break;
-    case CS_EVENT_CARD_INSERTION:
-	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-	tc589_config(link);
-	break;
-    case CS_EVENT_PM_SUSPEND:
+	dev_link_t *link = dev_to_instance(p_dev);
+	struct net_device *dev = link->priv;
+
 	link->state |= DEV_SUSPEND;
-	/* Fall through... */
-    case CS_EVENT_RESET_PHYSICAL:
 	if (link->state & DEV_CONFIG) {
-	    if (link->open)
-		netif_device_detach(dev);
-	    pcmcia_release_configuration(link->handle);
+		if (link->open)
+			netif_device_detach(dev);
+		pcmcia_release_configuration(link->handle);
 	}
-	break;
-    case CS_EVENT_PM_RESUME:
+
+	return 0;
+}
+
+static int tc589_resume(struct pcmcia_device *p_dev)
+{
+	dev_link_t *link = dev_to_instance(p_dev);
+	struct net_device *dev = link->priv;
+
 	link->state &= ~DEV_SUSPEND;
-	/* Fall through... */
-    case CS_EVENT_CARD_RESET:
 	if (link->state & DEV_CONFIG) {
-	    pcmcia_request_configuration(link->handle, &link->conf);
-	    if (link->open) {
-		tc589_reset(dev);
-		netif_device_attach(dev);
-	    }
+		pcmcia_request_configuration(link->handle, &link->conf);
+		if (link->open) {
+			tc589_reset(dev);
+			netif_device_attach(dev);
+		}
 	}
-	break;
-    }
-    return 0;
-} /* tc589_event */
+
+	return 0;
+}
 
 /*====================================================================*/
 
@@ -1067,10 +1019,11 @@ static struct pcmcia_driver tc589_driver = {
 	.drv		= {
 		.name	= "3c589_cs",
 	},
-	.attach		= tc589_attach,
-	.event		= tc589_event,
-	.detach		= tc589_detach,
+	.probe		= tc589_attach,
+	.remove		= tc589_detach,
         .id_table       = tc589_ids,
+	.suspend	= tc589_suspend,
+	.resume		= tc589_resume,
 };
 
 static int __init init_tc589(void)
@@ -1081,7 +1034,6 @@ static int __init init_tc589(void)
 static void __exit exit_tc589(void)
 {
 	pcmcia_unregister_driver(&tc589_driver);
-	BUG_ON(dev_list != NULL);
 }
 
 module_init(init_tc589);
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c
index 8bb4e85689ea..01ddfc8cce3f 100644
--- a/drivers/net/pcmcia/axnet_cs.c
+++ b/drivers/net/pcmcia/axnet_cs.c
@@ -87,8 +87,6 @@ static char *version =
 
 static void axnet_config(dev_link_t *link);
 static void axnet_release(dev_link_t *link);
-static int axnet_event(event_t event, int priority,
-		       event_callback_args_t *args);
 static int axnet_open(struct net_device *dev);
 static int axnet_close(struct net_device *dev);
 static int axnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
@@ -107,11 +105,7 @@ static void block_input(struct net_device *dev, int count,
 static void block_output(struct net_device *dev, int count,
 			 const u_char *buf, const int start_page);
 
-static dev_link_t *axnet_attach(void);
-static void axnet_detach(dev_link_t *);
-
-static dev_info_t dev_info = "axnet_cs";
-static dev_link_t *dev_list;
+static void axnet_detach(struct pcmcia_device *p_dev);
 
 static void axdev_setup(struct net_device *dev);
 static void AX88190_init(struct net_device *dev, int startp);
@@ -147,13 +141,11 @@ static inline axnet_dev_t *PRIV(struct net_device *dev)
 
 ======================================================================*/
 
-static dev_link_t *axnet_attach(void)
+static int axnet_attach(struct pcmcia_device *p_dev)
 {
     axnet_dev_t *info;
     dev_link_t *link;
     struct net_device *dev;
-    client_reg_t client_reg;
-    int ret;
 
     DEBUG(0, "axnet_attach()\n");
 
@@ -161,7 +153,7 @@ static dev_link_t *axnet_attach(void)
 			"eth%d", axdev_setup);
 
     if (!dev)
-	return NULL;
+	return -ENOMEM;
 
     info = PRIV(dev);
     link = &info->link;
@@ -176,20 +168,13 @@ static dev_link_t *axnet_attach(void)
     dev->do_ioctl = &axnet_ioctl;
     SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
 
-    /* Register with Card Services */
-    link->next = dev_list;
-    dev_list = link;
-    client_reg.dev_info = &dev_info;
-    client_reg.Version = 0x0210;
-    client_reg.event_callback_args.client_data = link;
-    ret = pcmcia_register_client(&link->handle, &client_reg);
-    if (ret != CS_SUCCESS) {
-	cs_error(link->handle, RegisterClient, ret);
-	axnet_detach(link);
-	return NULL;
-    }
+    link->handle = p_dev;
+    p_dev->instance = link;
 
-    return link;
+    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+    axnet_config(link);
+
+    return 0;
 } /* axnet_attach */
 
 /*======================================================================
@@ -201,30 +186,19 @@ static dev_link_t *axnet_attach(void)
 
 ======================================================================*/
 
-static void axnet_detach(dev_link_t *link)
+static void axnet_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     struct net_device *dev = link->priv;
-    dev_link_t **linkp;
 
     DEBUG(0, "axnet_detach(0x%p)\n", link);
 
-    /* Locate device structure */
-    for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
-	if (*linkp == link) break;
-    if (*linkp == NULL)
-	return;
-
     if (link->dev)
 	unregister_netdev(dev);
 
     if (link->state & DEV_CONFIG)
 	axnet_release(link);
 
-    if (link->handle)
-	pcmcia_deregister_client(link->handle);
-
-    /* Unlink device structure, free bits */
-    *linkp = link->next;
     free_netdev(dev);
 } /* axnet_detach */
 
@@ -490,59 +464,39 @@ static void axnet_release(dev_link_t *link)
     link->state &= ~DEV_CONFIG;
 }
 
-/*======================================================================
-
-    The card status event handler.  Mostly, this schedules other
-    stuff to run after an event is received.  A CARD_REMOVAL event
-    also sets some flags to discourage the net drivers from trying
-    to talk to the card any more.
-
-======================================================================*/
-
-static int axnet_event(event_t event, int priority,
-		       event_callback_args_t *args)
+static int axnet_suspend(struct pcmcia_device *p_dev)
 {
-    dev_link_t *link = args->client_data;
-    struct net_device *dev = link->priv;
+	dev_link_t *link = dev_to_instance(p_dev);
+	struct net_device *dev = link->priv;
 
-    DEBUG(2, "axnet_event(0x%06x)\n", event);
-
-    switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-	link->state &= ~DEV_PRESENT;
-	if (link->state & DEV_CONFIG)
-	    netif_device_detach(dev);
-	break;
-    case CS_EVENT_CARD_INSERTION:
-	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-	axnet_config(link);
-	break;
-    case CS_EVENT_PM_SUSPEND:
 	link->state |= DEV_SUSPEND;
-	/* Fall through... */
-    case CS_EVENT_RESET_PHYSICAL:
 	if (link->state & DEV_CONFIG) {
-	    if (link->open)
-		netif_device_detach(dev);
-	    pcmcia_release_configuration(link->handle);
+		if (link->open)
+			netif_device_detach(dev);
+		pcmcia_release_configuration(link->handle);
 	}
-	break;
-    case CS_EVENT_PM_RESUME:
+
+	return 0;
+}
+
+static int axnet_resume(struct pcmcia_device *p_dev)
+{
+	dev_link_t *link = dev_to_instance(p_dev);
+	struct net_device *dev = link->priv;
+
 	link->state &= ~DEV_SUSPEND;
-	/* Fall through... */
-    case CS_EVENT_CARD_RESET:
 	if (link->state & DEV_CONFIG) {
-	    pcmcia_request_configuration(link->handle, &link->conf);
-	    if (link->open) {
-		axnet_reset_8390(dev);
-		AX88190_init(dev, 1);
-		netif_device_attach(dev);
-	    }
+		pcmcia_request_configuration(link->handle, &link->conf);
+		if (link->open) {
+			axnet_reset_8390(dev);
+			AX88190_init(dev, 1);
+			netif_device_attach(dev);
+		}
 	}
-	break;
-    }
-    return 0;
-} /* axnet_event */
+
+	return 0;
+}
+
 
 /*======================================================================
 
@@ -616,7 +570,7 @@ static int axnet_open(struct net_device *dev)
 
     link->open++;
 
-    request_irq(dev->irq, ei_irq_wrapper, SA_SHIRQ, dev_info, dev);
+    request_irq(dev->irq, ei_irq_wrapper, SA_SHIRQ, "axnet_cs", dev);
 
     info->link_status = 0x00;
     init_timer(&info->watchdog);
@@ -877,10 +831,11 @@ static struct pcmcia_driver axnet_cs_driver = {
 	.drv		= {
 		.name	= "axnet_cs",
 	},
-	.attach		= axnet_attach,
-	.event		= axnet_event,
-	.detach		= axnet_detach,
+	.probe		= axnet_attach,
+	.remove		= axnet_detach,
 	.id_table       = axnet_ids,
+	.suspend	= axnet_suspend,
+	.resume		= axnet_resume,
 };
 
 static int __init init_axnet_cs(void)
@@ -891,7 +846,6 @@ static int __init init_axnet_cs(void)
 static void __exit exit_axnet_cs(void)
 {
 	pcmcia_unregister_driver(&axnet_cs_driver);
-	BUG_ON(dev_list != NULL);
 }
 
 module_init(init_axnet_cs);
diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c
index b9355d9498a3..2827a48ea37c 100644
--- a/drivers/net/pcmcia/com20020_cs.c
+++ b/drivers/net/pcmcia/com20020_cs.c
@@ -120,15 +120,8 @@ MODULE_LICENSE("GPL");
 
 static void com20020_config(dev_link_t *link);
 static void com20020_release(dev_link_t *link);
-static int com20020_event(event_t event, int priority,
-                       event_callback_args_t *args);
 
-static dev_info_t dev_info = "com20020_cs";
-
-static dev_link_t *com20020_attach(void);
-static void com20020_detach(dev_link_t *);
-
-static dev_link_t *dev_list;
+static void com20020_detach(struct pcmcia_device *p_dev);
 
 /*====================================================================*/
 
@@ -145,21 +138,19 @@ typedef struct com20020_dev_t {
 
 ======================================================================*/
 
-static dev_link_t *com20020_attach(void)
+static int com20020_attach(struct pcmcia_device *p_dev)
 {
-    client_reg_t client_reg;
     dev_link_t *link;
     com20020_dev_t *info;
     struct net_device *dev;
-    int ret;
     struct arcnet_local *lp;
-    
+
     DEBUG(0, "com20020_attach()\n");
 
     /* Create new network device */
     link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
     if (!link)
-	return NULL;
+	return -ENOMEM;
 
     info = kmalloc(sizeof(struct com20020_dev_t), GFP_KERNEL);
     if (!info)
@@ -191,30 +182,19 @@ static dev_link_t *com20020_attach(void)
     link->conf.IntType = INT_MEMORY_AND_IO;
     link->conf.Present = PRESENT_OPTION;
 
-
     link->irq.Instance = info->dev = dev;
     link->priv = info;
 
-    /* Register with Card Services */
-    link->next = dev_list;
-    dev_list = link;
-    client_reg.dev_info = &dev_info;
-    client_reg.Version = 0x0210;
-    client_reg.event_callback_args.client_data = link;
-    ret = pcmcia_register_client(&link->handle, &client_reg);
-    if (ret != 0) {
-        cs_error(link->handle, RegisterClient, ret);
-        com20020_detach(link);
-        return NULL;
-    }
+    link->state |= DEV_PRESENT;
+    com20020_config(link);
 
-    return link;
+    return 0;
 
 fail_alloc_dev:
     kfree(info);
 fail_alloc_info:
     kfree(link);
-    return NULL;
+    return -ENOMEM;
 } /* com20020_attach */
 
 /*======================================================================
@@ -226,29 +206,21 @@ fail_alloc_info:
 
 ======================================================================*/
 
-static void com20020_detach(dev_link_t *link)
+static void com20020_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     struct com20020_dev_t *info = link->priv;
-    dev_link_t **linkp;
-    struct net_device *dev; 
-    
+    struct net_device *dev = info->dev;
+
     DEBUG(1,"detach...\n");
 
     DEBUG(0, "com20020_detach(0x%p)\n", link);
 
-    /* Locate device structure */
-    for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
-        if (*linkp == link) break;
-    if (*linkp == NULL)
-        return;
-
-    dev = info->dev;
-
     if (link->dev) {
 	DEBUG(1,"unregister...\n");
 
 	unregister_netdev(dev);
-	    
+
 	/*
 	 * this is necessary because we register our IRQ separately
 	 * from card services.
@@ -260,12 +232,8 @@ static void com20020_detach(dev_link_t *link)
     if (link->state & DEV_CONFIG)
         com20020_release(link);
 
-    if (link->handle)
-        pcmcia_deregister_client(link->handle);
-
     /* Unlink device structure, free bits */
     DEBUG(1,"unlinking...\n");
-    *linkp = link->next;
     if (link->priv)
     {
 	dev = info->dev;
@@ -421,61 +389,41 @@ static void com20020_release(dev_link_t *link)
     link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING);
 }
 
-/*======================================================================
+static int com20020_suspend(struct pcmcia_device *p_dev)
+{
+	dev_link_t *link = dev_to_instance(p_dev);
+	com20020_dev_t *info = link->priv;
+	struct net_device *dev = info->dev;
 
-    The card status event handler.  Mostly, this schedules other
-    stuff to run after an event is received.  A CARD_REMOVAL event
-    also sets some flags to discourage the net drivers from trying
-    to talk to the card any more.
+	link->state |= DEV_SUSPEND;
+        if (link->state & DEV_CONFIG) {
+		if (link->open) {
+			netif_device_detach(dev);
+		}
+		pcmcia_release_configuration(link->handle);
+        }
 
-======================================================================*/
+	return 0;
+}
 
-static int com20020_event(event_t event, int priority,
-			  event_callback_args_t *args)
+static int com20020_resume(struct pcmcia_device *p_dev)
 {
-    dev_link_t *link = args->client_data;
-    com20020_dev_t *info = link->priv;
-    struct net_device *dev = info->dev;
+	dev_link_t *link = dev_to_instance(p_dev);
+	com20020_dev_t *info = link->priv;
+	struct net_device *dev = info->dev;
 
-    DEBUG(1, "com20020_event(0x%06x)\n", event);
-    
-    switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-        link->state &= ~DEV_PRESENT;
-        if (link->state & DEV_CONFIG)
-            netif_device_detach(dev);
-        break;
-    case CS_EVENT_CARD_INSERTION:
-        link->state |= DEV_PRESENT;
-	com20020_config(link); 
-	break;
-    case CS_EVENT_PM_SUSPEND:
-        link->state |= DEV_SUSPEND;
-        /* Fall through... */
-    case CS_EVENT_RESET_PHYSICAL:
-        if (link->state & DEV_CONFIG) {
-            if (link->open) {
-                netif_device_detach(dev);
-            }
-            pcmcia_release_configuration(link->handle);
-        }
-        break;
-    case CS_EVENT_PM_RESUME:
-        link->state &= ~DEV_SUSPEND;
-        /* Fall through... */
-    case CS_EVENT_CARD_RESET:
+	link->state &= ~DEV_SUSPEND;
         if (link->state & DEV_CONFIG) {
-            pcmcia_request_configuration(link->handle, &link->conf);
-            if (link->open) {
-		int ioaddr = dev->base_addr;
-		struct arcnet_local *lp = dev->priv;
-		ARCRESET;
-            }
+		pcmcia_request_configuration(link->handle, &link->conf);
+		if (link->open) {
+			int ioaddr = dev->base_addr;
+			struct arcnet_local *lp = dev->priv;
+			ARCRESET;
+		}
         }
-        break;
-    }
-    return 0;
-} /* com20020_event */
+
+	return 0;
+}
 
 static struct pcmcia_device_id com20020_ids[] = {
 	PCMCIA_DEVICE_PROD_ID12("Contemporary Control Systems, Inc.", "PCM20 Arcnet Adapter", 0x59991666, 0x95dfffaf),
@@ -488,10 +436,11 @@ static struct pcmcia_driver com20020_cs_driver = {
 	.drv		= {
 		.name	= "com20020_cs",
 	},
-	.attach		= com20020_attach,
-	.event		= com20020_event,
-	.detach		= com20020_detach,
+	.probe		= com20020_attach,
+	.remove		= com20020_detach,
 	.id_table	= com20020_ids,
+	.suspend	= com20020_suspend,
+	.resume		= com20020_resume,
 };
 
 static int __init init_com20020_cs(void)
@@ -502,7 +451,6 @@ static int __init init_com20020_cs(void)
 static void __exit exit_com20020_cs(void)
 {
 	pcmcia_unregister_driver(&com20020_cs_driver);
-	BUG_ON(dev_list != NULL);
 }
 
 module_init(init_com20020_cs);
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
index 356f50909222..28fe2fb4d6c0 100644
--- a/drivers/net/pcmcia/fmvj18x_cs.c
+++ b/drivers/net/pcmcia/fmvj18x_cs.c
@@ -88,10 +88,7 @@ static void fmvj18x_config(dev_link_t *link);
 static int fmvj18x_get_hwinfo(dev_link_t *link, u_char *node_id);
 static int fmvj18x_setup_mfc(dev_link_t *link);
 static void fmvj18x_release(dev_link_t *link);
-static int fmvj18x_event(event_t event, int priority,
-			  event_callback_args_t *args);
-static dev_link_t *fmvj18x_attach(void);
-static void fmvj18x_detach(dev_link_t *);
+static void fmvj18x_detach(struct pcmcia_device *p_dev);
 
 /*
     LAN controller(MBH86960A) specific routines
@@ -108,9 +105,6 @@ static void set_rx_mode(struct net_device *dev);
 static void fjn_tx_timeout(struct net_device *dev);
 static struct ethtool_ops netdev_ethtool_ops;
 
-static dev_info_t dev_info = "fmvj18x_cs";
-static dev_link_t *dev_list;
-
 /*
     card type
  */
@@ -234,20 +228,18 @@ typedef struct local_info_t {
 #define BANK_1U              0x24 /* bank 1 (CONFIG_1) */
 #define BANK_2U              0x28 /* bank 2 (CONFIG_1) */
 
-static dev_link_t *fmvj18x_attach(void)
+static int fmvj18x_attach(struct pcmcia_device *p_dev)
 {
     local_info_t *lp;
     dev_link_t *link;
     struct net_device *dev;
-    client_reg_t client_reg;
-    int ret;
-    
+
     DEBUG(0, "fmvj18x_attach()\n");
 
     /* Make up a FMVJ18x specific data structure */
     dev = alloc_etherdev(sizeof(local_info_t));
     if (!dev)
-	return NULL;
+	return -ENOMEM;
     lp = netdev_priv(dev);
     link = &lp->link;
     link->priv = dev;
@@ -262,7 +254,7 @@ static dev_link_t *fmvj18x_attach(void)
     link->irq.IRQInfo1 = IRQ_LEVEL_ID;
     link->irq.Handler = &fjn_interrupt;
     link->irq.Instance = dev;
-    
+
     /* General socket configuration */
     link->conf.Attributes = CONF_ENABLE_IRQ;
     link->conf.Vcc = 50;
@@ -281,37 +273,24 @@ static dev_link_t *fmvj18x_attach(void)
     dev->watchdog_timeo = TX_TIMEOUT;
 #endif
     SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
-    
-    /* Register with Card Services */
-    link->next = dev_list;
-    dev_list = link;
-    client_reg.dev_info = &dev_info;
-    client_reg.Version = 0x0210;
-    client_reg.event_callback_args.client_data = link;
-    ret = pcmcia_register_client(&link->handle, &client_reg);
-    if (ret != 0) {
-	cs_error(link->handle, RegisterClient, ret);
-	fmvj18x_detach(link);
-	return NULL;
-    }
 
-    return link;
+    link->handle = p_dev;
+    p_dev->instance = link;
+
+    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+    fmvj18x_config(link);
+
+    return 0;
 } /* fmvj18x_attach */
 
 /*====================================================================*/
 
-static void fmvj18x_detach(dev_link_t *link)
+static void fmvj18x_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     struct net_device *dev = link->priv;
-    dev_link_t **linkp;
-    
+
     DEBUG(0, "fmvj18x_detach(0x%p)\n", link);
-    
-    /* Locate device structure */
-    for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
-	if (*linkp == link) break;
-    if (*linkp == NULL)
-	return;
 
     if (link->dev)
 	unregister_netdev(dev);
@@ -319,12 +298,6 @@ static void fmvj18x_detach(dev_link_t *link)
     if (link->state & DEV_CONFIG)
 	fmvj18x_release(link);
 
-    /* Break the link with Card Services */
-    if (link->handle)
-	pcmcia_deregister_client(link->handle);
-    
-    /* Unlink device structure, free pieces */
-    *linkp = link->next;
     free_netdev(dev);
 } /* fmvj18x_detach */
 
@@ -713,51 +686,40 @@ static void fmvj18x_release(dev_link_t *link)
     link->state &= ~DEV_CONFIG;
 }
 
-/*====================================================================*/
-
-static int fmvj18x_event(event_t event, int priority,
-			  event_callback_args_t *args)
+static int fmvj18x_suspend(struct pcmcia_device *p_dev)
 {
-    dev_link_t *link = args->client_data;
-    struct net_device *dev = link->priv;
+	dev_link_t *link = dev_to_instance(p_dev);
+	struct net_device *dev = link->priv;
 
-    DEBUG(1, "fmvj18x_event(0x%06x)\n", event);
-    
-    switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-	link->state &= ~DEV_PRESENT;
-	if (link->state & DEV_CONFIG)
-	    netif_device_detach(dev);
-	break;
-    case CS_EVENT_CARD_INSERTION:
-	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-	fmvj18x_config(link);
-	break;
-    case CS_EVENT_PM_SUSPEND:
 	link->state |= DEV_SUSPEND;
-	/* Fall through... */
-    case CS_EVENT_RESET_PHYSICAL:
 	if (link->state & DEV_CONFIG) {
-	    if (link->open)
-		netif_device_detach(dev);
-	    pcmcia_release_configuration(link->handle);
+		if (link->open)
+			netif_device_detach(dev);
+		pcmcia_release_configuration(link->handle);
 	}
-	break;
-    case CS_EVENT_PM_RESUME:
+
+
+	return 0;
+}
+
+static int fmvj18x_resume(struct pcmcia_device *p_dev)
+{
+	dev_link_t *link = dev_to_instance(p_dev);
+	struct net_device *dev = link->priv;
+
 	link->state &= ~DEV_SUSPEND;
-	/* Fall through... */
-    case CS_EVENT_CARD_RESET:
 	if (link->state & DEV_CONFIG) {
-	    pcmcia_request_configuration(link->handle, &link->conf);
-	    if (link->open) {
-		fjn_reset(dev);
-		netif_device_attach(dev);
-	    }
+		pcmcia_request_configuration(link->handle, &link->conf);
+		if (link->open) {
+			fjn_reset(dev);
+			netif_device_attach(dev);
+		}
 	}
-	break;
-    }
-    return 0;
-} /* fmvj18x_event */
+
+	return 0;
+}
+
+/*====================================================================*/
 
 static struct pcmcia_device_id fmvj18x_ids[] = {
 	PCMCIA_DEVICE_MANF_CARD(0x0004, 0x0004),
@@ -789,10 +751,11 @@ static struct pcmcia_driver fmvj18x_cs_driver = {
 	.drv		= {
 		.name	= "fmvj18x_cs",
 	},
-	.attach		= fmvj18x_attach,
-	.event		= fmvj18x_event,
-	.detach		= fmvj18x_detach,
+	.probe		= fmvj18x_attach,
+	.remove		= fmvj18x_detach,
 	.id_table       = fmvj18x_ids,
+	.suspend	= fmvj18x_suspend,
+	.resume		= fmvj18x_resume,
 };
 
 static int __init init_fmvj18x_cs(void)
@@ -803,7 +766,6 @@ static int __init init_fmvj18x_cs(void)
 static void __exit exit_fmvj18x_cs(void)
 {
 	pcmcia_unregister_driver(&fmvj18x_cs_driver);
-	BUG_ON(dev_list != NULL);
 }
 
 module_init(init_fmvj18x_cs);
diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c
index b6c140eb9799..b9c7e39576f5 100644
--- a/drivers/net/pcmcia/ibmtr_cs.c
+++ b/drivers/net/pcmcia/ibmtr_cs.c
@@ -108,15 +108,7 @@ MODULE_LICENSE("GPL");
 static void ibmtr_config(dev_link_t *link);
 static void ibmtr_hw_setup(struct net_device *dev, u_int mmiobase);
 static void ibmtr_release(dev_link_t *link);
-static int ibmtr_event(event_t event, int priority,
-                       event_callback_args_t *args);
-
-static dev_info_t dev_info = "ibmtr_cs";
-
-static dev_link_t *ibmtr_attach(void);
-static void ibmtr_detach(dev_link_t *);
-
-static dev_link_t *dev_list;
+static void ibmtr_detach(struct pcmcia_device *p_dev);
 
 /*====================================================================*/
 
@@ -146,25 +138,23 @@ static struct ethtool_ops netdev_ethtool_ops = {
 
 ======================================================================*/
 
-static dev_link_t *ibmtr_attach(void)
+static int ibmtr_attach(struct pcmcia_device *p_dev)
 {
     ibmtr_dev_t *info;
     dev_link_t *link;
     struct net_device *dev;
-    client_reg_t client_reg;
-    int ret;
     
     DEBUG(0, "ibmtr_attach()\n");
 
     /* Create new token-ring device */
     info = kmalloc(sizeof(*info), GFP_KERNEL); 
-    if (!info) return NULL;
+    if (!info) return -ENOMEM;
     memset(info,0,sizeof(*info));
     dev = alloc_trdev(sizeof(struct tok_info));
-    if (!dev) { 
-	kfree(info); 
-	return NULL;
-    } 
+    if (!dev) {
+	kfree(info);
+	return -ENOMEM;
+    }
 
     link = &info->link;
     link->priv = info;
@@ -185,25 +175,13 @@ static dev_link_t *ibmtr_attach(void)
     
     SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
 
-    /* Register with Card Services */
-    link->next = dev_list;
-    dev_list = link;
-    client_reg.dev_info = &dev_info;
-    client_reg.Version = 0x0210;
-    client_reg.event_callback_args.client_data = link;
-    ret = pcmcia_register_client(&link->handle, &client_reg);
-    if (ret != 0) {
-        cs_error(link->handle, RegisterClient, ret);
-	goto out_detach;
-    }
+    link->handle = p_dev;
+    p_dev->instance = link;
 
-out:
-    return link;
+    link->state |= DEV_PRESENT;
+    ibmtr_config(link);
 
-out_detach:
-    ibmtr_detach(link);
-    link = NULL;
-    goto out;
+    return 0;
 } /* ibmtr_attach */
 
 /*======================================================================
@@ -215,22 +193,14 @@ out_detach:
 
 ======================================================================*/
 
-static void ibmtr_detach(dev_link_t *link)
+static void ibmtr_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     struct ibmtr_dev_t *info = link->priv;
-    dev_link_t **linkp;
-    struct net_device *dev;
+    struct net_device *dev = info->dev;
 
     DEBUG(0, "ibmtr_detach(0x%p)\n", link);
 
-    /* Locate device structure */
-    for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
-        if (*linkp == link) break;
-    if (*linkp == NULL)
-        return;
-
-    dev = info->dev;
-
     if (link->dev)
 	unregister_netdev(dev);
 
@@ -241,13 +211,8 @@ static void ibmtr_detach(dev_link_t *link)
     if (link->state & DEV_CONFIG)
         ibmtr_release(link);
 
-    if (link->handle)
-        pcmcia_deregister_client(link->handle);
-
-    /* Unlink device structure, free bits */
-    *linkp = link->next;
     free_netdev(dev);
-    kfree(info); 
+    kfree(info);
 } /* ibmtr_detach */
 
 /*======================================================================
@@ -401,63 +366,40 @@ static void ibmtr_release(dev_link_t *link)
     link->state &= ~DEV_CONFIG;
 }
 
-/*======================================================================
+static int ibmtr_suspend(struct pcmcia_device *p_dev)
+{
+	dev_link_t *link = dev_to_instance(p_dev);
+	ibmtr_dev_t *info = link->priv;
+	struct net_device *dev = info->dev;
 
-    The card status event handler.  Mostly, this schedules other
-    stuff to run after an event is received.  A CARD_REMOVAL event
-    also sets some flags to discourage the net drivers from trying
-    to talk to the card any more.
+	link->state |= DEV_SUSPEND;
+        if (link->state & DEV_CONFIG) {
+		if (link->open)
+			netif_device_detach(dev);
+		pcmcia_release_configuration(link->handle);
+        }
 
-======================================================================*/
+	return 0;
+}
 
-static int ibmtr_event(event_t event, int priority,
-                       event_callback_args_t *args)
+static int ibmtr_resume(struct pcmcia_device *p_dev)
 {
-    dev_link_t *link = args->client_data;
-    ibmtr_dev_t *info = link->priv;
-    struct net_device *dev = info->dev;
+	dev_link_t *link = dev_to_instance(p_dev);
+	ibmtr_dev_t *info = link->priv;
+	struct net_device *dev = info->dev;
 
-    DEBUG(1, "ibmtr_event(0x%06x)\n", event);
-
-    switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-        link->state &= ~DEV_PRESENT;
-        if (link->state & DEV_CONFIG) {
-	    /* set flag to bypass normal interrupt code */
-	    struct tok_info *priv = netdev_priv(dev);
-	    priv->sram_phys |= 1;
-	    netif_device_detach(dev);
-        }
-        break;
-    case CS_EVENT_CARD_INSERTION:
-        link->state |= DEV_PRESENT;
-	ibmtr_config(link);
-	break;
-    case CS_EVENT_PM_SUSPEND:
-        link->state |= DEV_SUSPEND;
-        /* Fall through... */
-    case CS_EVENT_RESET_PHYSICAL:
+	link->state &= ~DEV_SUSPEND;
         if (link->state & DEV_CONFIG) {
-            if (link->open)
-		netif_device_detach(dev);
-            pcmcia_release_configuration(link->handle);
+		pcmcia_request_configuration(link->handle, &link->conf);
+		if (link->open) {
+			ibmtr_probe(dev);	/* really? */
+			netif_device_attach(dev);
+		}
         }
-        break;
-    case CS_EVENT_PM_RESUME:
-        link->state &= ~DEV_SUSPEND;
-        /* Fall through... */
-    case CS_EVENT_CARD_RESET:
-        if (link->state & DEV_CONFIG) {
-            pcmcia_request_configuration(link->handle, &link->conf);
-            if (link->open) {
-		ibmtr_probe(dev);	/* really? */
-		netif_device_attach(dev);
-            }
-        }
-        break;
-    }
-    return 0;
-} /* ibmtr_event */
+
+	return 0;
+}
+
 
 /*====================================================================*/
 
@@ -514,10 +456,11 @@ static struct pcmcia_driver ibmtr_cs_driver = {
 	.drv		= {
 		.name	= "ibmtr_cs",
 	},
-	.attach		= ibmtr_attach,
-	.event		= ibmtr_event,
-	.detach		= ibmtr_detach,
+	.probe		= ibmtr_attach,
+	.remove		= ibmtr_detach,
 	.id_table       = ibmtr_ids,
+	.suspend	= ibmtr_suspend,
+	.resume		= ibmtr_resume,
 };
 
 static int __init init_ibmtr_cs(void)
@@ -528,7 +471,6 @@ static int __init init_ibmtr_cs(void)
 static void __exit exit_ibmtr_cs(void)
 {
 	pcmcia_unregister_driver(&ibmtr_cs_driver);
-	BUG_ON(dev_list != NULL);
 }
 
 module_init(init_ibmtr_cs);
diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c
index 980d7e5d66cb..4a232254a497 100644
--- a/drivers/net/pcmcia/nmclan_cs.c
+++ b/drivers/net/pcmcia/nmclan_cs.c
@@ -388,9 +388,6 @@ static char *version =
 DRV_NAME " " DRV_VERSION " (Roger C. Pao)";
 #endif
 
-static dev_info_t dev_info="nmclan_cs";
-static dev_link_t *dev_list;
-
 static char *if_names[]={
     "Auto", "10baseT", "BNC",
 };
@@ -422,8 +419,6 @@ Function Prototypes
 
 static void nmclan_config(dev_link_t *link);
 static void nmclan_release(dev_link_t *link);
-static int nmclan_event(event_t event, int priority,
-			event_callback_args_t *args);
 
 static void nmclan_reset(struct net_device *dev);
 static int mace_config(struct net_device *dev, struct ifmap *map);
@@ -439,8 +434,7 @@ static void set_multicast_list(struct net_device *dev);
 static struct ethtool_ops netdev_ethtool_ops;
 
 
-static dev_link_t *nmclan_attach(void);
-static void nmclan_detach(dev_link_t *);
+static void nmclan_detach(struct pcmcia_device *p_dev);
 
 /* ----------------------------------------------------------------------------
 nmclan_attach
@@ -449,13 +443,11 @@ nmclan_attach
 	Services.
 ---------------------------------------------------------------------------- */
 
-static dev_link_t *nmclan_attach(void)
+static int nmclan_attach(struct pcmcia_device *p_dev)
 {
     mace_private *lp;
     dev_link_t *link;
     struct net_device *dev;
-    client_reg_t client_reg;
-    int ret;
 
     DEBUG(0, "nmclan_attach()\n");
     DEBUG(1, "%s\n", rcsid);
@@ -463,7 +455,7 @@ static dev_link_t *nmclan_attach(void)
     /* Create new ethernet device */
     dev = alloc_etherdev(sizeof(mace_private));
     if (!dev)
-	return NULL;
+	    return -ENOMEM;
     lp = netdev_priv(dev);
     link = &lp->link;
     link->priv = dev;
@@ -497,20 +489,13 @@ static dev_link_t *nmclan_attach(void)
     dev->watchdog_timeo = TX_TIMEOUT;
 #endif
 
-    /* Register with Card Services */
-    link->next = dev_list;
-    dev_list = link;
-    client_reg.dev_info = &dev_info;
-    client_reg.Version = 0x0210;
-    client_reg.event_callback_args.client_data = link;
-    ret = pcmcia_register_client(&link->handle, &client_reg);
-    if (ret != 0) {
-	cs_error(link->handle, RegisterClient, ret);
-	nmclan_detach(link);
-	return NULL;
-    }
+    link->handle = p_dev;
+    p_dev->instance = link;
+
+    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+    nmclan_config(link);
 
-    return link;
+    return 0;
 } /* nmclan_attach */
 
 /* ----------------------------------------------------------------------------
@@ -521,30 +506,19 @@ nmclan_detach
 	when the device is released.
 ---------------------------------------------------------------------------- */
 
-static void nmclan_detach(dev_link_t *link)
+static void nmclan_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     struct net_device *dev = link->priv;
-    dev_link_t **linkp;
 
     DEBUG(0, "nmclan_detach(0x%p)\n", link);
 
-    /* Locate device structure */
-    for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
-	if (*linkp == link) break;
-    if (*linkp == NULL)
-	return;
-
     if (link->dev)
 	unregister_netdev(dev);
 
     if (link->state & DEV_CONFIG)
 	nmclan_release(link);
 
-    if (link->handle)
-	pcmcia_deregister_client(link->handle);
-
-    /* Unlink device structure, free bits */
-    *linkp = link->next;
     free_netdev(dev);
 } /* nmclan_detach */
 
@@ -801,59 +775,39 @@ static void nmclan_release(dev_link_t *link)
   link->state &= ~DEV_CONFIG;
 }
 
-/* ----------------------------------------------------------------------------
-nmclan_event
-	The card status event handler.  Mostly, this schedules other
-	stuff to run after an event is received.  A CARD_REMOVAL event
-	also sets some flags to discourage the net drivers from trying
-	to talk to the card any more.
----------------------------------------------------------------------------- */
-static int nmclan_event(event_t event, int priority,
-		       event_callback_args_t *args)
+static int nmclan_suspend(struct pcmcia_device *p_dev)
 {
-  dev_link_t *link = args->client_data;
-  struct net_device *dev = link->priv;
+	dev_link_t *link = dev_to_instance(p_dev);
+	struct net_device *dev = link->priv;
+
+	link->state |= DEV_SUSPEND;
+	if (link->state & DEV_CONFIG) {
+		if (link->open)
+			netif_device_detach(dev);
+		pcmcia_release_configuration(link->handle);
+	}
 
-  DEBUG(1, "nmclan_event(0x%06x)\n", event);
 
-  switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-      link->state &= ~DEV_PRESENT;
-      if (link->state & DEV_CONFIG)
-	netif_device_detach(dev);
-      break;
-    case CS_EVENT_CARD_INSERTION:
-      link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-      nmclan_config(link);
-      break;
-    case CS_EVENT_PM_SUSPEND:
-      link->state |= DEV_SUSPEND;
-      /* Fall through... */
-    case CS_EVENT_RESET_PHYSICAL:
-      if (link->state & DEV_CONFIG) {
-	if (link->open)
-	  netif_device_detach(dev);
-	pcmcia_release_configuration(link->handle);
-      }
-      break;
-    case CS_EVENT_PM_RESUME:
-      link->state &= ~DEV_SUSPEND;
-      /* Fall through... */
-    case CS_EVENT_CARD_RESET:
-      if (link->state & DEV_CONFIG) {
-	pcmcia_request_configuration(link->handle, &link->conf);
-	if (link->open) {
-	  nmclan_reset(dev);
-	  netif_device_attach(dev);
+	return 0;
+}
+
+static int nmclan_resume(struct pcmcia_device *p_dev)
+{
+	dev_link_t *link = dev_to_instance(p_dev);
+	struct net_device *dev = link->priv;
+
+	link->state &= ~DEV_SUSPEND;
+	if (link->state & DEV_CONFIG) {
+		pcmcia_request_configuration(link->handle, &link->conf);
+		if (link->open) {
+			nmclan_reset(dev);
+			netif_device_attach(dev);
+		}
 	}
-      }
-      break;
-    case CS_EVENT_RESET_REQUEST:
-      return 1;
-      break;
-  }
-  return 0;
-} /* nmclan_event */
+
+	return 0;
+}
+
 
 /* ----------------------------------------------------------------------------
 nmclan_reset
@@ -1681,10 +1635,11 @@ static struct pcmcia_driver nmclan_cs_driver = {
 	.drv		= {
 		.name	= "nmclan_cs",
 	},
-	.attach		= nmclan_attach,
-	.event		= nmclan_event,
-	.detach		= nmclan_detach,
+	.probe		= nmclan_attach,
+	.remove		= nmclan_detach,
 	.id_table       = nmclan_ids,
+	.suspend	= nmclan_suspend,
+	.resume		= nmclan_resume,
 };
 
 static int __init init_nmclan_cs(void)
@@ -1695,7 +1650,6 @@ static int __init init_nmclan_cs(void)
 static void __exit exit_nmclan_cs(void)
 {
 	pcmcia_unregister_driver(&nmclan_cs_driver);
-	BUG_ON(dev_list != NULL);
 }
 
 module_init(init_nmclan_cs);
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index 818c185d6438..d85b758f3efa 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -105,8 +105,6 @@ module_param_array(hw_addr, int, NULL, 0);
 static void mii_phy_probe(struct net_device *dev);
 static void pcnet_config(dev_link_t *link);
 static void pcnet_release(dev_link_t *link);
-static int pcnet_event(event_t event, int priority,
-		       event_callback_args_t *args);
 static int pcnet_open(struct net_device *dev);
 static int pcnet_close(struct net_device *dev);
 static int ei_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
@@ -120,11 +118,9 @@ static int setup_shmem_window(dev_link_t *link, int start_pg,
 static int setup_dma_config(dev_link_t *link, int start_pg,
 			    int stop_pg);
 
-static dev_link_t *pcnet_attach(void);
-static void pcnet_detach(dev_link_t *);
+static void pcnet_detach(struct pcmcia_device *p_dev);
 
 static dev_info_t dev_info = "pcnet_cs";
-static dev_link_t *dev_list;
 
 /*====================================================================*/
 
@@ -244,19 +240,17 @@ static inline pcnet_dev_t *PRIV(struct net_device *dev)
 
 ======================================================================*/
 
-static dev_link_t *pcnet_attach(void)
+static int pcnet_probe(struct pcmcia_device *p_dev)
 {
     pcnet_dev_t *info;
     dev_link_t *link;
     struct net_device *dev;
-    client_reg_t client_reg;
-    int ret;
 
     DEBUG(0, "pcnet_attach()\n");
 
     /* Create new ethernet device */
     dev = __alloc_ei_netdev(sizeof(pcnet_dev_t));
-    if (!dev) return NULL;
+    if (!dev) return -ENOMEM;
     info = PRIV(dev);
     link = &info->link;
     link->priv = dev;
@@ -271,20 +265,13 @@ static dev_link_t *pcnet_attach(void)
     dev->stop = &pcnet_close;
     dev->set_config = &set_config;
 
-    /* Register with Card Services */
-    link->next = dev_list;
-    dev_list = link;
-    client_reg.dev_info = &dev_info;
-    client_reg.Version = 0x0210;
-    client_reg.event_callback_args.client_data = link;
-    ret = pcmcia_register_client(&link->handle, &client_reg);
-    if (ret != CS_SUCCESS) {
-	cs_error(link->handle, RegisterClient, ret);
-	pcnet_detach(link);
-	return NULL;
-    }
+    link->handle = p_dev;
+    p_dev->instance = link;
 
-    return link;
+    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+    pcnet_config(link);
+
+    return 0;
 } /* pcnet_attach */
 
 /*======================================================================
@@ -296,31 +283,20 @@ static dev_link_t *pcnet_attach(void)
 
 ======================================================================*/
 
-static void pcnet_detach(dev_link_t *link)
+static void pcnet_detach(struct pcmcia_device *p_dev)
 {
-    struct net_device *dev = link->priv;
-    dev_link_t **linkp;
-
-    DEBUG(0, "pcnet_detach(0x%p)\n", link);
+	dev_link_t *link = dev_to_instance(p_dev);
+	struct net_device *dev = link->priv;
 
-    /* Locate device structure */
-    for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
-	if (*linkp == link) break;
-    if (*linkp == NULL)
-	return;
+	DEBUG(0, "pcnet_detach(0x%p)\n", link);
 
-    if (link->dev)
-	unregister_netdev(dev);
+	if (link->dev)
+		unregister_netdev(dev);
 
-    if (link->state & DEV_CONFIG)
-	pcnet_release(link);
-
-    if (link->handle)
-	pcmcia_deregister_client(link->handle);
+	if (link->state & DEV_CONFIG)
+		pcnet_release(link);
 
-    /* Unlink device structure, free bits */
-    *linkp = link->next;
-    free_netdev(dev);
+	free_netdev(dev);
 } /* pcnet_detach */
 
 /*======================================================================
@@ -780,50 +756,39 @@ static void pcnet_release(dev_link_t *link)
 
 ======================================================================*/
 
-static int pcnet_event(event_t event, int priority,
-		       event_callback_args_t *args)
+static int pcnet_suspend(struct pcmcia_device *p_dev)
 {
-    dev_link_t *link = args->client_data;
-    struct net_device *dev = link->priv;
+	dev_link_t *link = dev_to_instance(p_dev);
+	struct net_device *dev = link->priv;
 
-    DEBUG(2, "pcnet_event(0x%06x)\n", event);
-
-    switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-	link->state &= ~DEV_PRESENT;
-	if (link->state & DEV_CONFIG)
-	    netif_device_detach(dev);
-	break;
-    case CS_EVENT_CARD_INSERTION:
-	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-	pcnet_config(link);
-	break;
-    case CS_EVENT_PM_SUSPEND:
 	link->state |= DEV_SUSPEND;
-	/* Fall through... */
-    case CS_EVENT_RESET_PHYSICAL:
 	if (link->state & DEV_CONFIG) {
-	    if (link->open)
-		netif_device_detach(dev);
-	    pcmcia_release_configuration(link->handle);
+		if (link->open)
+			netif_device_detach(dev);
+		pcmcia_release_configuration(link->handle);
 	}
-	break;
-    case CS_EVENT_PM_RESUME:
+
+	return 0;
+}
+
+static int pcnet_resume(struct pcmcia_device *p_dev)
+{
+	dev_link_t *link = dev_to_instance(p_dev);
+	struct net_device *dev = link->priv;
+
 	link->state &= ~DEV_SUSPEND;
-	/* Fall through... */
-    case CS_EVENT_CARD_RESET:
 	if (link->state & DEV_CONFIG) {
-	    pcmcia_request_configuration(link->handle, &link->conf);
-	    if (link->open) {
-		pcnet_reset_8390(dev);
-		NS8390_init(dev, 1);
-		netif_device_attach(dev);
-	    }
+		pcmcia_request_configuration(link->handle, &link->conf);
+		if (link->open) {
+			pcnet_reset_8390(dev);
+			NS8390_init(dev, 1);
+			netif_device_attach(dev);
+		}
 	}
-	break;
-    }
-    return 0;
-} /* pcnet_event */
+
+	return 0;
+}
+
 
 /*======================================================================
 
@@ -1844,11 +1809,12 @@ static struct pcmcia_driver pcnet_driver = {
 	.drv		= {
 		.name	= "pcnet_cs",
 	},
-	.attach		= pcnet_attach,
-	.event		= pcnet_event,
-	.detach		= pcnet_detach,
+	.probe		= pcnet_probe,
+	.remove		= pcnet_detach,
 	.owner		= THIS_MODULE,
 	.id_table	= pcnet_ids,
+	.suspend	= pcnet_suspend,
+	.resume		= pcnet_resume,
 };
 
 static int __init init_pcnet_cs(void)
@@ -1860,7 +1826,6 @@ static void __exit exit_pcnet_cs(void)
 {
     DEBUG(0, "pcnet_cs: unloading\n");
     pcmcia_unregister_driver(&pcnet_driver);
-    BUG_ON(dev_list != NULL);
 }
 
 module_init(init_pcnet_cs);
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index c7cca842e5ee..0122415dfeef 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -102,10 +102,6 @@ static const char *version =
    currently have room for another Tx packet. */
 #define MEMORY_WAIT_TIME       	8
 
-static dev_info_t dev_info = "smc91c92_cs";
-
-static dev_link_t *dev_list;
-
 struct smc_private {
     dev_link_t			link;
     spinlock_t			lock;
@@ -281,12 +277,9 @@ enum RxCfg { RxAllMulti = 0x0004, RxPromisc = 0x0002,
 
 /*====================================================================*/
 
-static dev_link_t *smc91c92_attach(void);
-static void smc91c92_detach(dev_link_t *);
+static void smc91c92_detach(struct pcmcia_device *p_dev);
 static void smc91c92_config(dev_link_t *link);
 static void smc91c92_release(dev_link_t *link);
-static int smc91c92_event(event_t event, int priority,
-			  event_callback_args_t *args);
 
 static int smc_open(struct net_device *dev);
 static int smc_close(struct net_device *dev);
@@ -315,20 +308,18 @@ static struct ethtool_ops ethtool_ops;
 
 ======================================================================*/
 
-static dev_link_t *smc91c92_attach(void)
+static int smc91c92_attach(struct pcmcia_device *p_dev)
 {
-    client_reg_t client_reg;
     struct smc_private *smc;
     dev_link_t *link;
     struct net_device *dev;
-    int ret;
 
     DEBUG(0, "smc91c92_attach()\n");
 
     /* Create new ethernet device */
     dev = alloc_etherdev(sizeof(struct smc_private));
     if (!dev)
-	return NULL;
+	return -ENOMEM;
     smc = netdev_priv(dev);
     link = &smc->link;
     link->priv = dev;
@@ -366,20 +357,13 @@ static dev_link_t *smc91c92_attach(void)
     smc->mii_if.phy_id_mask = 0x1f;
     smc->mii_if.reg_num_mask = 0x1f;
 
-    /* Register with Card Services */
-    link->next = dev_list;
-    dev_list = link;
-    client_reg.dev_info = &dev_info;
-    client_reg.Version = 0x0210;
-    client_reg.event_callback_args.client_data = link;
-    ret = pcmcia_register_client(&link->handle, &client_reg);
-    if (ret != 0) {
-	cs_error(link->handle, RegisterClient, ret);
-	smc91c92_detach(link);
-	return NULL;
-    }
+    link->handle = p_dev;
+    p_dev->instance = link;
+
+    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+    smc91c92_config(link);
 
-    return link;
+    return 0;
 } /* smc91c92_attach */
 
 /*======================================================================
@@ -391,30 +375,19 @@ static dev_link_t *smc91c92_attach(void)
 
 ======================================================================*/
 
-static void smc91c92_detach(dev_link_t *link)
+static void smc91c92_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     struct net_device *dev = link->priv;
-    dev_link_t **linkp;
 
     DEBUG(0, "smc91c92_detach(0x%p)\n", link);
 
-    /* Locate device structure */
-    for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
-	if (*linkp == link) break;
-    if (*linkp == NULL)
-	return;
-
     if (link->dev)
 	unregister_netdev(dev);
 
     if (link->state & DEV_CONFIG)
 	smc91c92_release(link);
 
-    if (link->handle)
-	pcmcia_deregister_client(link->handle);
-
-    /* Unlink device structure, free bits */
-    *linkp = link->next;
     free_netdev(dev);
 } /* smc91c92_detach */
 
@@ -895,6 +868,62 @@ free_cfg_mem:
    return rc;
 }
 
+static int smc91c92_suspend(struct pcmcia_device *p_dev)
+{
+	dev_link_t *link = dev_to_instance(p_dev);
+	struct net_device *dev = link->priv;
+
+	link->state |= DEV_SUSPEND;
+	if (link->state & DEV_CONFIG) {
+		if (link->open)
+			netif_device_detach(dev);
+		pcmcia_release_configuration(link->handle);
+	}
+
+	return 0;
+}
+
+static int smc91c92_resume(struct pcmcia_device *p_dev)
+{
+	dev_link_t *link = dev_to_instance(p_dev);
+	struct net_device *dev = link->priv;
+	struct smc_private *smc = netdev_priv(dev);
+	int i;
+
+	link->state &= ~DEV_SUSPEND;
+	if (link->state & DEV_CONFIG) {
+		if ((smc->manfid == MANFID_MEGAHERTZ) &&
+		    (smc->cardid == PRODID_MEGAHERTZ_EM3288))
+			mhz_3288_power(link);
+		pcmcia_request_configuration(link->handle, &link->conf);
+		if (smc->manfid == MANFID_MOTOROLA)
+			mot_config(link);
+		if ((smc->manfid == MANFID_OSITECH) &&
+		    (smc->cardid != PRODID_OSITECH_SEVEN)) {
+			/* Power up the card and enable interrupts */
+			set_bits(0x0300, dev->base_addr-0x10+OSITECH_AUI_PWR);
+			set_bits(0x0300, dev->base_addr-0x10+OSITECH_RESET_ISR);
+		}
+		if (((smc->manfid == MANFID_OSITECH) &&
+		     (smc->cardid == PRODID_OSITECH_SEVEN)) ||
+		    ((smc->manfid == MANFID_PSION) &&
+		     (smc->cardid == PRODID_PSION_NET100))) {
+			/* Download the Seven of Diamonds firmware */
+			for (i = 0; i < sizeof(__Xilinx7OD); i++) {
+				outb(__Xilinx7OD[i], link->io.BasePort1+2);
+				udelay(50);
+			}
+		}
+		if (link->open) {
+			smc_reset(dev);
+			netif_device_attach(dev);
+		}
+	}
+
+	return 0;
+}
+
+
 /*======================================================================
 
     This verifies that the chip is some SMC91cXX variant, and returns
@@ -935,14 +964,12 @@ static int check_sig(dev_link_t *link)
     }
 
     if (width) {
-	event_callback_args_t args;
 	printk(KERN_INFO "smc91c92_cs: using 8-bit IO window.\n");
-	args.client_data = link;
-	smc91c92_event(CS_EVENT_RESET_PHYSICAL, 0, &args);
+	smc91c92_suspend(link->handle);
 	pcmcia_release_io(link->handle, &link->io);
 	link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
 	pcmcia_request_io(link->handle, &link->io);
-	smc91c92_event(CS_EVENT_CARD_RESET, 0, &args);
+	smc91c92_resume(link->handle);
 	return check_sig(link);
     }
     return -ENODEV;
@@ -1172,82 +1199,6 @@ static void smc91c92_release(dev_link_t *link)
 
 /*======================================================================
 
-    The card status event handler.  Mostly, this schedules other
-    stuff to run after an event is received.  A CARD_REMOVAL event
-    also sets some flags to discourage the net drivers from trying
-    to talk to the card any more.
-
-======================================================================*/
-
-static int smc91c92_event(event_t event, int priority,
-			  event_callback_args_t *args)
-{
-    dev_link_t *link = args->client_data;
-    struct net_device *dev = link->priv;
-    struct smc_private *smc = netdev_priv(dev);
-    int i;
-
-    DEBUG(1, "smc91c92_event(0x%06x)\n", event);
-
-    switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-	link->state &= ~DEV_PRESENT;
-	if (link->state & DEV_CONFIG)
-	    netif_device_detach(dev);
-	break;
-    case CS_EVENT_CARD_INSERTION:
-	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-	smc91c92_config(link);
-	break;
-    case CS_EVENT_PM_SUSPEND:
-	link->state |= DEV_SUSPEND;
-	/* Fall through... */
-    case CS_EVENT_RESET_PHYSICAL:
-	if (link->state & DEV_CONFIG) {
-	    if (link->open)
-		netif_device_detach(dev);
-	    pcmcia_release_configuration(link->handle);
-	}
-	break;
-    case CS_EVENT_PM_RESUME:
-	link->state &= ~DEV_SUSPEND;
-	/* Fall through... */
-    case CS_EVENT_CARD_RESET:
-	if (link->state & DEV_CONFIG) {
-	    if ((smc->manfid == MANFID_MEGAHERTZ) &&
-		(smc->cardid == PRODID_MEGAHERTZ_EM3288))
-		mhz_3288_power(link);
-	    pcmcia_request_configuration(link->handle, &link->conf);
-	    if (smc->manfid == MANFID_MOTOROLA)
-		mot_config(link);
-	    if ((smc->manfid == MANFID_OSITECH) &&
-		(smc->cardid != PRODID_OSITECH_SEVEN)) {
-		/* Power up the card and enable interrupts */
-		set_bits(0x0300, dev->base_addr-0x10+OSITECH_AUI_PWR);
-		set_bits(0x0300, dev->base_addr-0x10+OSITECH_RESET_ISR);
-	    }
-	    if (((smc->manfid == MANFID_OSITECH) &&
-	 	(smc->cardid == PRODID_OSITECH_SEVEN)) ||
-		((smc->manfid == MANFID_PSION) &&
-	 	(smc->cardid == PRODID_PSION_NET100))) {
-		/* Download the Seven of Diamonds firmware */
-		for (i = 0; i < sizeof(__Xilinx7OD); i++) {
-	    	    outb(__Xilinx7OD[i], link->io.BasePort1+2);
-	   	    udelay(50);
-		}
-	    }
-	    if (link->open) {
-		smc_reset(dev);
-		netif_device_attach(dev);
-	    }
-	}
-	break;
-    }
-    return 0;
-} /* smc91c92_event */
-
-/*======================================================================
-
     MII interface support for SMC91cXX based cards
 ======================================================================*/
 
@@ -2360,10 +2311,11 @@ static struct pcmcia_driver smc91c92_cs_driver = {
 	.drv		= {
 		.name	= "smc91c92_cs",
 	},
-	.attach		= smc91c92_attach,
-	.event		= smc91c92_event,
-	.detach		= smc91c92_detach,
+	.probe		= smc91c92_attach,
+	.remove		= smc91c92_detach,
 	.id_table       = smc91c92_ids,
+	.suspend	= smc91c92_suspend,
+	.resume		= smc91c92_resume,
 };
 
 static int __init init_smc91c92_cs(void)
@@ -2374,7 +2326,6 @@ static int __init init_smc91c92_cs(void)
 static void __exit exit_smc91c92_cs(void)
 {
 	pcmcia_unregister_driver(&smc91c92_cs_driver);
-	BUG_ON(dev_list != NULL);
 }
 
 module_init(init_smc91c92_cs);
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c
index ce143f08638a..049c34b37067 100644
--- a/drivers/net/pcmcia/xirc2ps_cs.c
+++ b/drivers/net/pcmcia/xirc2ps_cs.c
@@ -292,8 +292,6 @@ static void mii_wr(kio_addr_t ioaddr, u_char phyaddr, u_char phyreg,
 static int has_ce2_string(dev_link_t * link);
 static void xirc2ps_config(dev_link_t * link);
 static void xirc2ps_release(dev_link_t * link);
-static int xirc2ps_event(event_t event, int priority,
-			 event_callback_args_t * args);
 
 /****************
  * The attach() and detach() entry points are used to create and destroy
@@ -301,8 +299,7 @@ static int xirc2ps_event(event_t event, int priority,
  * needed to manage one actual PCMCIA card.
  */
 
-static dev_link_t *xirc2ps_attach(void);
-static void xirc2ps_detach(dev_link_t *);
+static void xirc2ps_detach(struct pcmcia_device *p_dev);
 
 /****************
  * You'll also need to prototype all the functions that will actually
@@ -313,14 +310,6 @@ static void xirc2ps_detach(dev_link_t *);
 
 static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 
-/*
- * The dev_info variable is the "key" that is used to match up this
- * device driver with appropriate cards, through the card configuration
- * database.
- */
-
-static dev_info_t dev_info = "xirc2ps_cs";
-
 /****************
  * A linked list of "instances" of the device.  Each actual
  * PCMCIA card corresponds to one device instance, and is described
@@ -331,15 +320,7 @@ static dev_info_t dev_info = "xirc2ps_cs";
  * device numbers are used to derive the corresponding array index.
  */
 
-static dev_link_t *dev_list;
-
 /****************
- * A dev_link_t structure has fields for most things that are needed
- * to keep track of a socket, but there will usually be some device
- * specific information that also needs to be kept track of.  The
- * 'priv' pointer in a dev_link_t structure can be used to point to
- * a device-specific private data structure, like this.
- *
  * A driver needs to provide a dev_node_t structure for each device
  * on a card.  In some cases, there is only one device per card (for
  * example, ethernet cards, modems).  In other cases, there may be
@@ -571,21 +552,19 @@ mii_wr(kio_addr_t ioaddr, u_char phyaddr, u_char phyreg, unsigned data, int len)
  * card insertion event.
  */
 
-static dev_link_t *
-xirc2ps_attach(void)
+static int
+xirc2ps_attach(struct pcmcia_device *p_dev)
 {
-    client_reg_t client_reg;
     dev_link_t *link;
     struct net_device *dev;
     local_info_t *local;
-    int err;
 
     DEBUG(0, "attach()\n");
 
     /* Allocate the device structure */
     dev = alloc_etherdev(sizeof(local_info_t));
     if (!dev)
-	    return NULL;
+	    return -ENOMEM;
     local = netdev_priv(dev);
     link = &local->link;
     link->priv = dev;
@@ -614,19 +593,13 @@ xirc2ps_attach(void)
     dev->watchdog_timeo = TX_TIMEOUT;
 #endif
 
-    /* Register with Card Services */
-    link->next = dev_list;
-    dev_list = link;
-    client_reg.dev_info = &dev_info;
-    client_reg.Version = 0x0210;
-    client_reg.event_callback_args.client_data = link;
-    if ((err = pcmcia_register_client(&link->handle, &client_reg))) {
-	cs_error(link->handle, RegisterClient, err);
-	xirc2ps_detach(link);
-	return NULL;
-    }
+    link->handle = p_dev;
+    p_dev->instance = link;
+
+    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+    xirc2ps_config(link);
 
-    return link;
+    return 0;
 } /* xirc2ps_attach */
 
 /****************
@@ -637,40 +610,19 @@ xirc2ps_attach(void)
  */
 
 static void
-xirc2ps_detach(dev_link_t * link)
+xirc2ps_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     struct net_device *dev = link->priv;
-    dev_link_t **linkp;
 
     DEBUG(0, "detach(0x%p)\n", link);
 
-    /* Locate device structure */
-    for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
-	if (*linkp == link)
-	    break;
-    if (!*linkp) {
-	DEBUG(0, "detach(0x%p): dev_link lost\n", link);
-	return;
-    }
-
     if (link->dev)
 	unregister_netdev(dev);
 
-    /*
-     * If the device is currently configured and active, we won't
-     * actually delete it yet.	Instead, it is marked so that when
-     * the release() function is called, that will trigger a proper
-     * detach().
-     */
     if (link->state & DEV_CONFIG)
 	xirc2ps_release(link);
 
-    /* Break the link with Card Services */
-    if (link->handle)
-	pcmcia_deregister_client(link->handle);
-
-    /* Unlink device structure, free it */
-    *linkp = link->next;
     free_netdev(dev);
 } /* xirc2ps_detach */
 
@@ -1157,67 +1109,41 @@ xirc2ps_release(dev_link_t *link)
 
 /*====================================================================*/
 
-/****************
- * The card status event handler.  Mostly, this schedules other
- * stuff to run after an event is received.  A CARD_REMOVAL event
- * also sets some flags to discourage the net drivers from trying
- * to talk to the card any more.
- *
- * When a CARD_REMOVAL event is received, we immediately set a flag
- * to block future accesses to this device.  All the functions that
- * actually access the device should check this flag to make sure
- * the card is still present.
- */
 
-static int
-xirc2ps_event(event_t event, int priority,
-	      event_callback_args_t * args)
+static int xirc2ps_suspend(struct pcmcia_device *p_dev)
 {
-    dev_link_t *link = args->client_data;
-    struct net_device *dev = link->priv;
-
-    DEBUG(0, "event(%d)\n", (int)event);
+	dev_link_t *link = dev_to_instance(p_dev);
+	struct net_device *dev = link->priv;
 
-    switch (event) {
-    case CS_EVENT_REGISTRATION_COMPLETE:
-	DEBUG(0, "registration complete\n");
-	break;
-    case CS_EVENT_CARD_REMOVAL:
-	link->state &= ~DEV_PRESENT;
-	if (link->state & DEV_CONFIG)
-	    netif_device_detach(dev);
-	break;
-    case CS_EVENT_CARD_INSERTION:
-	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-	xirc2ps_config(link);
-	break;
-    case CS_EVENT_PM_SUSPEND:
 	link->state |= DEV_SUSPEND;
-	/* Fall through... */
-    case CS_EVENT_RESET_PHYSICAL:
 	if (link->state & DEV_CONFIG) {
-	    if (link->open) {
-		netif_device_detach(dev);
-		do_powerdown(dev);
-	    }
-	    pcmcia_release_configuration(link->handle);
+		if (link->open) {
+			netif_device_detach(dev);
+			do_powerdown(dev);
+		}
+		pcmcia_release_configuration(link->handle);
 	}
-	break;
-    case CS_EVENT_PM_RESUME:
+
+	return 0;
+}
+
+static int xirc2ps_resume(struct pcmcia_device *p_dev)
+{
+	dev_link_t *link = dev_to_instance(p_dev);
+	struct net_device *dev = link->priv;
+
 	link->state &= ~DEV_SUSPEND;
-	/* Fall through... */
-    case CS_EVENT_CARD_RESET:
 	if (link->state & DEV_CONFIG) {
-	    pcmcia_request_configuration(link->handle, &link->conf);
-	    if (link->open) {
-		do_reset(dev,1);
-		netif_device_attach(dev);
-	    }
+		pcmcia_request_configuration(link->handle, &link->conf);
+		if (link->open) {
+			do_reset(dev,1);
+			netif_device_attach(dev);
+		}
 	}
-	break;
-    }
-    return 0;
-} /* xirc2ps_event */
+
+	return 0;
+}
+
 
 /*====================================================================*/
 
@@ -2009,10 +1935,11 @@ static struct pcmcia_driver xirc2ps_cs_driver = {
 	.drv		= {
 		.name	= "xirc2ps_cs",
 	},
-	.attach		= xirc2ps_attach,
-	.event		= xirc2ps_event,
-	.detach		= xirc2ps_detach,
+	.probe		= xirc2ps_attach,
+	.remove		= xirc2ps_detach,
 	.id_table       = xirc2ps_ids,
+	.suspend	= xirc2ps_suspend,
+	.resume		= xirc2ps_resume,
 };
 
 static int __init
@@ -2025,7 +1952,6 @@ static void __exit
 exit_xirc2ps_cs(void)
 {
 	pcmcia_unregister_driver(&xirc2ps_cs_driver);
-	BUG_ON(dev_list != NULL);
 }
 
 module_init(init_xirc2ps_cs);
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index c782a6329805..fa39b944bc46 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -6,7 +6,7 @@ menu "PHY device support"
 
 config PHYLIB
 	tristate "PHY Device support and infrastructure"
-	depends on NET_ETHERNET && (BROKEN || !ARCH_S390)
+	depends on NET_ETHERNET && (BROKEN || !S390)
 	help
 	  Ethernet controllers are usually attached to PHY
 	  devices.  This option provides infrastructure for
diff --git a/drivers/net/plip.c b/drivers/net/plip.c
index 1bd22cd40c75..87ee3271b17d 100644
--- a/drivers/net/plip.c
+++ b/drivers/net/plip.c
@@ -98,7 +98,6 @@ static const char version[] = "NET3 PLIP version 2.4-parport gniibe@mri.co.jp\n"
 #include <linux/in.h>
 #include <linux/errno.h>
 #include <linux/delay.h>
-#include <linux/lp.h>
 #include <linux/init.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -106,7 +105,6 @@ static const char version[] = "NET3 PLIP version 2.4-parport gniibe@mri.co.jp\n"
 #include <linux/skbuff.h>
 #include <linux/if_plip.h>
 #include <linux/workqueue.h>
-#include <linux/ioport.h>
 #include <linux/spinlock.h>
 #include <linux/parport.h>
 #include <linux/bitops.h>
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c
index a842ecc60a34..9369f811075d 100644
--- a/drivers/net/pppoe.c
+++ b/drivers/net/pppoe.c
@@ -85,7 +85,7 @@ static int pppoe_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 static int pppoe_xmit(struct ppp_channel *chan, struct sk_buff *skb);
 static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb);
 
-static struct proto_ops pppoe_ops;
+static const struct proto_ops pppoe_ops;
 static DEFINE_RWLOCK(pppoe_hash_lock);
 
 static struct ppp_channel_ops pppoe_chan_ops;
@@ -383,8 +383,6 @@ static int pppoe_rcv(struct sk_buff *skb,
 {
 	struct pppoe_hdr *ph;
 	struct pppox_sock *po;
-	struct sock *sk;
-	int ret;
 
 	if (!pskb_may_pull(skb, sizeof(struct pppoe_hdr)))
 		goto drop;
@@ -395,24 +393,8 @@ static int pppoe_rcv(struct sk_buff *skb,
 	ph = (struct pppoe_hdr *) skb->nh.raw;
 
 	po = get_item((unsigned long) ph->sid, eth_hdr(skb)->h_source);
-	if (!po) 
-		goto drop;
-
-	sk = sk_pppox(po);
-	bh_lock_sock(sk);
-
-	/* Socket state is unknown, must put skb into backlog. */
-	if (sock_owned_by_user(sk) != 0) {
-		sk_add_backlog(sk, skb);
-		ret = NET_RX_SUCCESS;
-	} else {
-		ret = pppoe_rcv_core(sk, skb);
-	}
-
-	bh_unlock_sock(sk);
-	sock_put(sk);
-
-	return ret;
+	if (po != NULL) 
+		return sk_receive_skb(sk_pppox(po), skb);
 drop:
 	kfree_skb(skb);
 out:
@@ -1081,9 +1063,7 @@ static int __init pppoe_proc_init(void)
 static inline int pppoe_proc_init(void) { return 0; }
 #endif /* CONFIG_PROC_FS */
 
-/* ->ioctl are set at pppox_create */
-
-static struct proto_ops pppoe_ops = {
+static const struct proto_ops pppoe_ops = {
     .family		= AF_PPPOX,
     .owner		= THIS_MODULE,
     .release		= pppoe_release,
@@ -1099,7 +1079,8 @@ static struct proto_ops pppoe_ops = {
     .getsockopt		= sock_no_getsockopt,
     .sendmsg		= pppoe_sendmsg,
     .recvmsg		= pppoe_recvmsg,
-    .mmap		= sock_no_mmap
+    .mmap		= sock_no_mmap,
+    .ioctl		= pppox_ioctl,
 };
 
 static struct pppox_proto pppoe_proto = {
diff --git a/drivers/net/pppox.c b/drivers/net/pppox.c
index 0c1e114527fb..9315046b3f55 100644
--- a/drivers/net/pppox.c
+++ b/drivers/net/pppox.c
@@ -68,8 +68,7 @@ EXPORT_SYMBOL(register_pppox_proto);
 EXPORT_SYMBOL(unregister_pppox_proto);
 EXPORT_SYMBOL(pppox_unbind_sock);
 
-static int pppox_ioctl(struct socket* sock, unsigned int cmd, 
-		       unsigned long arg)
+int pppox_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 {
 	struct sock *sk = sock->sk;
 	struct pppox_sock *po = pppox_sk(sk);
@@ -105,6 +104,7 @@ static int pppox_ioctl(struct socket* sock, unsigned int cmd,
 	return rc;
 }
 
+EXPORT_SYMBOL(pppox_ioctl);
 
 static int pppox_create(struct socket *sock, int protocol)
 {
@@ -119,11 +119,7 @@ static int pppox_create(struct socket *sock, int protocol)
 		goto out;
 
 	rc = pppox_protos[protocol]->create(sock);
-	if (!rc) {
-		/* We get to set the ioctl handler. */
-		/* For everything else, pppox is just a shell. */
-		sock->ops->ioctl = pppox_ioctl;
-	}
+
 	module_put(pppox_protos[protocol]->owner);
 out:
 	return rc;
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index 669dd52c412a..89c46787676c 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -66,7 +66,7 @@
 #include "s2io.h"
 #include "s2io-regs.h"
 
-#define DRV_VERSION "Version 2.0.9.3"
+#define DRV_VERSION "Version 2.0.9.4"
 
 /* S2io Driver name & version. */
 static char s2io_driver_name[] = "Neterion";
@@ -412,7 +412,7 @@ static int init_shared_mem(struct s2io_nic *nic)
 		    config->tx_cfg[i].fifo_len - 1;
 		mac_control->fifos[i].fifo_no = i;
 		mac_control->fifos[i].nic = nic;
-		mac_control->fifos[i].max_txds = MAX_SKB_FRAGS + 1;
+		mac_control->fifos[i].max_txds = MAX_SKB_FRAGS + 2;
 
 		for (j = 0; j < page_num; j++) {
 			int k = 0;
@@ -459,6 +459,10 @@ static int init_shared_mem(struct s2io_nic *nic)
 		}
 	}
 
+	nic->ufo_in_band_v = kmalloc((sizeof(u64) * size), GFP_KERNEL);
+	if (!nic->ufo_in_band_v)
+		return -ENOMEM;
+
 	/* Allocation and initialization of RXDs in Rings */
 	size = 0;
 	for (i = 0; i < config->rx_ring_num; i++) {
@@ -731,6 +735,8 @@ static void free_shared_mem(struct s2io_nic *nic)
 				    mac_control->stats_mem,
 				    mac_control->stats_mem_phy);
 	}
+	if (nic->ufo_in_band_v)
+		kfree(nic->ufo_in_band_v);
 }
 
 /**
@@ -2003,6 +2009,49 @@ static int start_nic(struct s2io_nic *nic)
 
 	return SUCCESS;
 }
+/**
+ * s2io_txdl_getskb - Get the skb from txdl, unmap and return skb
+ */
+static struct sk_buff *s2io_txdl_getskb(fifo_info_t *fifo_data, TxD_t *txdlp, int get_off)
+{
+	nic_t *nic = fifo_data->nic;
+	struct sk_buff *skb;
+	TxD_t *txds;
+	u16 j, frg_cnt;
+
+	txds = txdlp;
+	if (txds->Host_Control == (u64)(long)nic->ufo_in_band_v) {
+		pci_unmap_single(nic->pdev, (dma_addr_t)
+			txds->Buffer_Pointer, sizeof(u64),
+			PCI_DMA_TODEVICE);
+		txds++;
+	}
+
+	skb = (struct sk_buff *) ((unsigned long)
+			txds->Host_Control);
+	if (!skb) {
+		memset(txdlp, 0, (sizeof(TxD_t) * fifo_data->max_txds));
+		return NULL;
+	}
+	pci_unmap_single(nic->pdev, (dma_addr_t)
+			 txds->Buffer_Pointer,
+			 skb->len - skb->data_len,
+			 PCI_DMA_TODEVICE);
+	frg_cnt = skb_shinfo(skb)->nr_frags;
+	if (frg_cnt) {
+		txds++;
+		for (j = 0; j < frg_cnt; j++, txds++) {
+			skb_frag_t *frag = &skb_shinfo(skb)->frags[j];
+			if (!txds->Buffer_Pointer)
+				break;
+			pci_unmap_page(nic->pdev, (dma_addr_t) 
+					txds->Buffer_Pointer,
+				       frag->size, PCI_DMA_TODEVICE);
+		}
+	}
+	txdlp->Host_Control = 0;
+	return(skb);
+}
 
 /**
  *  free_tx_buffers - Free all queued Tx buffers
@@ -2020,7 +2069,7 @@ static void free_tx_buffers(struct s2io_nic *nic)
 	int i, j;
 	mac_info_t *mac_control;
 	struct config_param *config;
-	int cnt = 0, frg_cnt;
+	int cnt = 0;
 
 	mac_control = &nic->mac_control;
 	config = &nic->config;
@@ -2029,38 +2078,11 @@ static void free_tx_buffers(struct s2io_nic *nic)
 		for (j = 0; j < config->tx_cfg[i].fifo_len - 1; j++) {
 			txdp = (TxD_t *) mac_control->fifos[i].list_info[j].
 			    list_virt_addr;
-			skb =
-			    (struct sk_buff *) ((unsigned long) txdp->
-						Host_Control);
-			if (skb == NULL) {
-				memset(txdp, 0, sizeof(TxD_t) *
-				       config->max_txds);
-				continue;
-			}
-			frg_cnt = skb_shinfo(skb)->nr_frags;
-			pci_unmap_single(nic->pdev, (dma_addr_t)
-					 txdp->Buffer_Pointer,
-					 skb->len - skb->data_len,
-					 PCI_DMA_TODEVICE);
-			if (frg_cnt) {
-				TxD_t *temp;
-				temp = txdp;
-				txdp++;
-				for (j = 0; j < frg_cnt; j++, txdp++) {
-					skb_frag_t *frag =
-					    &skb_shinfo(skb)->frags[j];
-					pci_unmap_page(nic->pdev,
-						       (dma_addr_t)
-						       txdp->
-						       Buffer_Pointer,
-						       frag->size,
-						       PCI_DMA_TODEVICE);
-				}
-				txdp = temp;
+			skb = s2io_txdl_getskb(&mac_control->fifos[i], txdp, j);
+			if (skb) {
+				dev_kfree_skb(skb);
+				cnt++;
 			}
-			dev_kfree_skb(skb);
-			memset(txdp, 0, sizeof(TxD_t) * config->max_txds);
-			cnt++;
 		}
 		DBG_PRINT(INTR_DBG,
 			  "%s:forcibly freeing %d skbs on FIFO%d\n",
@@ -2661,7 +2683,6 @@ static void tx_intr_handler(fifo_info_t *fifo_data)
 	tx_curr_get_info_t get_info, put_info;
 	struct sk_buff *skb;
 	TxD_t *txdlp;
-	u16 j, frg_cnt;
 
 	get_info = fifo_data->tx_curr_get_info;
 	put_info = fifo_data->tx_curr_put_info;
@@ -2684,8 +2705,7 @@ to loss of link\n");
 			}
 		}
 
-		skb = (struct sk_buff *) ((unsigned long)
-				txdlp->Host_Control);
+		skb = s2io_txdl_getskb(fifo_data, txdlp, get_info.offset);
 		if (skb == NULL) {
 			DBG_PRINT(ERR_DBG, "%s: Null skb ",
 			__FUNCTION__);
@@ -2693,34 +2713,6 @@ to loss of link\n");
 			return;
 		}
 
-		frg_cnt = skb_shinfo(skb)->nr_frags;
-		nic->tx_pkt_count++;
-
-		pci_unmap_single(nic->pdev, (dma_addr_t)
-				 txdlp->Buffer_Pointer,
-				 skb->len - skb->data_len,
-				 PCI_DMA_TODEVICE);
-		if (frg_cnt) {
-			TxD_t *temp;
-			temp = txdlp;
-			txdlp++;
-			for (j = 0; j < frg_cnt; j++, txdlp++) {
-				skb_frag_t *frag =
-				    &skb_shinfo(skb)->frags[j];
-				if (!txdlp->Buffer_Pointer)
-					break;
-				pci_unmap_page(nic->pdev,
-					       (dma_addr_t)
-					       txdlp->
-					       Buffer_Pointer,
-					       frag->size,
-					       PCI_DMA_TODEVICE);
-			}
-			txdlp = temp;
-		}
-		memset(txdlp, 0,
-		       (sizeof(TxD_t) * fifo_data->max_txds));
-
 		/* Updating the statistics block */
 		nic->stats.tx_bytes += skb->len;
 		dev_kfree_skb_irq(skb);
@@ -3331,7 +3323,7 @@ failed\n", dev->name);
 					  s2io_msix_fifo_handle, 0, sp->desc1,
 					  sp->s2io_entries[i].arg);
 				DBG_PRINT(ERR_DBG, "%s @ 0x%llx\n", sp->desc1, 
-							sp->msix_info[i].addr);
+				    (unsigned long long)sp->msix_info[i].addr);
 			} else {
 				sprintf(sp->desc2, "%s:MSI-X-%d-RX",
 					dev->name, i);
@@ -3339,7 +3331,7 @@ failed\n", dev->name);
 					  s2io_msix_ring_handle, 0, sp->desc2,
 					  sp->s2io_entries[i].arg);
 				DBG_PRINT(ERR_DBG, "%s @ 0x%llx\n", sp->desc2, 
-							sp->msix_info[i].addr);
+				     (unsigned long long)sp->msix_info[i].addr);
 			}
 			if (err) {
 				DBG_PRINT(ERR_DBG, "%s: MSI-X-%d registration \
@@ -3527,6 +3519,8 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
 		return 0;
 	}
 
+	txdp->Control_1 = 0;
+	txdp->Control_2 = 0;
 #ifdef NETIF_F_TSO
 	mss = skb_shinfo(skb)->tso_size;
 	if (mss) {
@@ -3534,19 +3528,13 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
 		txdp->Control_1 |= TXD_TCP_LSO_MSS(mss);
 	}
 #endif
-
-	frg_cnt = skb_shinfo(skb)->nr_frags;
-	frg_len = skb->len - skb->data_len;
-
-	txdp->Buffer_Pointer = pci_map_single
-	    (sp->pdev, skb->data, frg_len, PCI_DMA_TODEVICE);
-	txdp->Host_Control = (unsigned long) skb;
 	if (skb->ip_summed == CHECKSUM_HW) {
 		txdp->Control_2 |=
 		    (TXD_TX_CKO_IPV4_EN | TXD_TX_CKO_TCP_EN |
 		     TXD_TX_CKO_UDP_EN);
 	}
-
+	txdp->Control_1 |= TXD_GATHER_CODE_FIRST;
+	txdp->Control_1 |= TXD_LIST_OWN_XENA;
 	txdp->Control_2 |= config->tx_intr_type;
 
 	if (sp->vlgrp && vlan_tx_tag_present(skb)) {
@@ -3554,10 +3542,40 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
 		txdp->Control_2 |= TXD_VLAN_TAG(vlan_tag);
 	}
 
-	txdp->Control_1 |= (TXD_BUFFER0_SIZE(frg_len) |
-			    TXD_GATHER_CODE_FIRST);
-	txdp->Control_1 |= TXD_LIST_OWN_XENA;
+	frg_len = skb->len - skb->data_len;
+	if (skb_shinfo(skb)->ufo_size) {
+		int ufo_size;
+
+		ufo_size = skb_shinfo(skb)->ufo_size;
+		ufo_size &= ~7;
+		txdp->Control_1 |= TXD_UFO_EN;
+		txdp->Control_1 |= TXD_UFO_MSS(ufo_size);
+		txdp->Control_1 |= TXD_BUFFER0_SIZE(8);
+#ifdef __BIG_ENDIAN
+		sp->ufo_in_band_v[put_off] =
+				(u64)skb_shinfo(skb)->ip6_frag_id;
+#else
+		sp->ufo_in_band_v[put_off] =
+				(u64)skb_shinfo(skb)->ip6_frag_id << 32;
+#endif
+		txdp->Host_Control = (unsigned long)sp->ufo_in_band_v;
+		txdp->Buffer_Pointer = pci_map_single(sp->pdev,
+					sp->ufo_in_band_v,
+					sizeof(u64), PCI_DMA_TODEVICE);
+		txdp++;
+		txdp->Control_1 = 0;
+		txdp->Control_2 = 0;
+	}
+
+	txdp->Buffer_Pointer = pci_map_single
+	    (sp->pdev, skb->data, frg_len, PCI_DMA_TODEVICE);
+	txdp->Host_Control = (unsigned long) skb;
+	txdp->Control_1 |= TXD_BUFFER0_SIZE(frg_len);
 
+	if (skb_shinfo(skb)->ufo_size)
+		txdp->Control_1 |= TXD_UFO_EN;
+
+	frg_cnt = skb_shinfo(skb)->nr_frags;
 	/* For fragmented SKB. */
 	for (i = 0; i < frg_cnt; i++) {
 		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
@@ -3569,9 +3587,14 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
 		    (sp->pdev, frag->page, frag->page_offset,
 		     frag->size, PCI_DMA_TODEVICE);
 		txdp->Control_1 |= TXD_BUFFER0_SIZE(frag->size);
+		if (skb_shinfo(skb)->ufo_size)
+			txdp->Control_1 |= TXD_UFO_EN;
 	}
 	txdp->Control_1 |= TXD_GATHER_CODE_LAST;
 
+	if (skb_shinfo(skb)->ufo_size)
+		frg_cnt++; /* as Txd0 was used for inband header */
+
 	tx_fifo = mac_control->tx_FIFO_start[queue];
 	val64 = mac_control->fifos[queue].list_info[put_off].list_phy_addr;
 	writeq(val64, &tx_fifo->TxDL_Pointer);
@@ -3583,6 +3606,8 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
 	if (mss)
 		val64 |= TX_FIFO_SPECIAL_FUNC;
 #endif
+	if (skb_shinfo(skb)->ufo_size)
+		val64 |= TX_FIFO_SPECIAL_FUNC;
 	writeq(val64, &tx_fifo->List_Control);
 
 	mmiowb();
@@ -4721,7 +4746,10 @@ static int s2io_eeprom_test(nic_t * sp, uint64_t * data)
 		fail = 1;
 
 	if (ret_data != 0x012345) {
-		DBG_PRINT(ERR_DBG, "%s: eeprom test error at offset 0x4F0. Data written %llx Data read %llx\n", dev->name, (u64)0x12345, ret_data); 
+		DBG_PRINT(ERR_DBG, "%s: eeprom test error at offset 0x4F0. "
+			"Data written %llx Data read %llx\n",
+			dev->name, (unsigned long long)0x12345,
+			(unsigned long long)ret_data);
 		fail = 1;
 	}
 
@@ -4740,7 +4768,10 @@ static int s2io_eeprom_test(nic_t * sp, uint64_t * data)
 		fail = 1;
 
 	if (ret_data != 0x012345) {
-		DBG_PRINT(ERR_DBG, "%s: eeprom test error at offset 0x7F0. Data written %llx Data read %llx\n", dev->name, (u64)0x12345, ret_data); 
+		DBG_PRINT(ERR_DBG, "%s: eeprom test error at offset 0x7F0. "
+			"Data written %llx Data read %llx\n",
+			dev->name, (unsigned long long)0x12345,
+			(unsigned long long)ret_data);
 		fail = 1;
 	}
 
@@ -5190,6 +5221,8 @@ static struct ethtool_ops netdev_ethtool_ops = {
 	.get_tso = ethtool_op_get_tso,
 	.set_tso = ethtool_op_set_tso,
 #endif
+	.get_ufo = ethtool_op_get_ufo,
+	.set_ufo = ethtool_op_set_ufo,
 	.self_test_count = s2io_ethtool_self_test_count,
 	.self_test = s2io_ethtool_test,
 	.get_strings = s2io_ethtool_get_strings,
@@ -5941,7 +5974,8 @@ Defaulting to INTA\n");
 			break;
 		}
 	}
-	config->max_txds = MAX_SKB_FRAGS + 1;
+	/* + 2 because one Txd for skb->data and one Txd for UFO */
+	config->max_txds = MAX_SKB_FRAGS + 2;
 
 	/* Rx side parameters. */
 	if (rx_ring_sz[0] == 0)
@@ -6035,6 +6069,10 @@ Defaulting to INTA\n");
 #ifdef NETIF_F_TSO
 	dev->features |= NETIF_F_TSO;
 #endif
+	if (sp->device_type & XFRAME_II_DEVICE) {
+		dev->features |= NETIF_F_UFO;
+		dev->features |= NETIF_F_HW_CSUM;
+	}
 
 	dev->tx_timeout = &s2io_tx_watchdog;
 	dev->watchdog_timeo = WATCH_DOG_TIMEOUT;
diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h
index 419aad7f10e7..852a6a899d07 100644
--- a/drivers/net/s2io.h
+++ b/drivers/net/s2io.h
@@ -393,7 +393,9 @@ typedef struct _TxD {
 #define TXD_GATHER_CODE_LAST    BIT(23)
 #define TXD_TCP_LSO_EN          BIT(30)
 #define TXD_UDP_COF_EN          BIT(31)
+#define TXD_UFO_EN		BIT(31) | BIT(30)
 #define TXD_TCP_LSO_MSS(val)    vBIT(val,34,14)
+#define TXD_UFO_MSS(val)	vBIT(val,34,14)
 #define TXD_BUFFER0_SIZE(val)   vBIT(val,48,16)
 
 	u64 Control_2;
@@ -789,6 +791,7 @@ struct s2io_nic {
 
 	spinlock_t	rx_lock;
 	atomic_t	isr_cnt;
+	u64 *ufo_in_band_v;
 };
 
 #define RESET_ERROR 1;
diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c
index 1d4d88680db1..3d95fa20cd88 100644
--- a/drivers/net/sis900.c
+++ b/drivers/net/sis900.c
@@ -1,6 +1,6 @@
 /* sis900.c: A SiS 900/7016 PCI Fast Ethernet driver for Linux.
    Copyright 1999 Silicon Integrated System Corporation 
-   Revision:	1.08.08 Jan. 22 2005
+   Revision:	1.08.09 Sep. 19 2005
    
    Modified from the driver which is originally written by Donald Becker.
    
@@ -17,6 +17,7 @@
    SiS 7014 Single Chip 100BASE-TX/10BASE-T Physical Layer Solution,
    preliminary Rev. 1.0 Jan. 18, 1998
 
+   Rev 1.08.09 Sep. 19 2005 Daniele Venzano add Wake on LAN support
    Rev 1.08.08 Jan. 22 2005 Daniele Venzano use netif_msg for debugging messages
    Rev 1.08.07 Nov.  2 2003 Daniele Venzano <webvenza@libero.it> add suspend/resume support
    Rev 1.08.06 Sep. 24 2002 Mufasa Yang bug fix for Tx timeout & add SiS963 support
@@ -76,7 +77,7 @@
 #include "sis900.h"
 
 #define SIS900_MODULE_NAME "sis900"
-#define SIS900_DRV_VERSION "v1.08.08 Jan. 22 2005"
+#define SIS900_DRV_VERSION "v1.08.09 Sep. 19 2005"
 
 static char version[] __devinitdata =
 KERN_INFO "sis900.c: " SIS900_DRV_VERSION "\n";
@@ -538,6 +539,11 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev,
 		printk("%2.2x:", (u8)net_dev->dev_addr[i]);
 	printk("%2.2x.\n", net_dev->dev_addr[i]);
 
+	/* Detect Wake on Lan support */
+	ret = inl(CFGPMC & PMESP);
+	if (netif_msg_probe(sis_priv) && (ret & PME_D3C) == 0)
+		printk(KERN_INFO "%s: Wake on LAN only available from suspend to RAM.", net_dev->name);
+
 	return 0;
 
  err_unmap_rx:
@@ -2015,6 +2021,67 @@ static int sis900_nway_reset(struct net_device *net_dev)
 	return mii_nway_restart(&sis_priv->mii_info);
 }
 
+/**
+ *	sis900_set_wol - Set up Wake on Lan registers
+ *	@net_dev: the net device to probe
+ *	@wol: container for info passed to the driver
+ *
+ *	Process ethtool command "wol" to setup wake on lan features.
+ *	SiS900 supports sending WoL events if a correct packet is received,
+ *	but there is no simple way to filter them to only a subset (broadcast,
+ *	multicast, unicast or arp).
+ */
+ 
+static int sis900_set_wol(struct net_device *net_dev, struct ethtool_wolinfo *wol)
+{
+	struct sis900_private *sis_priv = net_dev->priv;
+	long pmctrl_addr = net_dev->base_addr + pmctrl;
+	u32 cfgpmcsr = 0, pmctrl_bits = 0;
+
+	if (wol->wolopts == 0) {
+		pci_read_config_dword(sis_priv->pci_dev, CFGPMCSR, &cfgpmcsr);
+		cfgpmcsr |= ~PME_EN;
+		pci_write_config_dword(sis_priv->pci_dev, CFGPMCSR, cfgpmcsr);
+		outl(pmctrl_bits, pmctrl_addr);
+		if (netif_msg_wol(sis_priv))
+			printk(KERN_DEBUG "%s: Wake on LAN disabled\n", net_dev->name);
+		return 0;
+	}
+
+	if (wol->wolopts & (WAKE_MAGICSECURE | WAKE_UCAST | WAKE_MCAST
+				| WAKE_BCAST | WAKE_ARP))
+		return -EINVAL;
+
+	if (wol->wolopts & WAKE_MAGIC)
+		pmctrl_bits |= MAGICPKT;
+	if (wol->wolopts & WAKE_PHY)
+		pmctrl_bits |= LINKON;
+	
+	outl(pmctrl_bits, pmctrl_addr);
+
+	pci_read_config_dword(sis_priv->pci_dev, CFGPMCSR, &cfgpmcsr);
+	cfgpmcsr |= PME_EN;
+	pci_write_config_dword(sis_priv->pci_dev, CFGPMCSR, cfgpmcsr);
+	if (netif_msg_wol(sis_priv))
+		printk(KERN_DEBUG "%s: Wake on LAN enabled\n", net_dev->name);
+
+	return 0;
+}
+
+static void sis900_get_wol(struct net_device *net_dev, struct ethtool_wolinfo *wol)
+{
+	long pmctrl_addr = net_dev->base_addr + pmctrl;
+	u32 pmctrl_bits;
+
+	pmctrl_bits = inl(pmctrl_addr);
+	if (pmctrl_bits & MAGICPKT)
+		wol->wolopts |= WAKE_MAGIC;
+	if (pmctrl_bits & LINKON)
+		wol->wolopts |= WAKE_PHY;
+
+	wol->supported = (WAKE_PHY | WAKE_MAGIC);
+}
+
 static struct ethtool_ops sis900_ethtool_ops = {
 	.get_drvinfo 	= sis900_get_drvinfo,
 	.get_msglevel	= sis900_get_msglevel,
@@ -2023,6 +2090,8 @@ static struct ethtool_ops sis900_ethtool_ops = {
 	.get_settings	= sis900_get_settings,
 	.set_settings	= sis900_set_settings,
 	.nway_reset	= sis900_nway_reset,
+	.get_wol	= sis900_get_wol,
+	.set_wol	= sis900_set_wol
 };
 
 /**
diff --git a/drivers/net/sis900.h b/drivers/net/sis900.h
index de3c06735d15..4233ea55670f 100644
--- a/drivers/net/sis900.h
+++ b/drivers/net/sis900.h
@@ -33,6 +33,7 @@ enum sis900_registers {
         rxcfg=0x34,             //Receive Configuration Register
         flctrl=0x38,            //Flow Control Register
         rxlen=0x3c,             //Receive Packet Length Register
+        cfgpmcsr=0x44,          //Configuration Power Management Control/Status Register
         rfcr=0x48,              //Receive Filter Control Register
         rfdr=0x4C,              //Receive Filter Data Register
         pmctrl=0xB0,            //Power Management Control Register
@@ -140,6 +141,50 @@ enum sis96x_eeprom_command {
 	EEREQ = 0x00000400, EEDONE = 0x00000200, EEGNT = 0x00000100
 };
 
+/* PCI Registers */
+enum sis900_pci_registers {
+	CFGPMC 	 = 0x40,
+	CFGPMCSR = 0x44
+};
+
+/* Power management capabilities bits */
+enum sis900_cfgpmc_register_bits {
+	PMVER	= 0x00070000, 
+	DSI	= 0x00100000,
+	PMESP	= 0xf8000000
+};
+
+enum sis900_pmesp_bits {
+	PME_D0 = 0x1,
+	PME_D1 = 0x2,
+	PME_D2 = 0x4,
+	PME_D3H = 0x8,
+	PME_D3C = 0x10
+};
+
+/* Power management control/status bits */
+enum sis900_cfgpmcsr_register_bits {
+	PMESTS = 0x00004000,
+	PME_EN = 0x00000100, // Power management enable
+	PWR_STA = 0x00000003 // Current power state
+};
+
+/* Wake-on-LAN support. */
+enum sis900_power_management_control_register_bits {
+	LINKLOSS  = 0x00000001,
+	LINKON    = 0x00000002,
+	MAGICPKT  = 0x00000400,
+	ALGORITHM = 0x00000800,
+	FRM1EN    = 0x00100000,
+	FRM2EN    = 0x00200000,
+	FRM3EN    = 0x00400000,
+	FRM1ACS   = 0x01000000,
+	FRM2ACS   = 0x02000000,
+	FRM3ACS   = 0x04000000,
+	WAKEALL   = 0x40000000,
+	GATECLK   = 0x80000000
+};
+
 /* Management Data I/O (mdio) frame */
 #define MIIread         0x6000
 #define MIIwrite        0x5002
diff --git a/drivers/net/sk98lin/Makefile b/drivers/net/sk98lin/Makefile
index 7653d6e33aa2..afd900d5d730 100644
--- a/drivers/net/sk98lin/Makefile
+++ b/drivers/net/sk98lin/Makefile
@@ -26,8 +26,7 @@ sk98lin-objs    :=	\
 		skrlmt.o	\
 		sktimer.o	\
 		skvpd.o		\
-		skxmac2.o	\
-		skproc.o
+		skxmac2.o
 
 # DBGDEF =  \
 # -DDEBUG
diff --git a/drivers/net/sk98lin/h/skdrv2nd.h b/drivers/net/sk98lin/h/skdrv2nd.h
index 2dc5728e3ef6..778d9e618ebd 100644
--- a/drivers/net/sk98lin/h/skdrv2nd.h
+++ b/drivers/net/sk98lin/h/skdrv2nd.h
@@ -60,7 +60,6 @@ extern SK_U64		SkOsGetTime(SK_AC*);
 extern int		SkPciReadCfgDWord(SK_AC*, int, SK_U32*);
 extern int		SkPciReadCfgWord(SK_AC*, int, SK_U16*);
 extern int		SkPciReadCfgByte(SK_AC*, int, SK_U8*);
-extern int		SkPciWriteCfgDWord(SK_AC*, int, SK_U32);
 extern int		SkPciWriteCfgWord(SK_AC*, int, SK_U16);
 extern int		SkPciWriteCfgByte(SK_AC*, int, SK_U8);
 extern int		SkDrvEvent(SK_AC*, SK_IOC IoC, SK_U32, SK_EVPARA);
@@ -268,8 +267,6 @@ typedef struct s_DevNet DEV_NET;
 struct s_DevNet {
 	int             PortNr;
 	int             NetNr;
-	int             Mtu;
-	int             Up;
 	SK_AC   *pAC;
 };  
 
@@ -298,6 +295,7 @@ struct s_RxPort {
 	RXD		*pRxdRingTail;	/* Tail of Rx rings */
 	RXD		*pRxdRingPrev;	/* descriptor given to BMU previously */
 	int		RxdRingFree;	/* # of free entrys */
+	int		RxCsum;		/* use receive checksum hardware */
 	spinlock_t	RxDesRingLock;	/* serialize descriptor accesses */
 	int		RxFillLimit;	/* limit for buffers in ring */
 	SK_IOC		HwAddr;		/* bmu registers address */
@@ -390,12 +388,10 @@ struct s_AC  {
 	
 	SK_IOC		IoBase;		/* register set of adapter */
 	int		BoardLevel;	/* level of active hw init (0-2) */
-	char		DeviceStr[80];	/* adapter string from vpd */
+
 	SK_U32		AllocFlag;	/* flag allocation of resources */
 	struct pci_dev	*PciDev;	/* for access to pci config space */
-	SK_U32		PciDevId;	/* pci device id */
 	struct SK_NET_DEVICE	*dev[2];	/* pointer to device struct */
-	char		Name[30];	/* driver name */
 
 	int		RxBufSize;	/* length of receive buffers */
         struct net_device_stats stats;	/* linux 'netstat -i' statistics */
@@ -430,7 +426,6 @@ struct s_AC  {
 	DIM_INFO        DynIrqModInfo;  /* all data related to DIM */
 
 	/* Only for tests */
-	int		PortUp;
 	int		PortDown;
 	int		ChipsetType;	/*  Chipset family type 
 					 *  0 == Genesis family support
diff --git a/drivers/net/sk98lin/h/skvpd.h b/drivers/net/sk98lin/h/skvpd.h
index bdc1a5eaaae9..daa9a8d154fc 100644
--- a/drivers/net/sk98lin/h/skvpd.h
+++ b/drivers/net/sk98lin/h/skvpd.h
@@ -130,14 +130,12 @@ typedef	struct s_vpd_key {
 #ifndef VPD_DO_IO
 #define VPD_OUT8(pAC,IoC,Addr,Val)	(void)SkPciWriteCfgByte(pAC,Addr,Val)
 #define VPD_OUT16(pAC,IoC,Addr,Val)	(void)SkPciWriteCfgWord(pAC,Addr,Val)
-#define VPD_OUT32(pAC,IoC,Addr,Val)	(void)SkPciWriteCfgDWord(pAC,Addr,Val)
 #define VPD_IN8(pAC,IoC,Addr,pVal)	(void)SkPciReadCfgByte(pAC,Addr,pVal)
 #define VPD_IN16(pAC,IoC,Addr,pVal)	(void)SkPciReadCfgWord(pAC,Addr,pVal)
 #define VPD_IN32(pAC,IoC,Addr,pVal)	(void)SkPciReadCfgDWord(pAC,Addr,pVal)
 #else	/* VPD_DO_IO */
 #define VPD_OUT8(pAC,IoC,Addr,Val)	SK_OUT8(IoC,PCI_C(Addr),Val)
 #define VPD_OUT16(pAC,IoC,Addr,Val)	SK_OUT16(IoC,PCI_C(Addr),Val)
-#define VPD_OUT32(pAC,IoC,Addr,Val)	SK_OUT32(IoC,PCI_C(Addr),Val)
 #define VPD_IN8(pAC,IoC,Addr,pVal)	SK_IN8(IoC,PCI_C(Addr),pVal)
 #define VPD_IN16(pAC,IoC,Addr,pVal)	SK_IN16(IoC,PCI_C(Addr),pVal)
 #define VPD_IN32(pAC,IoC,Addr,pVal)	SK_IN32(IoC,PCI_C(Addr),pVal)
@@ -155,12 +153,6 @@ typedef	struct s_vpd_key {
 		else						\
 			SK_OUT16(pAC,PCI_C(Addr),Val);		\
 		}
-#define VPD_OUT32(pAC,Ioc,Addr,Val) {			\
-		if ((pAC)->DgT.DgUseCfgCycle)			\
-			SkPciWriteCfgDWord(pAC,Addr,Val);	\
-		else						\
-			SK_OUT32(pAC,PCI_C(Addr),Val); 		\
-		}
 #define VPD_IN8(pAC,Ioc,Addr,pVal) {			\
 		if ((pAC)->DgT.DgUseCfgCycle) 			\
 			SkPciReadCfgByte(pAC,Addr,pVal);	\
diff --git a/drivers/net/sk98lin/skethtool.c b/drivers/net/sk98lin/skethtool.c
index b71769ae4603..4265ed91a9c4 100644
--- a/drivers/net/sk98lin/skethtool.c
+++ b/drivers/net/sk98lin/skethtool.c
@@ -539,6 +539,48 @@ static int setPauseParams(struct net_device *dev , struct ethtool_pauseparam *ep
         return ret ? -EIO : 0;
 }
 
+/* Only Yukon supports checksum offload. */
+static int setScatterGather(struct net_device *dev, u32 data)
+{
+	DEV_NET *pNet = netdev_priv(dev);
+	SK_AC *pAC = pNet->pAC;
+
+	if (pAC->GIni.GIChipId == CHIP_ID_GENESIS)
+		return -EOPNOTSUPP;
+	return ethtool_op_set_sg(dev, data);
+}
+
+static int setTxCsum(struct net_device *dev, u32 data)
+{
+	DEV_NET *pNet = netdev_priv(dev);
+	SK_AC *pAC = pNet->pAC;
+
+	if (pAC->GIni.GIChipId == CHIP_ID_GENESIS)
+		return -EOPNOTSUPP;
+
+	return ethtool_op_set_tx_csum(dev, data);
+}
+
+static u32 getRxCsum(struct net_device *dev)
+{
+	DEV_NET *pNet = netdev_priv(dev);
+	SK_AC *pAC = pNet->pAC;
+
+	return pAC->RxPort[pNet->PortNr].RxCsum;
+}
+
+static int setRxCsum(struct net_device *dev, u32 data)
+{
+	DEV_NET *pNet = netdev_priv(dev);
+	SK_AC *pAC = pNet->pAC;
+
+	if (pAC->GIni.GIChipId == CHIP_ID_GENESIS)
+		return -EOPNOTSUPP;
+
+	pAC->RxPort[pNet->PortNr].RxCsum = data != 0;
+	return 0;
+}
+
 struct ethtool_ops SkGeEthtoolOps = {
 	.get_settings		= getSettings,
 	.set_settings		= setSettings,
@@ -551,4 +593,10 @@ struct ethtool_ops SkGeEthtoolOps = {
 	.set_pauseparam		= setPauseParams,
 	.get_link		= ethtool_op_get_link,
 	.get_perm_addr		= ethtool_op_get_perm_addr,
+	.get_sg			= ethtool_op_get_sg,
+	.set_sg			= setScatterGather,
+	.get_tx_csum		= ethtool_op_get_tx_csum,
+	.set_tx_csum		= setTxCsum,
+	.get_rx_csum		= getRxCsum,
+	.set_rx_csum		= setRxCsum,
 };
diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c
index ae7343934758..9a76ac180b11 100644
--- a/drivers/net/sk98lin/skge.c
+++ b/drivers/net/sk98lin/skge.c
@@ -107,10 +107,10 @@
 
 #include	"h/skversion.h"
 
+#include	<linux/in.h>
 #include	<linux/module.h>
 #include	<linux/moduleparam.h>
 #include	<linux/init.h>
-#include 	<linux/proc_fs.h>
 #include	<linux/dma-mapping.h>
 #include	<linux/ip.h>
 
@@ -206,7 +206,6 @@ static void	SkGeSetRxMode(struct SK_NET_DEVICE *dev);
 static struct	net_device_stats *SkGeStats(struct SK_NET_DEVICE *dev);
 static int	SkGeIoctl(struct SK_NET_DEVICE *dev, struct ifreq *rq, int cmd);
 static void	GetConfiguration(SK_AC*);
-static void	ProductStr(SK_AC*);
 static int	XmitFrame(SK_AC*, TX_PORT*, struct sk_buff*);
 static void	FreeTxDescriptors(SK_AC*pAC, TX_PORT*);
 static void	FillRxRing(SK_AC*, RX_PORT*);
@@ -235,28 +234,6 @@ static int      SkDrvDeInitAdapter(SK_AC *pAC, int devNbr);
  * Extern Function Prototypes
  *
  ******************************************************************************/
-static const char 	SKRootName[] = "net/sk98lin";
-static struct		proc_dir_entry *pSkRootDir;
-extern struct	file_operations sk_proc_fops;
-
-static inline void SkGeProcCreate(struct net_device *dev)
-{
-	struct proc_dir_entry *pe;
-
-	if (pSkRootDir && 
-	    (pe = create_proc_entry(dev->name, S_IRUGO, pSkRootDir))) {
-		pe->proc_fops = &sk_proc_fops;
-		pe->data = dev;
-		pe->owner = THIS_MODULE;
-	}
-}
- 
-static inline void SkGeProcRemove(struct net_device *dev)
-{
-	if (pSkRootDir)
-		remove_proc_entry(dev->name, pSkRootDir);
-}
-
 extern void SkDimEnableModerationIfNeeded(SK_AC *pAC);	
 extern void SkDimDisplayModerationSettings(SK_AC *pAC);
 extern void SkDimStartModerationTimer(SK_AC *pAC);
@@ -279,6 +256,27 @@ static uintptr_t RxQueueAddr[SK_MAX_MACS] = {0x400, 0x480};
 
 /*****************************************************************************
  *
+ *	SkPciWriteCfgDWord - write a 32 bit value to pci config space
+ *
+ * Description:
+ *	This routine writes a 32 bit value to the pci configuration
+ *	space.
+ *
+ * Returns:
+ *	0 - indicate everything worked ok.
+ *	!= 0 - error indication
+ */
+static inline int SkPciWriteCfgDWord(
+SK_AC *pAC,	/* Adapter Control structure pointer */
+int PciAddr,		/* PCI register address */
+SK_U32 Val)		/* pointer to store the read value */
+{
+	pci_write_config_dword(pAC->PciDev, PciAddr, Val);
+	return(0);
+} /* SkPciWriteCfgDWord */
+
+/*****************************************************************************
+ *
  * 	SkGeInitPCI - Init the PCI resources
  *
  * Description:
@@ -300,7 +298,7 @@ int SkGeInitPCI(SK_AC *pAC)
 	dev->mem_start = pci_resource_start (pdev, 0);
 	pci_set_master(pdev);
 
-	if (pci_request_regions(pdev, pAC->Name) != 0) {
+	if (pci_request_regions(pdev, "sk98lin") != 0) {
 		retval = 2;
 		goto out_disable;
 	}
@@ -578,10 +576,10 @@ SK_BOOL	DualNet;
 	spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
 
 	if (pAC->GIni.GIMacsFound == 2) {
-		 Ret = request_irq(dev->irq, SkGeIsr, SA_SHIRQ, pAC->Name, dev);
+		 Ret = request_irq(dev->irq, SkGeIsr, SA_SHIRQ, "sk98lin", dev);
 	} else if (pAC->GIni.GIMacsFound == 1) {
 		Ret = request_irq(dev->irq, SkGeIsrOnePort, SA_SHIRQ,
-			pAC->Name, dev);
+			"sk98lin", dev);
 	} else {
 		printk(KERN_WARNING "sk98lin: Illegal number of ports: %d\n",
 		       pAC->GIni.GIMacsFound);
@@ -1265,7 +1263,6 @@ struct SK_NET_DEVICE	*dev)
 	spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
 
 	pAC->MaxPorts++;
-	pNet->Up = 1;
 
 
 	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
@@ -1395,7 +1392,6 @@ struct SK_NET_DEVICE	*dev)
 			sizeof(SK_PNMI_STRUCT_DATA));
 
 	pAC->MaxPorts--;
-	pNet->Up = 0;
 
 	return (0);
 } /* SkGeClose */
@@ -2175,7 +2171,6 @@ rx_start:
 		pMsg->ip_summed = CHECKSUM_NONE;
 #endif
 
-
 		SK_DBG_MSG(NULL, SK_DBGMOD_DRV,	1,("V"));
 		ForRlmt = SK_RLMT_RX_PROTOCOL;
 #if 0
@@ -2550,7 +2545,7 @@ unsigned long		Flags;
 static int SkGeChangeMtu(struct SK_NET_DEVICE *dev, int NewMtu)
 {
 DEV_NET		*pNet;
-DEV_NET		*pOtherNet;
+struct net_device *pOtherDev;
 SK_AC		*pAC;
 unsigned long	Flags;
 int		i;
@@ -2580,11 +2575,11 @@ SK_EVPARA 	EvPara;
 	}
 #endif
 
-	pNet->Mtu = NewMtu;
-	pOtherNet = netdev_priv(pAC->dev[1 - pNet->NetNr]);
-	if ((pOtherNet->Mtu>1500) && (NewMtu<=1500) && (pOtherNet->Up==1)) {
-		return(0);
-	}
+	pOtherDev = pAC->dev[1 - pNet->NetNr];
+
+	if ( netif_running(pOtherDev) && (pOtherDev->mtu > 1500)
+	     && (NewMtu <= 1500))
+		return 0;
 
 	pAC->RxBufSize = NewMtu + 32;
 	dev->mtu = NewMtu;
@@ -2746,7 +2741,8 @@ SK_EVPARA 	EvPara;
 		EvPara.Para32[1] = -1;
 		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
 			
-		if (pOtherNet->Up) {
+		if (netif_running(pOtherDev)) {
+			DEV_NET *pOtherNet = netdev_priv(pOtherDev);
 			EvPara.Para32[0] = pOtherNet->PortNr;
 			SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
 		}
@@ -2820,7 +2816,7 @@ unsigned long	Flags;			/* for spin lock */
 	pAC->stats.rx_bytes = (SK_U32) pPnmiStruct->RxOctetsDeliveredCts;
 	pAC->stats.tx_bytes = (SK_U32) pPnmiStat->StatTxOctetsOkCts;
 	
-        if (pNet->Mtu <= 1500) {
+        if (dev->mtu <= 1500) {
                 pAC->stats.rx_errors = (SK_U32) pPnmiStruct->InErrorsCts & 0xFFFFFFFF;
         } else {
                 pAC->stats.rx_errors = (SK_U32) ((pPnmiStruct->InErrorsCts -
@@ -3771,25 +3767,21 @@ int	Capabilities[3][3] =
  *
  * Returns: N/A
  */
-static void ProductStr(
-SK_AC	*pAC		/* pointer to adapter context */
+static inline int ProductStr(
+	SK_AC	*pAC,		/* pointer to adapter context */
+	char    *DeviceStr,	/* result string */
+	int      StrLen		/* length of the string */
 )
 {
-int	StrLen = 80;		/* length of the string, defined in SK_AC */
 char	Keyword[] = VPD_NAME;	/* vpd productname identifier */
 int	ReturnCode;		/* return code from vpd_read */
 unsigned long Flags;
 
 	spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-	ReturnCode = VpdRead(pAC, pAC->IoBase, Keyword, pAC->DeviceStr,
-		&StrLen);
+	ReturnCode = VpdRead(pAC, pAC->IoBase, Keyword, DeviceStr, &StrLen);
 	spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-	if (ReturnCode != 0) {
-		/* there was an error reading the vpd data */
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ERROR,
-			("Error reading VPD data: %d\n", ReturnCode));
-		pAC->DeviceStr[0] = '\0';
-	}
+
+	return ReturnCode;
 } /* ProductStr */
 
 /*****************************************************************************
@@ -3992,28 +3984,6 @@ SK_U8 *pVal)		/* pointer to store the read value */
 
 /*****************************************************************************
  *
- *	SkPciWriteCfgDWord - write a 32 bit value to pci config space
- *
- * Description:
- *	This routine writes a 32 bit value to the pci configuration
- *	space.
- *
- * Returns:
- *	0 - indicate everything worked ok.
- *	!= 0 - error indication
- */
-int SkPciWriteCfgDWord(
-SK_AC *pAC,	/* Adapter Control structure pointer */
-int PciAddr,		/* PCI register address */
-SK_U32 Val)		/* pointer to store the read value */
-{
-	pci_write_config_dword(pAC->PciDev, PciAddr, Val);
-	return(0);
-} /* SkPciWriteCfgDWord */
-
-
-/*****************************************************************************
- *
  *	SkPciWriteCfgWord - write a 16 bit value to pci config space
  *
  * Description:
@@ -4150,6 +4120,7 @@ SK_BOOL		DualNet;
 			Flags);
 		break;
 	case SK_DRV_NET_UP:	 /* SK_U32 PortIdx */
+	{	struct net_device *dev = pAC->dev[Param.Para32[0]];
 		/* action list 5 */
 		FromPort = Param.Para32[0];
 		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
@@ -4233,22 +4204,12 @@ SK_BOOL		DualNet;
 			printk("    irq moderation:  disabled\n");
 
 
-#ifdef SK_ZEROCOPY
-		if (pAC->ChipsetType)
-#ifdef USE_SK_TX_CHECKSUM
-			printk("    scatter-gather:  enabled\n");
-#else
-			printk("    tx-checksum:     disabled\n");
-#endif
-		else
-			printk("    scatter-gather:  disabled\n");
-#else
-			printk("    scatter-gather:  disabled\n");
-#endif
-
-#ifndef USE_SK_RX_CHECKSUM
-			printk("    rx-checksum:     disabled\n");
-#endif
+		printk("    scatter-gather:  %s\n",
+		       (dev->features & NETIF_F_SG) ? "enabled" : "disabled");
+		printk("    tx-checksum:     %s\n",
+		       (dev->features & NETIF_F_IP_CSUM) ? "enabled" : "disabled");
+		printk("    rx-checksum:     %s\n",
+		       pAC->RxPort[Param.Para32[0]].RxCsum ? "enabled" : "disabled");
 
 		} else {
                         DoPrintInterfaceChange = SK_TRUE;
@@ -4263,9 +4224,9 @@ SK_BOOL		DualNet;
 		}
 
 		/* Inform the world that link protocol is up. */
-		netif_carrier_on(pAC->dev[Param.Para32[0]]);
-
+		netif_carrier_on(dev);
 		break;
+	}
 	case SK_DRV_NET_DOWN:	 /* SK_U32 Reason */
 		/* action list 7 */
 		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
@@ -4479,7 +4440,7 @@ SK_AC   *pAc)   /* pointer to adapter context */
 
 	pAC->DiagModeActive = DIAG_ACTIVE;
 	if (pAC->BoardLevel > SK_INIT_DATA) {
-		if (pNet->Up) {
+		if (netif_running(pAC->dev[0])) {
 			pAC->WasIfUp[0] = SK_TRUE;
 			pAC->DiagFlowCtrl = SK_TRUE; /* for SkGeClose      */
 			DoPrintInterfaceChange = SK_FALSE;
@@ -4489,7 +4450,7 @@ SK_AC   *pAc)   /* pointer to adapter context */
 		}
 		if (pNet != netdev_priv(pAC->dev[1])) {
 			pNet = netdev_priv(pAC->dev[1]);
-			if (pNet->Up) {
+			if (netif_running(pAC->dev[1])) {
 				pAC->WasIfUp[1] = SK_TRUE;
 				pAC->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */
 				DoPrintInterfaceChange = SK_FALSE;
@@ -4815,6 +4776,7 @@ static int __devinit skge_probe_one(struct pci_dev *pdev,
 	struct net_device	*dev = NULL;
 	static int boards_found = 0;
 	int error = -ENODEV;
+	char DeviceStr[80];
 
 	if (pci_enable_device(pdev))
 		goto out;
@@ -4842,14 +4804,11 @@ static int __devinit skge_probe_one(struct pci_dev *pdev,
 	memset(pNet->pAC, 0, sizeof(SK_AC));
 	pAC = pNet->pAC;
 	pAC->PciDev = pdev;
-	pAC->PciDevId = pdev->device;
+
 	pAC->dev[0] = dev;
 	pAC->dev[1] = dev;
-	sprintf(pAC->Name, "SysKonnect SK-98xx");
 	pAC->CheckQueue = SK_FALSE;
 
-	pNet->Mtu = 1500;
-	pNet->Up = 0;
 	dev->irq = pdev->irq;
 	error = SkGeInitPCI(pAC);
 	if (error) {
@@ -4872,21 +4831,30 @@ static int __devinit skge_probe_one(struct pci_dev *pdev,
 	SET_NETDEV_DEV(dev, &pdev->dev);
 	SET_ETHTOOL_OPS(dev, &SkGeEthtoolOps);
 
-#ifdef SK_ZEROCOPY
-#ifdef USE_SK_TX_CHECKSUM
+	/* Use only if yukon hardware */
 	if (pAC->ChipsetType) {
-		/* Use only if yukon hardware */
-		/* SK and ZEROCOPY - fly baby... */
-		dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
-	}
+#ifdef USE_SK_TX_CHECKSUM
+		dev->features |= NETIF_F_IP_CSUM;
+#endif
+#ifdef SK_ZEROCOPY
+		dev->features |= NETIF_F_SG;
 #endif
+#ifdef USE_SK_RX_CHECKSUM
+		pAC->RxPort[0].RxCsum = 1;
 #endif
+	}
 
 	pAC->Index = boards_found++;
 
 	if (SkGeBoardInit(dev, pAC))
 		goto out_free_netdev;
 
+	/* Read Adapter name from VPD */
+	if (ProductStr(pAC, DeviceStr, sizeof(DeviceStr)) != 0) {
+		printk(KERN_ERR "sk98lin: Could not read VPD data.\n");
+		goto out_free_resources;
+	}
+
 	/* Register net device */
 	if (register_netdev(dev)) {
 		printk(KERN_ERR "sk98lin: Could not register device.\n");
@@ -4894,8 +4862,7 @@ static int __devinit skge_probe_one(struct pci_dev *pdev,
 	}
 
 	/* Print adapter specific string from vpd */
-	ProductStr(pAC);
-	printk("%s: %s\n", dev->name, pAC->DeviceStr);
+	printk("%s: %s\n", dev->name, DeviceStr);
 
 	/* Print configuration settings */
 	printk("      PrefPort:%c  RlmtMode:%s\n",
@@ -4911,8 +4878,6 @@ static int __devinit skge_probe_one(struct pci_dev *pdev,
 	memcpy(&dev->dev_addr, &pAC->Addr.Net[0].CurrentMacAddress, 6);
 	memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
 
-	SkGeProcCreate(dev);
-
 	pNet->PortNr = 0;
 	pNet->NetNr  = 0;
 
@@ -4931,8 +4896,6 @@ static int __devinit skge_probe_one(struct pci_dev *pdev,
 		pNet->PortNr  = 1;
 		pNet->NetNr   = 1;
 		pNet->pAC     = pAC;
-		pNet->Mtu     = 1500;
-		pNet->Up      = 0;
 
 		dev->open               = &SkGeOpen;
 		dev->stop               = &SkGeClose;
@@ -4945,26 +4908,28 @@ static int __devinit skge_probe_one(struct pci_dev *pdev,
 		SET_NETDEV_DEV(dev, &pdev->dev);
 		SET_ETHTOOL_OPS(dev, &SkGeEthtoolOps);
 
-#ifdef SK_ZEROCOPY
-#ifdef USE_SK_TX_CHECKSUM
 		if (pAC->ChipsetType) {
-			/* SG and ZEROCOPY - fly baby... */
-			dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
-		}
+#ifdef USE_SK_TX_CHECKSUM
+			dev->features |= NETIF_F_IP_CSUM;
+#endif
+#ifdef SK_ZEROCOPY
+			dev->features |= NETIF_F_SG;
 #endif
+#ifdef USE_SK_RX_CHECKSUM
+			pAC->RxPort[1].RxCsum = 1;
 #endif
+		}
 
 		if (register_netdev(dev)) {
 			printk(KERN_ERR "sk98lin: Could not register device for seconf port.\n");
 			free_netdev(dev);
 			pAC->dev[1] = pAC->dev[0];
 		} else {
-			SkGeProcCreate(dev);
 			memcpy(&dev->dev_addr,
 					&pAC->Addr.Net[1].CurrentMacAddress, 6);
 			memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
 	
-			printk("%s: %s\n", dev->name, pAC->DeviceStr);
+			printk("%s: %s\n", dev->name, DeviceStr);
 			printk("      PrefPort:B  RlmtMode:Dual Check Link State\n");
 		}
 	}
@@ -5000,10 +4965,7 @@ static void __devexit skge_remove_one(struct pci_dev *pdev)
 	SK_AC *pAC = pNet->pAC;
 	struct net_device *otherdev = pAC->dev[1];
 
-	SkGeProcRemove(dev);
 	unregister_netdev(dev);
-	if (otherdev != dev)
-		SkGeProcRemove(otherdev);
 
 	SkGeYellowLED(pAC, pAC->IoBase, 0);
 
@@ -5088,9 +5050,9 @@ static int skge_resume(struct pci_dev *pdev)
 	pci_enable_device(pdev);
 	pci_set_master(pdev);
 	if (pAC->GIni.GIMacsFound == 2)
-		ret = request_irq(dev->irq, SkGeIsr, SA_SHIRQ, pAC->Name, dev);
+		ret = request_irq(dev->irq, SkGeIsr, SA_SHIRQ, "sk98lin", dev);
 	else
-		ret = request_irq(dev->irq, SkGeIsrOnePort, SA_SHIRQ, pAC->Name, dev);
+		ret = request_irq(dev->irq, SkGeIsrOnePort, SA_SHIRQ, "sk98lin", dev);
 	if (ret) {
 		printk(KERN_WARNING "sk98lin: unable to acquire IRQ %d\n", dev->irq);
 		pAC->AllocFlag &= ~SK_ALLOC_IRQ;
@@ -5148,23 +5110,12 @@ static struct pci_driver skge_driver = {
 
 static int __init skge_init(void)
 {
-	int error;
-
-	pSkRootDir = proc_mkdir(SKRootName, NULL);
-	if (pSkRootDir) 
-		pSkRootDir->owner = THIS_MODULE;
-	
-	error = pci_register_driver(&skge_driver);
-	if (error)
-		remove_proc_entry(SKRootName, NULL);
-	return error;
+	return pci_module_init(&skge_driver);
 }
 
 static void __exit skge_exit(void)
 {
 	pci_unregister_driver(&skge_driver);
-	remove_proc_entry(SKRootName, NULL);
-
 }
 
 module_init(skge_init);
diff --git a/drivers/net/sk98lin/skproc.c b/drivers/net/sk98lin/skproc.c
deleted file mode 100644
index 5cece25c034e..000000000000
--- a/drivers/net/sk98lin/skproc.c
+++ /dev/null
@@ -1,265 +0,0 @@
-/******************************************************************************
- *
- * Name:	skproc.c
- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.11 $
- * Date:	$Date: 2003/12/11 16:03:57 $
- * Purpose:	Funktions to display statictic data
- *
- ******************************************************************************/
- 
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	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.
- *
- *	Created 22-Nov-2000
- *	Author: Mirko Lindner (mlindner@syskonnect.de)
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-
-#include "h/skdrv1st.h"
-#include "h/skdrv2nd.h"
-#include "h/skversion.h"
-
-static int sk_seq_show(struct seq_file *seq, void *v);
-static int sk_proc_open(struct inode *inode, struct file *file);
-
-struct file_operations sk_proc_fops = {
-	.owner		= THIS_MODULE,
-	.open		= sk_proc_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-
-/*****************************************************************************
- *
- *      sk_seq_show - show proc information of a particular adapter
- *
- * Description:
- *  This function fills the proc entry with statistic data about 
- *  the ethernet device. It invokes the generic sk_gen_browse() to
- *  print out all items one per one.
- *  
- * Returns: 0
- *      
- */
-static int sk_seq_show(struct seq_file *seq, void *v)
-{
-	struct net_device *dev = seq->private;
-	DEV_NET			*pNet = netdev_priv(dev);
-	SK_AC			*pAC = pNet->pAC;
-	SK_PNMI_STRUCT_DATA 	*pPnmiStruct = &pAC->PnmiStruct;
-	unsigned long		Flags;	
-	unsigned int		Size;
-	char			sens_msg[50];
-	int 			t;
-	int 			i;
-
-	/* NetIndex in GetStruct is now required, zero is only dummy */
-	for (t=pAC->GIni.GIMacsFound; t > 0; t--) {
-		if ((pAC->GIni.GIMacsFound == 2) && pAC->RlmtNets == 1)
-			t--;
-
-		spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-		Size = SK_PNMI_STRUCT_SIZE;
-#ifdef SK_DIAG_SUPPORT
-		if (pAC->BoardLevel == SK_INIT_DATA) {
-			SK_MEMCPY(&(pAC->PnmiStruct), &(pAC->PnmiBackup), sizeof(SK_PNMI_STRUCT_DATA));
-			if (pAC->DiagModeActive == DIAG_NOTACTIVE) {
-				pAC->Pnmi.DiagAttached = SK_DIAG_IDLE;
-			}
-		} else {
-			SkPnmiGetStruct(pAC, pAC->IoBase, pPnmiStruct, &Size, t-1);
-		}
-#else
-		SkPnmiGetStruct(pAC, pAC->IoBase, 
-				pPnmiStruct, &Size, t-1);
-#endif
-		spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-	
-		if (pAC->dev[t-1] == dev) {
-			SK_PNMI_STAT	*pPnmiStat = &pPnmiStruct->Stat[0];
-
-			seq_printf(seq, "\nDetailed statistic for device %s\n",
-				      pAC->dev[t-1]->name);
-			seq_printf(seq, "=======================================\n");
-	
-			/* Board statistics */
-			seq_printf(seq, "\nBoard statistics\n\n");
-			seq_printf(seq, "Active Port                    %c\n",
-				      'A' + pAC->Rlmt.Net[t-1].Port[pAC->Rlmt.
-								    Net[t-1].PrefPort]->PortNumber);
-			seq_printf(seq, "Preferred Port                 %c\n",
-				      'A' + pAC->Rlmt.Net[t-1].Port[pAC->Rlmt.
-								    Net[t-1].PrefPort]->PortNumber);
-
-			seq_printf(seq, "Bus speed (MHz)                %d\n",
-				      pPnmiStruct->BusSpeed);
-
-			seq_printf(seq, "Bus width (Bit)                %d\n",
-				      pPnmiStruct->BusWidth);
-			seq_printf(seq, "Driver version                 %s\n",
-				      VER_STRING);
-			seq_printf(seq, "Hardware revision              v%d.%d\n",
-				      (pAC->GIni.GIPciHwRev >> 4) & 0x0F,
-				      pAC->GIni.GIPciHwRev & 0x0F);
-
-			/* Print sensor informations */
-			for (i=0; i < pAC->I2c.MaxSens; i ++) {
-				/* Check type */
-				switch (pAC->I2c.SenTable[i].SenType) {
-				case 1:
-					strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
-					strcat(sens_msg, " (C)");
-					seq_printf(seq, "%-25s      %d.%02d\n",
-						      sens_msg,
-						      pAC->I2c.SenTable[i].SenValue / 10,
-						      pAC->I2c.SenTable[i].SenValue % 10);
-
-					strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
-					strcat(sens_msg, " (F)");
-					seq_printf(seq, "%-25s      %d.%02d\n",
-						      sens_msg,
-						      ((((pAC->I2c.SenTable[i].SenValue)
-							 *10)*9)/5 + 3200)/100,
-						      ((((pAC->I2c.SenTable[i].SenValue)
-							 *10)*9)/5 + 3200) % 10);
-					break;
-				case 2:
-					strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
-					strcat(sens_msg, " (V)");
-					seq_printf(seq, "%-25s      %d.%03d\n",
-						      sens_msg,
-						      pAC->I2c.SenTable[i].SenValue / 1000,
-						      pAC->I2c.SenTable[i].SenValue % 1000);
-					break;
-				case 3:
-					strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
-					strcat(sens_msg, " (rpm)");
-					seq_printf(seq, "%-25s      %d\n",
-						      sens_msg,
-						      pAC->I2c.SenTable[i].SenValue);
-					break;
-				default:
-					break;
-				}
-			}
-				
-			/*Receive statistics */
-			seq_printf(seq, "\nReceive statistics\n\n");
-
-			seq_printf(seq, "Received bytes                 %Lu\n",
-				      (unsigned long long) pPnmiStat->StatRxOctetsOkCts);
-			seq_printf(seq, "Received packets               %Lu\n",
-				      (unsigned long long) pPnmiStat->StatRxOkCts);
-#if 0
-			if (pAC->GIni.GP[0].PhyType == SK_PHY_XMAC && 
-			    pAC->HWRevision < 12) {
-				pPnmiStruct->InErrorsCts = pPnmiStruct->InErrorsCts - 
-					pPnmiStat->StatRxShortsCts;
-				pPnmiStat->StatRxShortsCts = 0;
-			}
-#endif
-			if (dev->mtu > 1500)
-				pPnmiStruct->InErrorsCts = pPnmiStruct->InErrorsCts -
-					pPnmiStat->StatRxTooLongCts;
-
-			seq_printf(seq, "Receive errors                 %Lu\n",
-				      (unsigned long long) pPnmiStruct->InErrorsCts);
-			seq_printf(seq, "Receive dropped                %Lu\n",
-				      (unsigned long long) pPnmiStruct->RxNoBufCts);
-			seq_printf(seq, "Received multicast             %Lu\n",
-				      (unsigned long long) pPnmiStat->StatRxMulticastOkCts);
-			seq_printf(seq, "Receive error types\n");
-			seq_printf(seq, "   length                      %Lu\n",
-				      (unsigned long long) pPnmiStat->StatRxRuntCts);
-			seq_printf(seq, "   buffer overflow             %Lu\n",
-				      (unsigned long long) pPnmiStat->StatRxFifoOverflowCts);
-			seq_printf(seq, "   bad crc                     %Lu\n",
-				      (unsigned long long) pPnmiStat->StatRxFcsCts);
-			seq_printf(seq, "   framing                     %Lu\n",
-				      (unsigned long long) pPnmiStat->StatRxFramingCts);
-			seq_printf(seq, "   missed frames               %Lu\n",
-				      (unsigned long long) pPnmiStat->StatRxMissedCts);
-
-			if (dev->mtu > 1500)
-				pPnmiStat->StatRxTooLongCts = 0;
-
-			seq_printf(seq, "   too long                    %Lu\n",
-				      (unsigned long long) pPnmiStat->StatRxTooLongCts);					
-			seq_printf(seq, "   carrier extension           %Lu\n",
-				      (unsigned long long) pPnmiStat->StatRxCextCts);				
-			seq_printf(seq, "   too short                   %Lu\n",
-				      (unsigned long long) pPnmiStat->StatRxShortsCts);				
-			seq_printf(seq, "   symbol                      %Lu\n",
-				      (unsigned long long) pPnmiStat->StatRxSymbolCts);				
-			seq_printf(seq, "   LLC MAC size                %Lu\n",
-				      (unsigned long long) pPnmiStat->StatRxIRLengthCts);				
-			seq_printf(seq, "   carrier event               %Lu\n",
-				      (unsigned long long) pPnmiStat->StatRxCarrierCts);				
-			seq_printf(seq, "   jabber                      %Lu\n",
-				      (unsigned long long) pPnmiStat->StatRxJabberCts);				
-
-
-			/*Transmit statistics */
-			seq_printf(seq, "\nTransmit statistics\n\n");
-				
-			seq_printf(seq, "Transmited bytes               %Lu\n",
-				      (unsigned long long) pPnmiStat->StatTxOctetsOkCts);
-			seq_printf(seq, "Transmited packets             %Lu\n",
-				      (unsigned long long) pPnmiStat->StatTxOkCts);
-			seq_printf(seq, "Transmit errors                %Lu\n",
-				      (unsigned long long) pPnmiStat->StatTxSingleCollisionCts);
-			seq_printf(seq, "Transmit dropped               %Lu\n",
-				      (unsigned long long) pPnmiStruct->TxNoBufCts);
-			seq_printf(seq, "Transmit collisions            %Lu\n",
-				      (unsigned long long) pPnmiStat->StatTxSingleCollisionCts);
-			seq_printf(seq, "Transmit error types\n");
-			seq_printf(seq, "   excessive collision         %ld\n",
-				      pAC->stats.tx_aborted_errors);
-			seq_printf(seq, "   carrier                     %Lu\n",
-				      (unsigned long long) pPnmiStat->StatTxCarrierCts);
-			seq_printf(seq, "   fifo underrun               %Lu\n",
-				      (unsigned long long) pPnmiStat->StatTxFifoUnderrunCts);
-			seq_printf(seq, "   heartbeat                   %Lu\n",
-				      (unsigned long long) pPnmiStat->StatTxCarrierCts);
-			seq_printf(seq, "   window                      %ld\n",
-				      pAC->stats.tx_window_errors);
-				
-		}
-	}
-	return 0;
-}
-
-/*****************************************************************************
- *
- *      sk_proc_open - register the show function when proc is open'ed
- *  
- * Description:
- *  This function is called whenever a sk98lin proc file is queried.
- *  
- * Returns: the return value of single_open()
- *      
- */
-static int sk_proc_open(struct inode *inode, struct file *file)
-{
-    return single_open(file, sk_seq_show, PDE(inode)->data);
-}
-
-/*******************************************************************************
- *
- * End of file
- *
- ******************************************************************************/
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index 00d683063c01..b538e3038058 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -25,6 +25,7 @@
  */
 
 #include <linux/config.h>
+#include <linux/in.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
@@ -43,7 +44,7 @@
 #include "skge.h"
 
 #define DRV_NAME		"skge"
-#define DRV_VERSION		"1.2"
+#define DRV_VERSION		"1.3"
 #define PFX			DRV_NAME " "
 
 #define DEFAULT_TX_RING_SIZE	128
@@ -88,15 +89,14 @@ MODULE_DEVICE_TABLE(pci, skge_id_table);
 
 static int skge_up(struct net_device *dev);
 static int skge_down(struct net_device *dev);
+static void skge_phy_reset(struct skge_port *skge);
 static void skge_tx_clean(struct skge_port *skge);
 static int xm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val);
 static int gm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val);
 static void genesis_get_stats(struct skge_port *skge, u64 *data);
 static void yukon_get_stats(struct skge_port *skge, u64 *data);
 static void yukon_init(struct skge_hw *hw, int port);
-static void yukon_reset(struct skge_hw *hw, int port);
 static void genesis_mac_init(struct skge_hw *hw, int port);
-static void genesis_reset(struct skge_hw *hw, int port);
 static void genesis_link_up(struct skge_port *skge);
 
 /* Avoid conditionals by using array */
@@ -276,10 +276,9 @@ static int skge_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 	skge->autoneg = ecmd->autoneg;
 	skge->advertising = ecmd->advertising;
 
-	if (netif_running(dev)) {
-		skge_down(dev);
-		skge_up(dev);
-	}
+	if (netif_running(dev))
+		skge_phy_reset(skge);
+
 	return (0);
 }
 
@@ -399,6 +398,7 @@ static int skge_set_ring_param(struct net_device *dev,
 			       struct ethtool_ringparam *p)
 {
 	struct skge_port *skge = netdev_priv(dev);
+	int err;
 
 	if (p->rx_pending == 0 || p->rx_pending > MAX_RX_RING_SIZE ||
 	    p->tx_pending == 0 || p->tx_pending > MAX_TX_RING_SIZE)
@@ -409,7 +409,9 @@ static int skge_set_ring_param(struct net_device *dev,
 
 	if (netif_running(dev)) {
 		skge_down(dev);
-		skge_up(dev);
+		err = skge_up(dev);
+		if (err)
+			dev_close(dev);
 	}
 
 	return 0;
@@ -430,21 +432,11 @@ static void skge_set_msglevel(struct net_device *netdev, u32 value)
 static int skge_nway_reset(struct net_device *dev)
 {
 	struct skge_port *skge = netdev_priv(dev);
-	struct skge_hw *hw = skge->hw;
-	int port = skge->port;
 
 	if (skge->autoneg != AUTONEG_ENABLE || !netif_running(dev))
 		return -EINVAL;
 
-	spin_lock_bh(&hw->phy_lock);
-	if (hw->chip_id == CHIP_ID_GENESIS) {
-		genesis_reset(hw, port);
-		genesis_mac_init(hw, port);
-	} else {
-		yukon_reset(hw, port);
-		yukon_init(hw, port);
-	}
-	spin_unlock_bh(&hw->phy_lock);
+	skge_phy_reset(skge);
 	return 0;
 }
 
@@ -516,10 +508,8 @@ static int skge_set_pauseparam(struct net_device *dev,
 	else
 		skge->flow_control = FLOW_MODE_NONE;
 
-	if (netif_running(dev)) {
-		skge_down(dev);
-		skge_up(dev);
-	}
+	if (netif_running(dev))
+		skge_phy_reset(skge);
 	return 0;
 }
 
@@ -2019,6 +2009,25 @@ static void yukon_phy_intr(struct skge_port *skge)
 	/* XXX restart autonegotiation? */
 }
 
+static void skge_phy_reset(struct skge_port *skge)
+{
+	struct skge_hw *hw = skge->hw;
+	int port = skge->port;
+
+	netif_stop_queue(skge->netdev);
+	netif_carrier_off(skge->netdev);
+
+	spin_lock_bh(&hw->phy_lock);
+	if (hw->chip_id == CHIP_ID_GENESIS) {
+		genesis_reset(hw, port);
+		genesis_mac_init(hw, port);
+	} else {
+		yukon_reset(hw, port);
+		yukon_init(hw, port);
+	}
+	spin_unlock_bh(&hw->phy_lock);
+}
+
 /* Basic MII support */
 static int skge_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
@@ -2187,6 +2196,7 @@ static int skge_up(struct net_device *dev)
 	kfree(skge->rx_ring.start);
  free_pci_mem:
 	pci_free_consistent(hw->pdev, skge->mem_size, skge->mem, skge->dma);
+	skge->mem = NULL;
 
 	return err;
 }
@@ -2197,6 +2207,9 @@ static int skge_down(struct net_device *dev)
 	struct skge_hw *hw = skge->hw;
 	int port = skge->port;
 
+	if (skge->mem == NULL)
+		return 0;
+
 	if (netif_msg_ifdown(skge))
 		printk(KERN_INFO PFX "%s: disabling interface\n", dev->name);
 
@@ -2253,6 +2266,7 @@ static int skge_down(struct net_device *dev)
 	kfree(skge->rx_ring.start);
 	kfree(skge->tx_ring.start);
 	pci_free_consistent(hw->pdev, skge->mem_size, skge->mem, skge->dma);
+	skge->mem = NULL;
 	return 0;
 }
 
@@ -2413,18 +2427,23 @@ static void skge_tx_timeout(struct net_device *dev)
 
 static int skge_change_mtu(struct net_device *dev, int new_mtu)
 {
-	int err = 0;
-	int running = netif_running(dev);
+	int err;
 
 	if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU)
 		return -EINVAL;
 
+	if (!netif_running(dev)) {
+		dev->mtu = new_mtu;
+		return 0;
+	}
+
+	skge_down(dev);
 
-	if (running)
-		skge_down(dev);
 	dev->mtu = new_mtu;
-	if (running)
-		skge_up(dev);
+
+	err = skge_up(dev);
+	if (err)
+		dev_close(dev);
 
 	return err;
 }
@@ -3398,8 +3417,8 @@ static int skge_resume(struct pci_dev *pdev)
 		struct net_device *dev = hw->dev[i];
 		if (dev) {
 			netif_device_attach(dev);
-			if (netif_running(dev))
-				skge_up(dev);
+			if (netif_running(dev) && skge_up(dev))
+				dev_close(dev);
 		}
 	}
 	return 0;
diff --git a/drivers/net/skge.h b/drivers/net/skge.h
index ee123c15f545..2efdacc290e5 100644
--- a/drivers/net/skge.h
+++ b/drivers/net/skge.h
@@ -475,18 +475,6 @@ enum {
 	Q_T2	= 0x40,	/* 32 bit	Test Register 2	*/
 	Q_T3	= 0x44,	/* 32 bit	Test Register 3	*/
 
-/* Yukon-2 */
-	Q_DONE	= 0x24,	/* 16 bit	Done Index 		(Yukon-2 only) */
-	Q_WM	= 0x40,	/* 16 bit	FIFO Watermark */
-	Q_AL	= 0x42,	/*  8 bit	FIFO Alignment */
-	Q_RSP	= 0x44,	/* 16 bit	FIFO Read Shadow Pointer */
-	Q_RSL	= 0x46,	/*  8 bit	FIFO Read Shadow Level */
-	Q_RP	= 0x48,	/*  8 bit	FIFO Read Pointer */
-	Q_RL	= 0x4a,	/*  8 bit	FIFO Read Level */
-	Q_WP	= 0x4c,	/*  8 bit	FIFO Write Pointer */
-	Q_WSP	= 0x4d,	/*  8 bit	FIFO Write Shadow Pointer */
-	Q_WL	= 0x4e,	/*  8 bit	FIFO Write Level */
-	Q_WSL	= 0x4f,	/*  8 bit	FIFO Write Shadow Level */
 };
 #define Q_ADDR(reg, offs) (B8_Q_REGS + (reg) + (offs))
 
@@ -675,22 +663,16 @@ enum {
 	LED_OFF	= 1<<0,	/* switch LED off */
 };
 
-/* Receive GMAC FIFO (YUKON and Yukon-2) */
+/* Receive GMAC FIFO (YUKON) */
 enum {
 	RX_GMF_EA	= 0x0c40,/* 32 bit	Rx GMAC FIFO End Address */
 	RX_GMF_AF_THR	= 0x0c44,/* 32 bit	Rx GMAC FIFO Almost Full Thresh. */
 	RX_GMF_CTRL_T	= 0x0c48,/* 32 bit	Rx GMAC FIFO Control/Test */
 	RX_GMF_FL_MSK	= 0x0c4c,/* 32 bit	Rx GMAC FIFO Flush Mask */
 	RX_GMF_FL_THR	= 0x0c50,/* 32 bit	Rx GMAC FIFO Flush Threshold */
-	RX_GMF_TR_THR	= 0x0c54,/* 32 bit	Rx Truncation Threshold (Yukon-2) */
-
-	RX_GMF_VLAN	= 0x0c5c,/* 32 bit	Rx VLAN Type Register (Yukon-2) */
 	RX_GMF_WP	= 0x0c60,/* 32 bit	Rx GMAC FIFO Write Pointer */
-
 	RX_GMF_WLEV	= 0x0c68,/* 32 bit	Rx GMAC FIFO Write Level */
-
 	RX_GMF_RP	= 0x0c70,/* 32 bit	Rx GMAC FIFO Read Pointer */
-
 	RX_GMF_RLEV	= 0x0c78,/* 32 bit	Rx GMAC FIFO Read Level */
 };
 
@@ -855,48 +837,6 @@ enum {
 	GMAC_TI_ST_TST	= 0x0e1a,/*  8 bit	Time Stamp Timer Test Reg */
 };
 
-/* Status BMU Registers (Yukon-2 only)*/
-enum {
-	STAT_CTRL	= 0x0e80,/* 32 bit	Status BMU Control Reg */
-	STAT_LAST_IDX	= 0x0e84,/* 16 bit	Status BMU Last Index */
-	/* 0x0e85 - 0x0e86:	reserved */
-	STAT_LIST_ADDR_LO	= 0x0e88,/* 32 bit	Status List Start Addr (low) */
-	STAT_LIST_ADDR_HI	= 0x0e8c,/* 32 bit	Status List Start Addr (high) */
-	STAT_TXA1_RIDX	= 0x0e90,/* 16 bit	Status TxA1 Report Index Reg */
-	STAT_TXS1_RIDX	= 0x0e92,/* 16 bit	Status TxS1 Report Index Reg */
-	STAT_TXA2_RIDX	= 0x0e94,/* 16 bit	Status TxA2 Report Index Reg */
-	STAT_TXS2_RIDX	= 0x0e96,/* 16 bit	Status TxS2 Report Index Reg */
-	STAT_TX_IDX_TH	= 0x0e98,/* 16 bit	Status Tx Index Threshold Reg */
-	STAT_PUT_IDX	= 0x0e9c,/* 16 bit	Status Put Index Reg */
-
-/* FIFO Control/Status Registers (Yukon-2 only)*/
-	STAT_FIFO_WP	= 0x0ea0,/*  8 bit	Status FIFO Write Pointer Reg */
-	STAT_FIFO_RP	= 0x0ea4,/*  8 bit	Status FIFO Read Pointer Reg */
-	STAT_FIFO_RSP	= 0x0ea6,/*  8 bit	Status FIFO Read Shadow Ptr */
-	STAT_FIFO_LEVEL	= 0x0ea8,/*  8 bit	Status FIFO Level Reg */
-	STAT_FIFO_SHLVL	= 0x0eaa,/*  8 bit	Status FIFO Shadow Level Reg */
-	STAT_FIFO_WM	= 0x0eac,/*  8 bit	Status FIFO Watermark Reg */
-	STAT_FIFO_ISR_WM	= 0x0ead,/*  8 bit	Status FIFO ISR Watermark Reg */
-
-/* Level and ISR Timer Registers (Yukon-2 only)*/
-	STAT_LEV_TIMER_INI	= 0x0eb0,/* 32 bit	Level Timer Init. Value Reg */
-	STAT_LEV_TIMER_CNT	= 0x0eb4,/* 32 bit	Level Timer Counter Reg */
-	STAT_LEV_TIMER_CTRL	= 0x0eb8,/*  8 bit	Level Timer Control Reg */
-	STAT_LEV_TIMER_TEST	= 0x0eb9,/*  8 bit	Level Timer Test Reg */
-	STAT_TX_TIMER_INI	= 0x0ec0,/* 32 bit	Tx Timer Init. Value Reg */
-	STAT_TX_TIMER_CNT	= 0x0ec4,/* 32 bit	Tx Timer Counter Reg */
-	STAT_TX_TIMER_CTRL	= 0x0ec8,/*  8 bit	Tx Timer Control Reg */
-	STAT_TX_TIMER_TEST	= 0x0ec9,/*  8 bit	Tx Timer Test Reg */
-	STAT_ISR_TIMER_INI	= 0x0ed0,/* 32 bit	ISR Timer Init. Value Reg */
-	STAT_ISR_TIMER_CNT	= 0x0ed4,/* 32 bit	ISR Timer Counter Reg */
-	STAT_ISR_TIMER_CTRL	= 0x0ed8,/*  8 bit	ISR Timer Control Reg */
-	STAT_ISR_TIMER_TEST	= 0x0ed9,/*  8 bit	ISR Timer Test Reg */
-
-	ST_LAST_IDX_MASK	= 0x007f,/* Last Index Mask */
-	ST_TXRP_IDX_MASK	= 0x0fff,/* Tx Report Index Mask */
-	ST_TXTH_IDX_MASK	= 0x0fff,/* Tx Threshold Index Mask */
-	ST_WM_IDX_MASK	= 0x3f,/* FIFO Watermark Index Mask */
-};
 
 enum {
 	LINKLED_OFF 	     = 0x01,
@@ -923,8 +863,6 @@ enum {
 	WOL_MATCH_CTL	= 0x0f22,/*  8 bit	WOL Match Control Reg */
 	WOL_MATCH_RES	= 0x0f23,/*  8 bit	WOL Match Result Reg */
 	WOL_MAC_ADDR	= 0x0f24,/* 32 bit	WOL MAC Address */
-	WOL_PATT_PME	= 0x0f2a,/*  8 bit	WOL PME Match Enable (Yukon-2) */
-	WOL_PATT_ASFM	= 0x0f2b,/*  8 bit	WOL ASF Match Enable (Yukon-2) */
 	WOL_PATT_RPTR	= 0x0f2c,/*  8 bit	WOL Pattern Read Pointer */
 
 /* WOL Pattern Length Registers (YUKON only) */
@@ -1641,15 +1579,6 @@ enum {
 	PHY_M_FESC_SEL_CL_A	= 1<<0, /* Select Class A driver (100B-TX) */
 };
 
-/* for Yukon-2 Gigabit Ethernet PHY (88E1112 only) */
-/*****  PHY_MARV_PHY_CTRL (page 2)		16 bit r/w	MAC Specific Ctrl *****/
-enum {
-	PHY_M_MAC_MD_MSK	= 7<<7, /* Bit  9.. 7: Mode Select Mask */
-	PHY_M_MAC_MD_AUTO	= 3,/* Auto Copper/1000Base-X */
-	PHY_M_MAC_MD_COPPER	= 5,/* Copper only */
-	PHY_M_MAC_MD_1000BX	= 7,/* 1000Base-X only */
-};
-#define PHY_M_MAC_MODE_SEL(x)	(((x)<<7) & PHY_M_MAC_MD_MSK)
 
 /*****  PHY_MARV_PHY_CTRL (page 3)		16 bit r/w	LED Control Reg. *****/
 enum {
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
new file mode 100644
index 000000000000..f5d697c0c031
--- /dev/null
+++ b/drivers/net/sky2.c
@@ -0,0 +1,3262 @@
+/*
+ * New driver for Marvell Yukon 2 chipset.
+ * Based on earlier sk98lin, and skge driver.
+ *
+ * This driver intentionally does not support all the features
+ * of the original driver such as link fail-over and link management because
+ * those should be done at higher levels.
+ *
+ * Copyright (C) 2005 Stephen Hemminger <shemminger@osdl.org>
+ *
+ * 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.
+ */
+
+/*
+ * TOTEST
+ *	- speed setting
+ *	- suspend/resume
+ */
+
+#include <linux/config.h>
+#include <linux/crc32.h>
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/dma-mapping.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/pci.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/in.h>
+#include <linux/delay.h>
+#include <linux/workqueue.h>
+#include <linux/if_vlan.h>
+#include <linux/prefetch.h>
+#include <linux/mii.h>
+
+#include <asm/irq.h>
+
+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
+#define SKY2_VLAN_TAG_USED 1
+#endif
+
+#include "sky2.h"
+
+#define DRV_NAME		"sky2"
+#define DRV_VERSION		"0.11"
+#define PFX			DRV_NAME " "
+
+/*
+ * The Yukon II chipset takes 64 bit command blocks (called list elements)
+ * that are organized into three (receive, transmit, status) different rings
+ * similar to Tigon3. A transmit can require several elements;
+ * a receive requires one (or two if using 64 bit dma).
+ */
+
+#define is_ec_a1(hw) \
+	unlikely((hw)->chip_id == CHIP_ID_YUKON_EC && \
+		 (hw)->chip_rev == CHIP_REV_YU_EC_A1)
+
+#define RX_LE_SIZE	    	512
+#define RX_LE_BYTES		(RX_LE_SIZE*sizeof(struct sky2_rx_le))
+#define RX_MAX_PENDING		(RX_LE_SIZE/2 - 2)
+#define RX_DEF_PENDING		RX_MAX_PENDING
+
+#define TX_RING_SIZE		512
+#define TX_DEF_PENDING		(TX_RING_SIZE - 1)
+#define TX_MIN_PENDING		64
+#define MAX_SKB_TX_LE		(4 + 2*MAX_SKB_FRAGS)
+
+#define STATUS_RING_SIZE	2048	/* 2 ports * (TX + 2*RX) */
+#define STATUS_LE_BYTES		(STATUS_RING_SIZE*sizeof(struct sky2_status_le))
+#define ETH_JUMBO_MTU		9000
+#define TX_WATCHDOG		(5 * HZ)
+#define NAPI_WEIGHT		64
+#define PHY_RETRIES		1000
+
+static const u32 default_msg =
+    NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK
+    | NETIF_MSG_TIMER | NETIF_MSG_TX_ERR | NETIF_MSG_RX_ERR
+    | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN | NETIF_MSG_INTR;
+
+static int debug = -1;		/* defaults above */
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
+
+static int copybreak __read_mostly = 256;
+module_param(copybreak, int, 0);
+MODULE_PARM_DESC(copybreak, "Receive copy threshold");
+
+static const struct pci_device_id sky2_id_table[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b00) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b01) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4340) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4341) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4342) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4343) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4344) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4345) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4346) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4347) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4350) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4351) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4352) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4360) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4361) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4362) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4363) },
+	{ 0 }
+};
+
+MODULE_DEVICE_TABLE(pci, sky2_id_table);
+
+/* Avoid conditionals by using array */
+static const unsigned txqaddr[] = { Q_XA1, Q_XA2 };
+static const unsigned rxqaddr[] = { Q_R1, Q_R2 };
+
+/* This driver supports yukon2 chipset only */
+static const char *yukon2_name[] = {
+	"XL",		/* 0xb3 */
+	"EC Ultra", 	/* 0xb4 */
+	"UNKNOWN",	/* 0xb5 */
+	"EC",		/* 0xb6 */
+	"FE",		/* 0xb7 */
+};
+
+/* Access to external PHY */
+static int gm_phy_write(struct sky2_hw *hw, unsigned port, u16 reg, u16 val)
+{
+	int i;
+
+	gma_write16(hw, port, GM_SMI_DATA, val);
+	gma_write16(hw, port, GM_SMI_CTRL,
+		    GM_SMI_CT_PHY_AD(PHY_ADDR_MARV) | GM_SMI_CT_REG_AD(reg));
+
+	for (i = 0; i < PHY_RETRIES; i++) {
+		if (!(gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_BUSY))
+			return 0;
+		udelay(1);
+	}
+
+	printk(KERN_WARNING PFX "%s: phy write timeout\n", hw->dev[port]->name);
+	return -ETIMEDOUT;
+}
+
+static int __gm_phy_read(struct sky2_hw *hw, unsigned port, u16 reg, u16 *val)
+{
+	int i;
+
+	gma_write16(hw, port, GM_SMI_CTRL, GM_SMI_CT_PHY_AD(PHY_ADDR_MARV)
+		    | GM_SMI_CT_REG_AD(reg) | GM_SMI_CT_OP_RD);
+
+	for (i = 0; i < PHY_RETRIES; i++) {
+		if (gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_RD_VAL) {
+			*val = gma_read16(hw, port, GM_SMI_DATA);
+			return 0;
+		}
+
+		udelay(1);
+	}
+
+	return -ETIMEDOUT;
+}
+
+static u16 gm_phy_read(struct sky2_hw *hw, unsigned port, u16 reg)
+{
+	u16 v;
+
+	if (__gm_phy_read(hw, port, reg, &v) != 0)
+		printk(KERN_WARNING PFX "%s: phy read timeout\n", hw->dev[port]->name);
+	return v;
+}
+
+static int sky2_set_power_state(struct sky2_hw *hw, pci_power_t state)
+{
+	u16 power_control;
+	u32 reg1;
+	int vaux;
+	int ret = 0;
+
+	pr_debug("sky2_set_power_state %d\n", state);
+	sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+
+	pci_read_config_word(hw->pdev, hw->pm_cap + PCI_PM_PMC, &power_control);
+	vaux = (sky2_read8(hw, B0_CTST) & Y2_VAUX_AVAIL) &&
+		(power_control & PCI_PM_CAP_PME_D3cold);
+
+	pci_read_config_word(hw->pdev, hw->pm_cap + PCI_PM_CTRL, &power_control);
+
+	power_control |= PCI_PM_CTRL_PME_STATUS;
+	power_control &= ~(PCI_PM_CTRL_STATE_MASK);
+
+	switch (state) {
+	case PCI_D0:
+		/* switch power to VCC (WA for VAUX problem) */
+		sky2_write8(hw, B0_POWER_CTRL,
+			    PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_OFF | PC_VCC_ON);
+
+		/* disable Core Clock Division, */
+		sky2_write32(hw, B2_Y2_CLK_CTRL, Y2_CLK_DIV_DIS);
+
+		if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1)
+			/* enable bits are inverted */
+			sky2_write8(hw, B2_Y2_CLK_GATE,
+				    Y2_PCI_CLK_LNK1_DIS | Y2_COR_CLK_LNK1_DIS |
+				    Y2_CLK_GAT_LNK1_DIS | Y2_PCI_CLK_LNK2_DIS |
+				    Y2_COR_CLK_LNK2_DIS | Y2_CLK_GAT_LNK2_DIS);
+		else
+			sky2_write8(hw, B2_Y2_CLK_GATE, 0);
+
+		/* Turn off phy power saving */
+		pci_read_config_dword(hw->pdev, PCI_DEV_REG1, &reg1);
+		reg1 &= ~(PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD);
+
+		/* looks like this XL is back asswards .. */
+		if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1) {
+			reg1 |= PCI_Y2_PHY1_COMA;
+			if (hw->ports > 1)
+				reg1 |= PCI_Y2_PHY2_COMA;
+		}
+		pci_write_config_dword(hw->pdev, PCI_DEV_REG1, reg1);
+		break;
+
+	case PCI_D3hot:
+	case PCI_D3cold:
+		/* Turn on phy power saving */
+		pci_read_config_dword(hw->pdev, PCI_DEV_REG1, &reg1);
+		if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1)
+			reg1 &= ~(PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD);
+		else
+			reg1 |= (PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD);
+		pci_write_config_dword(hw->pdev, PCI_DEV_REG1, reg1);
+
+		if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1)
+			sky2_write8(hw, B2_Y2_CLK_GATE, 0);
+		else
+			/* enable bits are inverted */
+			sky2_write8(hw, B2_Y2_CLK_GATE,
+				    Y2_PCI_CLK_LNK1_DIS | Y2_COR_CLK_LNK1_DIS |
+				    Y2_CLK_GAT_LNK1_DIS | Y2_PCI_CLK_LNK2_DIS |
+				    Y2_COR_CLK_LNK2_DIS | Y2_CLK_GAT_LNK2_DIS);
+
+		/* switch power to VAUX */
+		if (vaux && state != PCI_D3cold)
+			sky2_write8(hw, B0_POWER_CTRL,
+				    (PC_VAUX_ENA | PC_VCC_ENA |
+				     PC_VAUX_ON | PC_VCC_OFF));
+		break;
+	default:
+		printk(KERN_ERR PFX "Unknown power state %d\n", state);
+		ret = -1;
+	}
+
+	pci_write_config_byte(hw->pdev, hw->pm_cap + PCI_PM_CTRL, power_control);
+	sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
+	return ret;
+}
+
+static void sky2_phy_reset(struct sky2_hw *hw, unsigned port)
+{
+	u16 reg;
+
+	/* disable all GMAC IRQ's */
+	sky2_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0);
+	/* disable PHY IRQs */
+	gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0);
+
+	gma_write16(hw, port, GM_MC_ADDR_H1, 0);	/* clear MC hash */
+	gma_write16(hw, port, GM_MC_ADDR_H2, 0);
+	gma_write16(hw, port, GM_MC_ADDR_H3, 0);
+	gma_write16(hw, port, GM_MC_ADDR_H4, 0);
+
+	reg = gma_read16(hw, port, GM_RX_CTRL);
+	reg |= GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA;
+	gma_write16(hw, port, GM_RX_CTRL, reg);
+}
+
+static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
+{
+	struct sky2_port *sky2 = netdev_priv(hw->dev[port]);
+	u16 ctrl, ct1000, adv, pg, ledctrl, ledover;
+
+	if (sky2->autoneg == AUTONEG_ENABLE && hw->chip_id != CHIP_ID_YUKON_XL) {
+		u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL);
+
+		ectrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK |
+			   PHY_M_EC_MAC_S_MSK);
+		ectrl |= PHY_M_EC_MAC_S(MAC_TX_CLK_25_MHZ);
+
+		if (hw->chip_id == CHIP_ID_YUKON_EC)
+			ectrl |= PHY_M_EC_DSC_2(2) | PHY_M_EC_DOWN_S_ENA;
+		else
+			ectrl |= PHY_M_EC_M_DSC(2) | PHY_M_EC_S_DSC(3);
+
+		gm_phy_write(hw, port, PHY_MARV_EXT_CTRL, ectrl);
+	}
+
+	ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL);
+	if (hw->copper) {
+		if (hw->chip_id == CHIP_ID_YUKON_FE) {
+			/* enable automatic crossover */
+			ctrl |= PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO) >> 1;
+		} else {
+			/* disable energy detect */
+			ctrl &= ~PHY_M_PC_EN_DET_MSK;
+
+			/* enable automatic crossover */
+			ctrl |= PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO);
+
+			if (sky2->autoneg == AUTONEG_ENABLE &&
+			    hw->chip_id == CHIP_ID_YUKON_XL) {
+				ctrl &= ~PHY_M_PC_DSC_MSK;
+				ctrl |= PHY_M_PC_DSC(2) | PHY_M_PC_DOWN_S_ENA;
+			}
+		}
+		gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl);
+	} else {
+		/* workaround for deviation #4.88 (CRC errors) */
+		/* disable Automatic Crossover */
+
+		ctrl &= ~PHY_M_PC_MDIX_MSK;
+		gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl);
+
+		if (hw->chip_id == CHIP_ID_YUKON_XL) {
+			/* Fiber: select 1000BASE-X only mode MAC Specific Ctrl Reg. */
+			gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 2);
+			ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL);
+			ctrl &= ~PHY_M_MAC_MD_MSK;
+			ctrl |= PHY_M_MAC_MODE_SEL(PHY_M_MAC_MD_1000BX);
+			gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl);
+
+			/* select page 1 to access Fiber registers */
+			gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 1);
+		}
+	}
+
+	ctrl = gm_phy_read(hw, port, PHY_MARV_CTRL);
+	if (sky2->autoneg == AUTONEG_DISABLE)
+		ctrl &= ~PHY_CT_ANE;
+	else
+		ctrl |= PHY_CT_ANE;
+
+	ctrl |= PHY_CT_RESET;
+	gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl);
+
+	ctrl = 0;
+	ct1000 = 0;
+	adv = PHY_AN_CSMA;
+
+	if (sky2->autoneg == AUTONEG_ENABLE) {
+		if (hw->copper) {
+			if (sky2->advertising & ADVERTISED_1000baseT_Full)
+				ct1000 |= PHY_M_1000C_AFD;
+			if (sky2->advertising & ADVERTISED_1000baseT_Half)
+				ct1000 |= PHY_M_1000C_AHD;
+			if (sky2->advertising & ADVERTISED_100baseT_Full)
+				adv |= PHY_M_AN_100_FD;
+			if (sky2->advertising & ADVERTISED_100baseT_Half)
+				adv |= PHY_M_AN_100_HD;
+			if (sky2->advertising & ADVERTISED_10baseT_Full)
+				adv |= PHY_M_AN_10_FD;
+			if (sky2->advertising & ADVERTISED_10baseT_Half)
+				adv |= PHY_M_AN_10_HD;
+		} else		/* special defines for FIBER (88E1011S only) */
+			adv |= PHY_M_AN_1000X_AHD | PHY_M_AN_1000X_AFD;
+
+		/* Set Flow-control capabilities */
+		if (sky2->tx_pause && sky2->rx_pause)
+			adv |= PHY_AN_PAUSE_CAP;	/* symmetric */
+		else if (sky2->rx_pause && !sky2->tx_pause)
+			adv |= PHY_AN_PAUSE_ASYM | PHY_AN_PAUSE_CAP;
+		else if (!sky2->rx_pause && sky2->tx_pause)
+			adv |= PHY_AN_PAUSE_ASYM;	/* local */
+
+		/* Restart Auto-negotiation */
+		ctrl |= PHY_CT_ANE | PHY_CT_RE_CFG;
+	} else {
+		/* forced speed/duplex settings */
+		ct1000 = PHY_M_1000C_MSE;
+
+		if (sky2->duplex == DUPLEX_FULL)
+			ctrl |= PHY_CT_DUP_MD;
+
+		switch (sky2->speed) {
+		case SPEED_1000:
+			ctrl |= PHY_CT_SP1000;
+			break;
+		case SPEED_100:
+			ctrl |= PHY_CT_SP100;
+			break;
+		}
+
+		ctrl |= PHY_CT_RESET;
+	}
+
+	if (hw->chip_id != CHIP_ID_YUKON_FE)
+		gm_phy_write(hw, port, PHY_MARV_1000T_CTRL, ct1000);
+
+	gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, adv);
+	gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl);
+
+	/* Setup Phy LED's */
+	ledctrl = PHY_M_LED_PULS_DUR(PULS_170MS);
+	ledover = 0;
+
+	switch (hw->chip_id) {
+	case CHIP_ID_YUKON_FE:
+		/* on 88E3082 these bits are at 11..9 (shifted left) */
+		ledctrl |= PHY_M_LED_BLINK_RT(BLINK_84MS) << 1;
+
+		ctrl = gm_phy_read(hw, port, PHY_MARV_FE_LED_PAR);
+
+		/* delete ACT LED control bits */
+		ctrl &= ~PHY_M_FELP_LED1_MSK;
+		/* change ACT LED control to blink mode */
+		ctrl |= PHY_M_FELP_LED1_CTRL(LED_PAR_CTRL_ACT_BL);
+		gm_phy_write(hw, port, PHY_MARV_FE_LED_PAR, ctrl);
+		break;
+
+	case CHIP_ID_YUKON_XL:
+		pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR);
+
+		/* select page 3 to access LED control register */
+		gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3);
+
+		/* set LED Function Control register */
+		gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, (PHY_M_LEDC_LOS_CTRL(1) |	/* LINK/ACT */
+							   PHY_M_LEDC_INIT_CTRL(7) |	/* 10 Mbps */
+							   PHY_M_LEDC_STA1_CTRL(7) |	/* 100 Mbps */
+							   PHY_M_LEDC_STA0_CTRL(7)));	/* 1000 Mbps */
+
+		/* set Polarity Control register */
+		gm_phy_write(hw, port, PHY_MARV_PHY_STAT,
+			     (PHY_M_POLC_LS1_P_MIX(4) |
+			      PHY_M_POLC_IS0_P_MIX(4) |
+			      PHY_M_POLC_LOS_CTRL(2) |
+			      PHY_M_POLC_INIT_CTRL(2) |
+			      PHY_M_POLC_STA1_CTRL(2) |
+			      PHY_M_POLC_STA0_CTRL(2)));
+
+		/* restore page register */
+		gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg);
+		break;
+
+	default:
+		/* set Tx LED (LED_TX) to blink mode on Rx OR Tx activity */
+		ledctrl |= PHY_M_LED_BLINK_RT(BLINK_84MS) | PHY_M_LEDC_TX_CTRL;
+		/* turn off the Rx LED (LED_RX) */
+		ledover |= PHY_M_LED_MO_RX(MO_LED_OFF);
+	}
+
+	gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl);
+
+	if (sky2->autoneg == AUTONEG_DISABLE || sky2->speed == SPEED_100) {
+		/* turn on 100 Mbps LED (LED_LINK100) */
+		ledover |= PHY_M_LED_MO_100(MO_LED_ON);
+	}
+
+	if (ledover)
+		gm_phy_write(hw, port, PHY_MARV_LED_OVER, ledover);
+
+	/* Enable phy interrupt on auto-negotiation complete (or link up) */
+	if (sky2->autoneg == AUTONEG_ENABLE)
+		gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_AN_COMPL);
+	else
+		gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
+}
+
+/* Force a renegotiation */
+static void sky2_phy_reinit(struct sky2_port *sky2)
+{
+	down(&sky2->phy_sema);
+	sky2_phy_init(sky2->hw, sky2->port);
+	up(&sky2->phy_sema);
+}
+
+static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
+{
+	struct sky2_port *sky2 = netdev_priv(hw->dev[port]);
+	u16 reg;
+	int i;
+	const u8 *addr = hw->dev[port]->dev_addr;
+
+	sky2_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET);
+	sky2_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_CLR|GPC_ENA_PAUSE);
+
+	sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_CLR);
+
+	if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev == 0 && port == 1) {
+		/* WA DEV_472 -- looks like crossed wires on port 2 */
+		/* clear GMAC 1 Control reset */
+		sky2_write8(hw, SK_REG(0, GMAC_CTRL), GMC_RST_CLR);
+		do {
+			sky2_write8(hw, SK_REG(1, GMAC_CTRL), GMC_RST_SET);
+			sky2_write8(hw, SK_REG(1, GMAC_CTRL), GMC_RST_CLR);
+		} while (gm_phy_read(hw, 1, PHY_MARV_ID0) != PHY_MARV_ID0_VAL ||
+			 gm_phy_read(hw, 1, PHY_MARV_ID1) != PHY_MARV_ID1_Y2 ||
+			 gm_phy_read(hw, 1, PHY_MARV_INT_MASK) != 0);
+	}
+
+	if (sky2->autoneg == AUTONEG_DISABLE) {
+		reg = gma_read16(hw, port, GM_GP_CTRL);
+		reg |= GM_GPCR_AU_ALL_DIS;
+		gma_write16(hw, port, GM_GP_CTRL, reg);
+		gma_read16(hw, port, GM_GP_CTRL);
+
+		switch (sky2->speed) {
+		case SPEED_1000:
+			reg |= GM_GPCR_SPEED_1000;
+			/* fallthru */
+		case SPEED_100:
+			reg |= GM_GPCR_SPEED_100;
+		}
+
+		if (sky2->duplex == DUPLEX_FULL)
+			reg |= GM_GPCR_DUP_FULL;
+	} else
+		reg = GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100 | GM_GPCR_DUP_FULL;
+
+	if (!sky2->tx_pause && !sky2->rx_pause) {
+		sky2_write32(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF);
+		reg |=
+		    GM_GPCR_FC_TX_DIS | GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS;
+	} else if (sky2->tx_pause && !sky2->rx_pause) {
+		/* disable Rx flow-control */
+		reg |= GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS;
+	}
+
+	gma_write16(hw, port, GM_GP_CTRL, reg);
+
+	sky2_read16(hw, SK_REG(port, GMAC_IRQ_SRC));
+
+	down(&sky2->phy_sema);
+	sky2_phy_init(hw, port);
+	up(&sky2->phy_sema);
+
+	/* MIB clear */
+	reg = gma_read16(hw, port, GM_PHY_ADDR);
+	gma_write16(hw, port, GM_PHY_ADDR, reg | GM_PAR_MIB_CLR);
+
+	for (i = 0; i < GM_MIB_CNT_SIZE; i++)
+		gma_read16(hw, port, GM_MIB_CNT_BASE + 8 * i);
+	gma_write16(hw, port, GM_PHY_ADDR, reg);
+
+	/* transmit control */
+	gma_write16(hw, port, GM_TX_CTRL, TX_COL_THR(TX_COL_DEF));
+
+	/* receive control reg: unicast + multicast + no FCS  */
+	gma_write16(hw, port, GM_RX_CTRL,
+		    GM_RXCR_UCF_ENA | GM_RXCR_CRC_DIS | GM_RXCR_MCF_ENA);
+
+	/* transmit flow control */
+	gma_write16(hw, port, GM_TX_FLOW_CTRL, 0xffff);
+
+	/* transmit parameter */
+	gma_write16(hw, port, GM_TX_PARAM,
+		    TX_JAM_LEN_VAL(TX_JAM_LEN_DEF) |
+		    TX_JAM_IPG_VAL(TX_JAM_IPG_DEF) |
+		    TX_IPG_JAM_DATA(TX_IPG_JAM_DEF) |
+		    TX_BACK_OFF_LIM(TX_BOF_LIM_DEF));
+
+	/* serial mode register */
+	reg = DATA_BLIND_VAL(DATA_BLIND_DEF) |
+		GM_SMOD_VLAN_ENA | IPG_DATA_VAL(IPG_DATA_DEF);
+
+	if (hw->dev[port]->mtu > ETH_DATA_LEN)
+		reg |= GM_SMOD_JUMBO_ENA;
+
+	gma_write16(hw, port, GM_SERIAL_MODE, reg);
+
+	/* virtual address for data */
+	gma_set_addr(hw, port, GM_SRC_ADDR_2L, addr);
+
+	/* physical address: used for pause frames */
+	gma_set_addr(hw, port, GM_SRC_ADDR_1L, addr);
+
+	/* ignore counter overflows */
+	gma_write16(hw, port, GM_TX_IRQ_MSK, 0);
+	gma_write16(hw, port, GM_RX_IRQ_MSK, 0);
+	gma_write16(hw, port, GM_TR_IRQ_MSK, 0);
+
+	/* Configure Rx MAC FIFO */
+	sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR);
+	sky2_write16(hw, SK_REG(port, RX_GMF_CTRL_T),
+		     GMF_RX_CTRL_DEF);
+
+	/* Flush Rx MAC FIFO on any flow control or error */
+	sky2_write16(hw, SK_REG(port, RX_GMF_FL_MSK), GMR_FS_ANY_ERR);
+
+	/* Set threshold to 0xa (64 bytes)
+	 *  ASF disabled so no need to do WA dev #4.30
+	 */
+	sky2_write16(hw, SK_REG(port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF);
+
+	/* Configure Tx MAC FIFO */
+	sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_CLR);
+	sky2_write16(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_OPER_ON);
+
+	if (hw->chip_id == CHIP_ID_YUKON_EC_U) {
+		sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 768/8);
+		sky2_write8(hw, SK_REG(port, RX_GMF_UP_THR), 1024/8);
+		if (hw->dev[port]->mtu > ETH_DATA_LEN) {
+			/* set Tx GMAC FIFO Almost Empty Threshold */
+			sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR), 0x180);
+			/* Disable Store & Forward mode for TX */
+			sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_STFW_DIS);
+		}
+	}
+
+}
+
+static void sky2_ramset(struct sky2_hw *hw, u16 q, u32 start, size_t len)
+{
+	u32 end;
+
+	start /= 8;
+	len /= 8;
+	end = start + len - 1;
+
+	sky2_write8(hw, RB_ADDR(q, RB_CTRL), RB_RST_CLR);
+	sky2_write32(hw, RB_ADDR(q, RB_START), start);
+	sky2_write32(hw, RB_ADDR(q, RB_END), end);
+	sky2_write32(hw, RB_ADDR(q, RB_WP), start);
+	sky2_write32(hw, RB_ADDR(q, RB_RP), start);
+
+	if (q == Q_R1 || q == Q_R2) {
+		u32 rxup, rxlo;
+
+		rxlo = len/2;
+		rxup = rxlo + len/4;
+
+		/* Set thresholds on receive queue's */
+		sky2_write32(hw, RB_ADDR(q, RB_RX_UTPP), rxup);
+		sky2_write32(hw, RB_ADDR(q, RB_RX_LTPP), rxlo);
+	} else {
+		/* Enable store & forward on Tx queue's because
+		 * Tx FIFO is only 1K on Yukon
+		 */
+		sky2_write8(hw, RB_ADDR(q, RB_CTRL), RB_ENA_STFWD);
+	}
+
+	sky2_write8(hw, RB_ADDR(q, RB_CTRL), RB_ENA_OP_MD);
+	sky2_read8(hw, RB_ADDR(q, RB_CTRL));
+}
+
+/* Setup Bus Memory Interface */
+static void sky2_qset(struct sky2_hw *hw, u16 q)
+{
+	sky2_write32(hw, Q_ADDR(q, Q_CSR), BMU_CLR_RESET);
+	sky2_write32(hw, Q_ADDR(q, Q_CSR), BMU_OPER_INIT);
+	sky2_write32(hw, Q_ADDR(q, Q_CSR), BMU_FIFO_OP_ON);
+	sky2_write32(hw, Q_ADDR(q, Q_WM),  BMU_WM_DEFAULT);
+}
+
+/* Setup prefetch unit registers. This is the interface between
+ * hardware and driver list elements
+ */
+static void sky2_prefetch_init(struct sky2_hw *hw, u32 qaddr,
+				      u64 addr, u32 last)
+{
+	sky2_write32(hw, Y2_QADDR(qaddr, PREF_UNIT_CTRL), PREF_UNIT_RST_SET);
+	sky2_write32(hw, Y2_QADDR(qaddr, PREF_UNIT_CTRL), PREF_UNIT_RST_CLR);
+	sky2_write32(hw, Y2_QADDR(qaddr, PREF_UNIT_ADDR_HI), addr >> 32);
+	sky2_write32(hw, Y2_QADDR(qaddr, PREF_UNIT_ADDR_LO), (u32) addr);
+	sky2_write16(hw, Y2_QADDR(qaddr, PREF_UNIT_LAST_IDX), last);
+	sky2_write32(hw, Y2_QADDR(qaddr, PREF_UNIT_CTRL), PREF_UNIT_OP_ON);
+
+	sky2_read32(hw, Y2_QADDR(qaddr, PREF_UNIT_CTRL));
+}
+
+static inline struct sky2_tx_le *get_tx_le(struct sky2_port *sky2)
+{
+	struct sky2_tx_le *le = sky2->tx_le + sky2->tx_prod;
+
+	sky2->tx_prod = (sky2->tx_prod + 1) % TX_RING_SIZE;
+	return le;
+}
+
+/*
+ * This is a workaround code taken from SysKonnect sk98lin driver
+ * to deal with chip bug on Yukon EC rev 0 in the wraparound case.
+ */
+static inline void sky2_put_idx(struct sky2_hw *hw, unsigned q,
+				u16 idx, u16 *last, u16 size)
+{
+	if (is_ec_a1(hw) && idx < *last) {
+		u16 hwget = sky2_read16(hw, Y2_QADDR(q, PREF_UNIT_GET_IDX));
+
+		if (hwget == 0) {
+			/* Start prefetching again */
+			sky2_write8(hw, Y2_QADDR(q, PREF_UNIT_FIFO_WM), 0xe0);
+			goto setnew;
+		}
+
+		if (hwget == size - 1) {
+			/* set watermark to one list element */
+			sky2_write8(hw, Y2_QADDR(q, PREF_UNIT_FIFO_WM), 8);
+
+			/* set put index to first list element */
+			sky2_write16(hw, Y2_QADDR(q, PREF_UNIT_PUT_IDX), 0);
+		} else		/* have hardware go to end of list */
+			sky2_write16(hw, Y2_QADDR(q, PREF_UNIT_PUT_IDX),
+				     size - 1);
+	} else {
+setnew:
+		sky2_write16(hw, Y2_QADDR(q, PREF_UNIT_PUT_IDX), idx);
+	}
+	*last = idx;
+}
+
+
+static inline struct sky2_rx_le *sky2_next_rx(struct sky2_port *sky2)
+{
+	struct sky2_rx_le *le = sky2->rx_le + sky2->rx_put;
+	sky2->rx_put = (sky2->rx_put + 1) % RX_LE_SIZE;
+	return le;
+}
+
+/* Return high part of DMA address (could be 32 or 64 bit) */
+static inline u32 high32(dma_addr_t a)
+{
+	return (a >> 16) >> 16;
+}
+
+/* Build description to hardware about buffer */
+static inline void sky2_rx_add(struct sky2_port *sky2, dma_addr_t map)
+{
+	struct sky2_rx_le *le;
+	u32 hi = high32(map);
+	u16 len = sky2->rx_bufsize;
+
+	if (sky2->rx_addr64 != hi) {
+		le = sky2_next_rx(sky2);
+		le->addr = cpu_to_le32(hi);
+		le->ctrl = 0;
+		le->opcode = OP_ADDR64 | HW_OWNER;
+		sky2->rx_addr64 = high32(map + len);
+	}
+
+	le = sky2_next_rx(sky2);
+	le->addr = cpu_to_le32((u32) map);
+	le->length = cpu_to_le16(len);
+	le->ctrl = 0;
+	le->opcode = OP_PACKET | HW_OWNER;
+}
+
+
+/* Tell chip where to start receive checksum.
+ * Actually has two checksums, but set both same to avoid possible byte
+ * order problems.
+ */
+static void rx_set_checksum(struct sky2_port *sky2)
+{
+	struct sky2_rx_le *le;
+
+	le = sky2_next_rx(sky2);
+	le->addr = (ETH_HLEN << 16) | ETH_HLEN;
+	le->ctrl = 0;
+	le->opcode = OP_TCPSTART | HW_OWNER;
+
+	sky2_write32(sky2->hw,
+		     Q_ADDR(rxqaddr[sky2->port], Q_CSR),
+		     sky2->rx_csum ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM);
+
+}
+
+/*
+ * The RX Stop command will not work for Yukon-2 if the BMU does not
+ * reach the end of packet and since we can't make sure that we have
+ * incoming data, we must reset the BMU while it is not doing a DMA
+ * transfer. Since it is possible that the RX path is still active,
+ * the RX RAM buffer will be stopped first, so any possible incoming
+ * data will not trigger a DMA. After the RAM buffer is stopped, the
+ * BMU is polled until any DMA in progress is ended and only then it
+ * will be reset.
+ */
+static void sky2_rx_stop(struct sky2_port *sky2)
+{
+	struct sky2_hw *hw = sky2->hw;
+	unsigned rxq = rxqaddr[sky2->port];
+	int i;
+
+	/* disable the RAM Buffer receive queue */
+	sky2_write8(hw, RB_ADDR(rxq, RB_CTRL), RB_DIS_OP_MD);
+
+	for (i = 0; i < 0xffff; i++)
+		if (sky2_read8(hw, RB_ADDR(rxq, Q_RSL))
+		    == sky2_read8(hw, RB_ADDR(rxq, Q_RL)))
+			goto stopped;
+
+	printk(KERN_WARNING PFX "%s: receiver stop failed\n",
+	       sky2->netdev->name);
+stopped:
+	sky2_write32(hw, Q_ADDR(rxq, Q_CSR), BMU_RST_SET | BMU_FIFO_RST);
+
+	/* reset the Rx prefetch unit */
+	sky2_write32(hw, Y2_QADDR(rxq, PREF_UNIT_CTRL), PREF_UNIT_RST_SET);
+}
+
+/* Clean out receive buffer area, assumes receiver hardware stopped */
+static void sky2_rx_clean(struct sky2_port *sky2)
+{
+	unsigned i;
+
+	memset(sky2->rx_le, 0, RX_LE_BYTES);
+	for (i = 0; i < sky2->rx_pending; i++) {
+		struct ring_info *re = sky2->rx_ring + i;
+
+		if (re->skb) {
+			pci_unmap_single(sky2->hw->pdev,
+					 re->mapaddr, sky2->rx_bufsize,
+					 PCI_DMA_FROMDEVICE);
+			kfree_skb(re->skb);
+			re->skb = NULL;
+		}
+	}
+}
+
+/* Basic MII support */
+static int sky2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+	struct mii_ioctl_data *data = if_mii(ifr);
+	struct sky2_port *sky2 = netdev_priv(dev);
+	struct sky2_hw *hw = sky2->hw;
+	int err = -EOPNOTSUPP;
+
+	if (!netif_running(dev))
+		return -ENODEV;	/* Phy still in reset */
+
+	switch(cmd) {
+	case SIOCGMIIPHY:
+		data->phy_id = PHY_ADDR_MARV;
+
+		/* fallthru */
+	case SIOCGMIIREG: {
+		u16 val = 0;
+
+		down(&sky2->phy_sema);
+		err = __gm_phy_read(hw, sky2->port, data->reg_num & 0x1f, &val);
+		up(&sky2->phy_sema);
+
+		data->val_out = val;
+		break;
+	}
+
+	case SIOCSMIIREG:
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
+
+		down(&sky2->phy_sema);
+		err = gm_phy_write(hw, sky2->port, data->reg_num & 0x1f,
+				   data->val_in);
+		up(&sky2->phy_sema);
+		break;
+	}
+	return err;
+}
+
+#ifdef SKY2_VLAN_TAG_USED
+static void sky2_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
+{
+	struct sky2_port *sky2 = netdev_priv(dev);
+	struct sky2_hw *hw = sky2->hw;
+	u16 port = sky2->port;
+
+	spin_lock(&sky2->tx_lock);
+
+	sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), RX_VLAN_STRIP_ON);
+	sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_VLAN_TAG_ON);
+	sky2->vlgrp = grp;
+
+	spin_unlock(&sky2->tx_lock);
+}
+
+static void sky2_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
+{
+	struct sky2_port *sky2 = netdev_priv(dev);
+	struct sky2_hw *hw = sky2->hw;
+	u16 port = sky2->port;
+
+	spin_lock(&sky2->tx_lock);
+
+	sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), RX_VLAN_STRIP_OFF);
+	sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_VLAN_TAG_OFF);
+	if (sky2->vlgrp)
+		sky2->vlgrp->vlan_devices[vid] = NULL;
+
+	spin_unlock(&sky2->tx_lock);
+}
+#endif
+
+/*
+ * Allocate and setup receiver buffer pool.
+ * In case of 64 bit dma, there are 2X as many list elements
+ * available as ring entries
+ * and need to reserve one list element so we don't wrap around.
+ *
+ * It appears the hardware has a bug in the FIFO logic that
+ * cause it to hang if the FIFO gets overrun and the receive buffer
+ * is not aligned.  This means we can't use skb_reserve to align
+ * the IP header.
+ */
+static int sky2_rx_start(struct sky2_port *sky2)
+{
+	struct sky2_hw *hw = sky2->hw;
+	unsigned rxq = rxqaddr[sky2->port];
+	int i;
+
+	sky2->rx_put = sky2->rx_next = 0;
+	sky2_qset(hw, rxq);
+	sky2_prefetch_init(hw, rxq, sky2->rx_le_map, RX_LE_SIZE - 1);
+
+	rx_set_checksum(sky2);
+	for (i = 0; i < sky2->rx_pending; i++) {
+		struct ring_info *re = sky2->rx_ring + i;
+
+		re->skb = dev_alloc_skb(sky2->rx_bufsize);
+		if (!re->skb)
+			goto nomem;
+
+		re->mapaddr = pci_map_single(hw->pdev, re->skb->data,
+					     sky2->rx_bufsize, PCI_DMA_FROMDEVICE);
+		sky2_rx_add(sky2, re->mapaddr);
+	}
+
+	/* Tell chip about available buffers */
+	sky2_write16(hw, Y2_QADDR(rxq, PREF_UNIT_PUT_IDX), sky2->rx_put);
+	sky2->rx_last_put = sky2_read16(hw, Y2_QADDR(rxq, PREF_UNIT_PUT_IDX));
+	return 0;
+nomem:
+	sky2_rx_clean(sky2);
+	return -ENOMEM;
+}
+
+/* Bring up network interface. */
+static int sky2_up(struct net_device *dev)
+{
+	struct sky2_port *sky2 = netdev_priv(dev);
+	struct sky2_hw *hw = sky2->hw;
+	unsigned port = sky2->port;
+	u32 ramsize, rxspace;
+	int err = -ENOMEM;
+
+	if (netif_msg_ifup(sky2))
+		printk(KERN_INFO PFX "%s: enabling interface\n", dev->name);
+
+	/* must be power of 2 */
+	sky2->tx_le = pci_alloc_consistent(hw->pdev,
+					   TX_RING_SIZE *
+					   sizeof(struct sky2_tx_le),
+					   &sky2->tx_le_map);
+	if (!sky2->tx_le)
+		goto err_out;
+
+	sky2->tx_ring = kcalloc(TX_RING_SIZE, sizeof(struct tx_ring_info),
+				GFP_KERNEL);
+	if (!sky2->tx_ring)
+		goto err_out;
+	sky2->tx_prod = sky2->tx_cons = 0;
+
+	sky2->rx_le = pci_alloc_consistent(hw->pdev, RX_LE_BYTES,
+					   &sky2->rx_le_map);
+	if (!sky2->rx_le)
+		goto err_out;
+	memset(sky2->rx_le, 0, RX_LE_BYTES);
+
+	sky2->rx_ring = kcalloc(sky2->rx_pending, sizeof(struct ring_info),
+				GFP_KERNEL);
+	if (!sky2->rx_ring)
+		goto err_out;
+
+	sky2_mac_init(hw, port);
+
+	/* Configure RAM buffers */
+	if (hw->chip_id == CHIP_ID_YUKON_FE ||
+	    (hw->chip_id == CHIP_ID_YUKON_EC && hw->chip_rev == 2))
+		ramsize = 4096;
+	else {
+		u8 e0 = sky2_read8(hw, B2_E_0);
+		ramsize = (e0 == 0) ? (128 * 1024) : (e0 * 4096);
+	}
+
+	/* 2/3 for Rx */
+	rxspace = (2 * ramsize) / 3;
+	sky2_ramset(hw, rxqaddr[port], 0, rxspace);
+	sky2_ramset(hw, txqaddr[port], rxspace, ramsize - rxspace);
+
+	/* Make sure SyncQ is disabled */
+	sky2_write8(hw, RB_ADDR(port == 0 ? Q_XS1 : Q_XS2, RB_CTRL),
+		    RB_RST_SET);
+
+	sky2_qset(hw, txqaddr[port]);
+	if (hw->chip_id == CHIP_ID_YUKON_EC_U)
+		sky2_write16(hw, Q_ADDR(txqaddr[port], Q_AL), 0x1a0);
+
+
+	sky2_prefetch_init(hw, txqaddr[port], sky2->tx_le_map,
+			   TX_RING_SIZE - 1);
+
+	err = sky2_rx_start(sky2);
+	if (err)
+		goto err_out;
+
+	/* Enable interrupts from phy/mac for port */
+	hw->intr_mask |= (port == 0) ? Y2_IS_PORT_1 : Y2_IS_PORT_2;
+	sky2_write32(hw, B0_IMSK, hw->intr_mask);
+	return 0;
+
+err_out:
+	if (sky2->rx_le) {
+		pci_free_consistent(hw->pdev, RX_LE_BYTES,
+				    sky2->rx_le, sky2->rx_le_map);
+		sky2->rx_le = NULL;
+	}
+	if (sky2->tx_le) {
+		pci_free_consistent(hw->pdev,
+				    TX_RING_SIZE * sizeof(struct sky2_tx_le),
+				    sky2->tx_le, sky2->tx_le_map);
+		sky2->tx_le = NULL;
+	}
+	kfree(sky2->tx_ring);
+	kfree(sky2->rx_ring);
+
+	sky2->tx_ring = NULL;
+	sky2->rx_ring = NULL;
+	return err;
+}
+
+/* Modular subtraction in ring */
+static inline int tx_dist(unsigned tail, unsigned head)
+{
+	return (head - tail) % TX_RING_SIZE;
+}
+
+/* Number of list elements available for next tx */
+static inline int tx_avail(const struct sky2_port *sky2)
+{
+	return sky2->tx_pending - tx_dist(sky2->tx_cons, sky2->tx_prod);
+}
+
+/* Estimate of number of transmit list elements required */
+static inline unsigned tx_le_req(const struct sk_buff *skb)
+{
+	unsigned count;
+
+	count = sizeof(dma_addr_t) / sizeof(u32);
+	count += skb_shinfo(skb)->nr_frags * count;
+
+	if (skb_shinfo(skb)->tso_size)
+		++count;
+
+	if (skb->ip_summed == CHECKSUM_HW)
+		++count;
+
+	return count;
+}
+
+/*
+ * Put one packet in ring for transmit.
+ * A single packet can generate multiple list elements, and
+ * the number of ring elements will probably be less than the number
+ * of list elements used.
+ *
+ * No BH disabling for tx_lock here (like tg3)
+ */
+static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
+{
+	struct sky2_port *sky2 = netdev_priv(dev);
+	struct sky2_hw *hw = sky2->hw;
+	struct sky2_tx_le *le = NULL;
+	struct tx_ring_info *re;
+	unsigned i, len;
+	dma_addr_t mapping;
+	u32 addr64;
+	u16 mss;
+	u8 ctrl;
+
+	if (!spin_trylock(&sky2->tx_lock))
+		return NETDEV_TX_LOCKED;
+
+	if (unlikely(tx_avail(sky2) < tx_le_req(skb))) {
+		/* There is a known but harmless race with lockless tx
+		 * and netif_stop_queue.
+		 */
+		if (!netif_queue_stopped(dev)) {
+			netif_stop_queue(dev);
+			printk(KERN_WARNING PFX "%s: ring full when queue awake!\n",
+			       dev->name);
+		}
+		spin_unlock(&sky2->tx_lock);
+
+		return NETDEV_TX_BUSY;
+	}
+
+	if (unlikely(netif_msg_tx_queued(sky2)))
+		printk(KERN_DEBUG "%s: tx queued, slot %u, len %d\n",
+		       dev->name, sky2->tx_prod, skb->len);
+
+	len = skb_headlen(skb);
+	mapping = pci_map_single(hw->pdev, skb->data, len, PCI_DMA_TODEVICE);
+	addr64 = high32(mapping);
+
+	re = sky2->tx_ring + sky2->tx_prod;
+
+	/* Send high bits if changed or crosses boundary */
+	if (addr64 != sky2->tx_addr64 || high32(mapping + len) != sky2->tx_addr64) {
+		le = get_tx_le(sky2);
+		le->tx.addr = cpu_to_le32(addr64);
+		le->ctrl = 0;
+		le->opcode = OP_ADDR64 | HW_OWNER;
+		sky2->tx_addr64 = high32(mapping + len);
+	}
+
+	/* Check for TCP Segmentation Offload */
+	mss = skb_shinfo(skb)->tso_size;
+	if (mss != 0) {
+		/* just drop the packet if non-linear expansion fails */
+		if (skb_header_cloned(skb) &&
+		    pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
+			dev_kfree_skb_any(skb);
+			goto out_unlock;
+		}
+
+		mss += ((skb->h.th->doff - 5) * 4);	/* TCP options */
+		mss += (skb->nh.iph->ihl * 4) + sizeof(struct tcphdr);
+		mss += ETH_HLEN;
+	}
+
+	if (mss != sky2->tx_last_mss) {
+		le = get_tx_le(sky2);
+		le->tx.tso.size = cpu_to_le16(mss);
+		le->tx.tso.rsvd = 0;
+		le->opcode = OP_LRGLEN | HW_OWNER;
+		le->ctrl = 0;
+		sky2->tx_last_mss = mss;
+	}
+
+	ctrl = 0;
+#ifdef SKY2_VLAN_TAG_USED
+	/* Add VLAN tag, can piggyback on LRGLEN or ADDR64 */
+	if (sky2->vlgrp && vlan_tx_tag_present(skb)) {
+		if (!le) {
+			le = get_tx_le(sky2);
+			le->tx.addr = 0;
+			le->opcode = OP_VLAN|HW_OWNER;
+			le->ctrl = 0;
+		} else
+			le->opcode |= OP_VLAN;
+		le->length = cpu_to_be16(vlan_tx_tag_get(skb));
+		ctrl |= INS_VLAN;
+	}
+#endif
+
+	/* Handle TCP checksum offload */
+	if (skb->ip_summed == CHECKSUM_HW) {
+		u16 hdr = skb->h.raw - skb->data;
+		u16 offset = hdr + skb->csum;
+
+		ctrl = CALSUM | WR_SUM | INIT_SUM | LOCK_SUM;
+		if (skb->nh.iph->protocol == IPPROTO_UDP)
+			ctrl |= UDPTCP;
+
+		le = get_tx_le(sky2);
+		le->tx.csum.start = cpu_to_le16(hdr);
+		le->tx.csum.offset = cpu_to_le16(offset);
+		le->length = 0;	/* initial checksum value */
+		le->ctrl = 1;	/* one packet */
+		le->opcode = OP_TCPLISW | HW_OWNER;
+	}
+
+	le = get_tx_le(sky2);
+	le->tx.addr = cpu_to_le32((u32) mapping);
+	le->length = cpu_to_le16(len);
+	le->ctrl = ctrl;
+	le->opcode = mss ? (OP_LARGESEND | HW_OWNER) : (OP_PACKET | HW_OWNER);
+
+	/* Record the transmit mapping info */
+	re->skb = skb;
+	pci_unmap_addr_set(re, mapaddr, mapping);
+
+	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+		struct tx_ring_info *fre;
+
+		mapping = pci_map_page(hw->pdev, frag->page, frag->page_offset,
+				       frag->size, PCI_DMA_TODEVICE);
+		addr64 = (mapping >> 16) >> 16;
+		if (addr64 != sky2->tx_addr64) {
+			le = get_tx_le(sky2);
+			le->tx.addr = cpu_to_le32(addr64);
+			le->ctrl = 0;
+			le->opcode = OP_ADDR64 | HW_OWNER;
+			sky2->tx_addr64 = addr64;
+		}
+
+		le = get_tx_le(sky2);
+		le->tx.addr = cpu_to_le32((u32) mapping);
+		le->length = cpu_to_le16(frag->size);
+		le->ctrl = ctrl;
+		le->opcode = OP_BUFFER | HW_OWNER;
+
+		fre = sky2->tx_ring
+		    + ((re - sky2->tx_ring) + i + 1) % TX_RING_SIZE;
+		pci_unmap_addr_set(fre, mapaddr, mapping);
+	}
+
+	re->idx = sky2->tx_prod;
+	le->ctrl |= EOP;
+
+	sky2_put_idx(hw, txqaddr[sky2->port], sky2->tx_prod,
+		     &sky2->tx_last_put, TX_RING_SIZE);
+
+	if (tx_avail(sky2) <= MAX_SKB_TX_LE)
+		netif_stop_queue(dev);
+
+out_unlock:
+	mmiowb();
+	spin_unlock(&sky2->tx_lock);
+
+	dev->trans_start = jiffies;
+	return NETDEV_TX_OK;
+}
+
+/*
+ * Free ring elements from starting at tx_cons until "done"
+ *
+ * NB: the hardware will tell us about partial completion of multi-part
+ *     buffers; these are deferred until completion.
+ */
+static void sky2_tx_complete(struct sky2_port *sky2, u16 done)
+{
+	struct net_device *dev = sky2->netdev;
+	struct pci_dev *pdev = sky2->hw->pdev;
+	u16 nxt, put;
+	unsigned i;
+
+	BUG_ON(done >= TX_RING_SIZE);
+
+	if (unlikely(netif_msg_tx_done(sky2)))
+		printk(KERN_DEBUG "%s: tx done, up to %u\n",
+		       dev->name, done);
+
+	for (put = sky2->tx_cons; put != done; put = nxt) {
+		struct tx_ring_info *re = sky2->tx_ring + put;
+		struct sk_buff *skb = re->skb;
+
+  		nxt = re->idx;
+		BUG_ON(nxt >= TX_RING_SIZE);
+		prefetch(sky2->tx_ring + nxt);
+
+		/* Check for partial status */
+		if (tx_dist(put, done) < tx_dist(put, nxt))
+			break;
+
+		skb = re->skb;
+		pci_unmap_single(pdev, pci_unmap_addr(re, mapaddr),
+				 skb_headlen(skb), PCI_DMA_TODEVICE);
+
+		for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+			struct tx_ring_info *fre;
+			fre = sky2->tx_ring + (put + i + 1) % TX_RING_SIZE;
+			pci_unmap_page(pdev, pci_unmap_addr(fre, mapaddr),
+  				       skb_shinfo(skb)->frags[i].size,
+				       PCI_DMA_TODEVICE);
+		}
+
+		dev_kfree_skb_any(skb);
+	}
+
+	spin_lock(&sky2->tx_lock);
+	sky2->tx_cons = put;
+	if (netif_queue_stopped(dev) && tx_avail(sky2) > MAX_SKB_TX_LE)
+		netif_wake_queue(dev);
+	spin_unlock(&sky2->tx_lock);
+}
+
+/* Cleanup all untransmitted buffers, assume transmitter not running */
+static void sky2_tx_clean(struct sky2_port *sky2)
+{
+	sky2_tx_complete(sky2, sky2->tx_prod);
+}
+
+/* Network shutdown */
+static int sky2_down(struct net_device *dev)
+{
+	struct sky2_port *sky2 = netdev_priv(dev);
+	struct sky2_hw *hw = sky2->hw;
+	unsigned port = sky2->port;
+	u16 ctrl;
+
+	/* Never really got started! */
+	if (!sky2->tx_le)
+		return 0;
+
+	if (netif_msg_ifdown(sky2))
+		printk(KERN_INFO PFX "%s: disabling interface\n", dev->name);
+
+	/* Stop more packets from being queued */
+	netif_stop_queue(dev);
+
+	/* Disable port IRQ */
+	local_irq_disable();
+	hw->intr_mask &= ~((sky2->port == 0) ? Y2_IS_IRQ_PHY1 : Y2_IS_IRQ_PHY2);
+	sky2_write32(hw, B0_IMSK, hw->intr_mask);
+	local_irq_enable();
+
+	flush_scheduled_work();
+
+	sky2_phy_reset(hw, port);
+
+	/* Stop transmitter */
+	sky2_write32(hw, Q_ADDR(txqaddr[port], Q_CSR), BMU_STOP);
+	sky2_read32(hw, Q_ADDR(txqaddr[port], Q_CSR));
+
+	sky2_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL),
+		     RB_RST_SET | RB_DIS_OP_MD);
+
+	ctrl = gma_read16(hw, port, GM_GP_CTRL);
+	ctrl &= ~(GM_GPCR_TX_ENA | GM_GPCR_RX_ENA);
+	gma_write16(hw, port, GM_GP_CTRL, ctrl);
+
+	sky2_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET);
+
+	/* Workaround shared GMAC reset */
+	if (!(hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev == 0
+	      && port == 0 && hw->dev[1] && netif_running(hw->dev[1])))
+		sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_SET);
+
+	/* Disable Force Sync bit and Enable Alloc bit */
+	sky2_write8(hw, SK_REG(port, TXA_CTRL),
+		    TXA_DIS_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC);
+
+	/* Stop Interval Timer and Limit Counter of Tx Arbiter */
+	sky2_write32(hw, SK_REG(port, TXA_ITI_INI), 0L);
+	sky2_write32(hw, SK_REG(port, TXA_LIM_INI), 0L);
+
+	/* Reset the PCI FIFO of the async Tx queue */
+	sky2_write32(hw, Q_ADDR(txqaddr[port], Q_CSR),
+		     BMU_RST_SET | BMU_FIFO_RST);
+
+	/* Reset the Tx prefetch units */
+	sky2_write32(hw, Y2_QADDR(txqaddr[port], PREF_UNIT_CTRL),
+		     PREF_UNIT_RST_SET);
+
+	sky2_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL), RB_RST_SET);
+
+	sky2_rx_stop(sky2);
+
+	sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET);
+	sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET);
+
+	/* turn off LED's */
+	sky2_write16(hw, B0_Y2LED, LED_STAT_OFF);
+
+	synchronize_irq(hw->pdev->irq);
+
+	sky2_tx_clean(sky2);
+	sky2_rx_clean(sky2);
+
+	pci_free_consistent(hw->pdev, RX_LE_BYTES,
+			    sky2->rx_le, sky2->rx_le_map);
+	kfree(sky2->rx_ring);
+
+	pci_free_consistent(hw->pdev,
+			    TX_RING_SIZE * sizeof(struct sky2_tx_le),
+			    sky2->tx_le, sky2->tx_le_map);
+	kfree(sky2->tx_ring);
+
+	sky2->tx_le = NULL;
+	sky2->rx_le = NULL;
+
+	sky2->rx_ring = NULL;
+	sky2->tx_ring = NULL;
+
+	return 0;
+}
+
+static u16 sky2_phy_speed(const struct sky2_hw *hw, u16 aux)
+{
+	if (!hw->copper)
+		return SPEED_1000;
+
+	if (hw->chip_id == CHIP_ID_YUKON_FE)
+		return (aux & PHY_M_PS_SPEED_100) ? SPEED_100 : SPEED_10;
+
+	switch (aux & PHY_M_PS_SPEED_MSK) {
+	case PHY_M_PS_SPEED_1000:
+		return SPEED_1000;
+	case PHY_M_PS_SPEED_100:
+		return SPEED_100;
+	default:
+		return SPEED_10;
+	}
+}
+
+static void sky2_link_up(struct sky2_port *sky2)
+{
+	struct sky2_hw *hw = sky2->hw;
+	unsigned port = sky2->port;
+	u16 reg;
+
+	/* Enable Transmit FIFO Underrun */
+	sky2_write8(hw, SK_REG(port, GMAC_IRQ_MSK), GMAC_DEF_MSK);
+
+	reg = gma_read16(hw, port, GM_GP_CTRL);
+	if (sky2->duplex == DUPLEX_FULL || sky2->autoneg == AUTONEG_ENABLE)
+		reg |= GM_GPCR_DUP_FULL;
+
+	/* enable Rx/Tx */
+	reg |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA;
+	gma_write16(hw, port, GM_GP_CTRL, reg);
+	gma_read16(hw, port, GM_GP_CTRL);
+
+	gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
+
+	netif_carrier_on(sky2->netdev);
+	netif_wake_queue(sky2->netdev);
+
+	/* Turn on link LED */
+	sky2_write8(hw, SK_REG(port, LNK_LED_REG),
+		    LINKLED_ON | LINKLED_BLINK_OFF | LINKLED_LINKSYNC_OFF);
+
+	if (hw->chip_id == CHIP_ID_YUKON_XL) {
+		u16 pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR);
+
+		gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3);
+		gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, PHY_M_LEDC_LOS_CTRL(1) |	/* LINK/ACT */
+			     PHY_M_LEDC_INIT_CTRL(sky2->speed ==
+						  SPEED_10 ? 7 : 0) |
+			     PHY_M_LEDC_STA1_CTRL(sky2->speed ==
+						  SPEED_100 ? 7 : 0) |
+			     PHY_M_LEDC_STA0_CTRL(sky2->speed ==
+						  SPEED_1000 ? 7 : 0));
+		gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg);
+	}
+
+	if (netif_msg_link(sky2))
+		printk(KERN_INFO PFX
+		       "%s: Link is up at %d Mbps, %s duplex, flow control %s\n",
+		       sky2->netdev->name, sky2->speed,
+		       sky2->duplex == DUPLEX_FULL ? "full" : "half",
+		       (sky2->tx_pause && sky2->rx_pause) ? "both" :
+		       sky2->tx_pause ? "tx" : sky2->rx_pause ? "rx" : "none");
+}
+
+static void sky2_link_down(struct sky2_port *sky2)
+{
+	struct sky2_hw *hw = sky2->hw;
+	unsigned port = sky2->port;
+	u16 reg;
+
+	gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0);
+
+	reg = gma_read16(hw, port, GM_GP_CTRL);
+	reg &= ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA);
+	gma_write16(hw, port, GM_GP_CTRL, reg);
+	gma_read16(hw, port, GM_GP_CTRL);	/* PCI post */
+
+	if (sky2->rx_pause && !sky2->tx_pause) {
+		/* restore Asymmetric Pause bit */
+		gm_phy_write(hw, port, PHY_MARV_AUNE_ADV,
+			     gm_phy_read(hw, port, PHY_MARV_AUNE_ADV)
+			     | PHY_M_AN_ASP);
+	}
+
+	netif_carrier_off(sky2->netdev);
+	netif_stop_queue(sky2->netdev);
+
+	/* Turn on link LED */
+	sky2_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF);
+
+	if (netif_msg_link(sky2))
+		printk(KERN_INFO PFX "%s: Link is down.\n", sky2->netdev->name);
+	sky2_phy_init(hw, port);
+}
+
+static int sky2_autoneg_done(struct sky2_port *sky2, u16 aux)
+{
+	struct sky2_hw *hw = sky2->hw;
+	unsigned port = sky2->port;
+	u16 lpa;
+
+	lpa = gm_phy_read(hw, port, PHY_MARV_AUNE_LP);
+
+	if (lpa & PHY_M_AN_RF) {
+		printk(KERN_ERR PFX "%s: remote fault", sky2->netdev->name);
+		return -1;
+	}
+
+	if (hw->chip_id != CHIP_ID_YUKON_FE &&
+	    gm_phy_read(hw, port, PHY_MARV_1000T_STAT) & PHY_B_1000S_MSF) {
+		printk(KERN_ERR PFX "%s: master/slave fault",
+		       sky2->netdev->name);
+		return -1;
+	}
+
+	if (!(aux & PHY_M_PS_SPDUP_RES)) {
+		printk(KERN_ERR PFX "%s: speed/duplex mismatch",
+		       sky2->netdev->name);
+		return -1;
+	}
+
+	sky2->duplex = (aux & PHY_M_PS_FULL_DUP) ? DUPLEX_FULL : DUPLEX_HALF;
+
+	sky2->speed = sky2_phy_speed(hw, aux);
+
+	/* Pause bits are offset (9..8) */
+	if (hw->chip_id == CHIP_ID_YUKON_XL)
+		aux >>= 6;
+
+	sky2->rx_pause = (aux & PHY_M_PS_RX_P_EN) != 0;
+	sky2->tx_pause = (aux & PHY_M_PS_TX_P_EN) != 0;
+
+	if ((sky2->tx_pause || sky2->rx_pause)
+	    && !(sky2->speed < SPEED_1000 && sky2->duplex == DUPLEX_HALF))
+		sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_ON);
+	else
+		sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF);
+
+	return 0;
+}
+
+/*
+ * Interrupt from PHY are handled outside of interrupt context
+ * because accessing phy registers requires spin wait which might
+ * cause excess interrupt latency.
+ */
+static void sky2_phy_task(void *arg)
+{
+	struct sky2_port *sky2 = arg;
+	struct sky2_hw *hw = sky2->hw;
+	u16 istatus, phystat;
+
+	down(&sky2->phy_sema);
+	istatus = gm_phy_read(hw, sky2->port, PHY_MARV_INT_STAT);
+	phystat = gm_phy_read(hw, sky2->port, PHY_MARV_PHY_STAT);
+
+	if (netif_msg_intr(sky2))
+		printk(KERN_INFO PFX "%s: phy interrupt status 0x%x 0x%x\n",
+		       sky2->netdev->name, istatus, phystat);
+
+	if (istatus & PHY_M_IS_AN_COMPL) {
+		if (sky2_autoneg_done(sky2, phystat) == 0)
+			sky2_link_up(sky2);
+		goto out;
+	}
+
+	if (istatus & PHY_M_IS_LSP_CHANGE)
+		sky2->speed = sky2_phy_speed(hw, phystat);
+
+	if (istatus & PHY_M_IS_DUP_CHANGE)
+		sky2->duplex =
+		    (phystat & PHY_M_PS_FULL_DUP) ? DUPLEX_FULL : DUPLEX_HALF;
+
+	if (istatus & PHY_M_IS_LST_CHANGE) {
+		if (phystat & PHY_M_PS_LINK_UP)
+			sky2_link_up(sky2);
+		else
+			sky2_link_down(sky2);
+	}
+out:
+	up(&sky2->phy_sema);
+
+	local_irq_disable();
+	hw->intr_mask |= (sky2->port == 0) ? Y2_IS_IRQ_PHY1 : Y2_IS_IRQ_PHY2;
+	sky2_write32(hw, B0_IMSK, hw->intr_mask);
+	local_irq_enable();
+}
+
+static void sky2_tx_timeout(struct net_device *dev)
+{
+	struct sky2_port *sky2 = netdev_priv(dev);
+	struct sky2_hw *hw = sky2->hw;
+	unsigned txq = txqaddr[sky2->port];
+
+	if (netif_msg_timer(sky2))
+		printk(KERN_ERR PFX "%s: tx timeout\n", dev->name);
+
+	netif_stop_queue(dev);
+
+	sky2_write32(hw, Q_ADDR(txq, Q_CSR), BMU_STOP);
+	sky2_read32(hw, Q_ADDR(txq, Q_CSR));
+
+	sky2_write32(hw, Y2_QADDR(txq, PREF_UNIT_CTRL), PREF_UNIT_RST_SET);
+
+	sky2_tx_clean(sky2);
+
+	sky2_qset(hw, txq);
+	sky2_prefetch_init(hw, txq, sky2->tx_le_map, TX_RING_SIZE - 1);
+
+	netif_wake_queue(dev);
+}
+
+
+#define roundup(x, y)   ((((x)+((y)-1))/(y))*(y))
+/* Want receive buffer size to be multiple of 64 bits, and incl room for vlan */
+static inline unsigned sky2_buf_size(int mtu)
+{
+	return roundup(mtu + ETH_HLEN + 4, 8);
+}
+
+static int sky2_change_mtu(struct net_device *dev, int new_mtu)
+{
+	struct sky2_port *sky2 = netdev_priv(dev);
+	struct sky2_hw *hw = sky2->hw;
+	int err;
+	u16 ctl, mode;
+
+	if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU)
+		return -EINVAL;
+
+	if (hw->chip_id == CHIP_ID_YUKON_EC_U && new_mtu > ETH_DATA_LEN)
+		return -EINVAL;
+
+	if (!netif_running(dev)) {
+		dev->mtu = new_mtu;
+		return 0;
+	}
+
+	sky2_write32(hw, B0_IMSK, 0);
+
+	dev->trans_start = jiffies;	/* prevent tx timeout */
+	netif_stop_queue(dev);
+	netif_poll_disable(hw->dev[0]);
+
+	ctl = gma_read16(hw, sky2->port, GM_GP_CTRL);
+	gma_write16(hw, sky2->port, GM_GP_CTRL, ctl & ~GM_GPCR_RX_ENA);
+	sky2_rx_stop(sky2);
+	sky2_rx_clean(sky2);
+
+	dev->mtu = new_mtu;
+	sky2->rx_bufsize = sky2_buf_size(new_mtu);
+	mode = DATA_BLIND_VAL(DATA_BLIND_DEF) |
+		GM_SMOD_VLAN_ENA | IPG_DATA_VAL(IPG_DATA_DEF);
+
+	if (dev->mtu > ETH_DATA_LEN)
+		mode |= GM_SMOD_JUMBO_ENA;
+
+	gma_write16(hw, sky2->port, GM_SERIAL_MODE, mode);
+
+	sky2_write8(hw, RB_ADDR(rxqaddr[sky2->port], RB_CTRL), RB_ENA_OP_MD);
+
+	err = sky2_rx_start(sky2);
+	sky2_write32(hw, B0_IMSK, hw->intr_mask);
+
+	if (err)
+		dev_close(dev);
+	else {
+		gma_write16(hw, sky2->port, GM_GP_CTRL, ctl);
+
+		netif_poll_enable(hw->dev[0]);
+		netif_wake_queue(dev);
+	}
+
+	return err;
+}
+
+/*
+ * Receive one packet.
+ * For small packets or errors, just reuse existing skb.
+ * For larger packets, get new buffer.
+ */
+static struct sk_buff *sky2_receive(struct sky2_port *sky2,
+				    u16 length, u32 status)
+{
+	struct ring_info *re = sky2->rx_ring + sky2->rx_next;
+	struct sk_buff *skb = NULL;
+
+	if (unlikely(netif_msg_rx_status(sky2)))
+		printk(KERN_DEBUG PFX "%s: rx slot %u status 0x%x len %d\n",
+		       sky2->netdev->name, sky2->rx_next, status, length);
+
+	sky2->rx_next = (sky2->rx_next + 1) % sky2->rx_pending;
+	prefetch(sky2->rx_ring + sky2->rx_next);
+
+	if (status & GMR_FS_ANY_ERR)
+		goto error;
+
+	if (!(status & GMR_FS_RX_OK))
+		goto resubmit;
+
+	if ((status >> 16) != length || length > sky2->rx_bufsize)
+		goto oversize;
+
+	if (length < copybreak) {
+		skb = alloc_skb(length + 2, GFP_ATOMIC);
+		if (!skb)
+			goto resubmit;
+
+		skb_reserve(skb, 2);
+		pci_dma_sync_single_for_cpu(sky2->hw->pdev, re->mapaddr,
+					    length, PCI_DMA_FROMDEVICE);
+		memcpy(skb->data, re->skb->data, length);
+		skb->ip_summed = re->skb->ip_summed;
+		skb->csum = re->skb->csum;
+		pci_dma_sync_single_for_device(sky2->hw->pdev, re->mapaddr,
+					       length, PCI_DMA_FROMDEVICE);
+	} else {
+		struct sk_buff *nskb;
+
+		nskb = dev_alloc_skb(sky2->rx_bufsize);
+		if (!nskb)
+			goto resubmit;
+
+		skb = re->skb;
+		re->skb = nskb;
+		pci_unmap_single(sky2->hw->pdev, re->mapaddr,
+				 sky2->rx_bufsize, PCI_DMA_FROMDEVICE);
+		prefetch(skb->data);
+
+		re->mapaddr = pci_map_single(sky2->hw->pdev, nskb->data,
+					     sky2->rx_bufsize, PCI_DMA_FROMDEVICE);
+	}
+
+	skb_put(skb, length);
+resubmit:
+	re->skb->ip_summed = CHECKSUM_NONE;
+	sky2_rx_add(sky2, re->mapaddr);
+
+	/* Tell receiver about new buffers. */
+	sky2_put_idx(sky2->hw, rxqaddr[sky2->port], sky2->rx_put,
+		     &sky2->rx_last_put, RX_LE_SIZE);
+
+	return skb;
+
+oversize:
+	++sky2->net_stats.rx_over_errors;
+	goto resubmit;
+
+error:
+	++sky2->net_stats.rx_errors;
+
+	if (netif_msg_rx_err(sky2))
+		printk(KERN_INFO PFX "%s: rx error, status 0x%x length %d\n",
+		       sky2->netdev->name, status, length);
+
+	if (status & (GMR_FS_LONG_ERR | GMR_FS_UN_SIZE))
+		sky2->net_stats.rx_length_errors++;
+	if (status & GMR_FS_FRAGMENT)
+		sky2->net_stats.rx_frame_errors++;
+	if (status & GMR_FS_CRC_ERR)
+		sky2->net_stats.rx_crc_errors++;
+	if (status & GMR_FS_RX_FF_OV)
+		sky2->net_stats.rx_fifo_errors++;
+
+	goto resubmit;
+}
+
+/*
+ * Check for transmit complete
+ */
+#define TX_NO_STATUS	0xffff
+
+static inline void sky2_tx_check(struct sky2_hw *hw, int port, u16 last)
+{
+	if (last != TX_NO_STATUS) {
+		struct net_device *dev = hw->dev[port];
+		if (dev && netif_running(dev)) {
+			struct sky2_port *sky2 = netdev_priv(dev);
+			sky2_tx_complete(sky2, last);
+		}
+	}
+}
+
+/*
+ * Both ports share the same status interrupt, therefore there is only
+ * one poll routine.
+ */
+static int sky2_poll(struct net_device *dev0, int *budget)
+{
+	struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw;
+	unsigned int to_do = min(dev0->quota, *budget);
+	unsigned int work_done = 0;
+	u16 hwidx;
+	u16 tx_done[2] = { TX_NO_STATUS, TX_NO_STATUS };
+
+	hwidx = sky2_read16(hw, STAT_PUT_IDX);
+	BUG_ON(hwidx >= STATUS_RING_SIZE);
+	rmb();
+
+	while (hwidx != hw->st_idx) {
+		struct sky2_status_le *le  = hw->st_le + hw->st_idx;
+		struct net_device *dev;
+		struct sky2_port *sky2;
+		struct sk_buff *skb;
+		u32 status;
+		u16 length;
+		u8 op;
+
+		le = hw->st_le + hw->st_idx;
+		hw->st_idx = (hw->st_idx + 1) % STATUS_RING_SIZE;
+		prefetch(hw->st_le + hw->st_idx);
+
+		BUG_ON(le->link >= 2);
+		dev = hw->dev[le->link];
+		if (dev == NULL || !netif_running(dev))
+			continue;
+
+		sky2 = netdev_priv(dev);
+		status = le32_to_cpu(le->status);
+		length = le16_to_cpu(le->length);
+		op = le->opcode & ~HW_OWNER;
+		le->opcode = 0;
+
+		switch (op) {
+		case OP_RXSTAT:
+			skb = sky2_receive(sky2, length, status);
+			if (!skb)
+				break;
+
+			skb->dev = dev;
+			skb->protocol = eth_type_trans(skb, dev);
+			dev->last_rx = jiffies;
+
+#ifdef SKY2_VLAN_TAG_USED
+			if (sky2->vlgrp && (status & GMR_FS_VLAN)) {
+				vlan_hwaccel_receive_skb(skb,
+							 sky2->vlgrp,
+							 be16_to_cpu(sky2->rx_tag));
+			} else
+#endif
+				netif_receive_skb(skb);
+
+			if (++work_done >= to_do)
+				goto exit_loop;
+			break;
+
+#ifdef SKY2_VLAN_TAG_USED
+		case OP_RXVLAN:
+			sky2->rx_tag = length;
+			break;
+
+		case OP_RXCHKSVLAN:
+			sky2->rx_tag = length;
+			/* fall through */
+#endif
+		case OP_RXCHKS:
+			skb = sky2->rx_ring[sky2->rx_next].skb;
+			skb->ip_summed = CHECKSUM_HW;
+			skb->csum = le16_to_cpu(status);
+			break;
+
+		case OP_TXINDEXLE:
+			/* TX index reports status for both ports */
+			tx_done[0] = status & 0xffff;
+			tx_done[1] = ((status >> 24) & 0xff)
+				| (u16)(length & 0xf) << 8;
+			break;
+
+		default:
+			if (net_ratelimit())
+				printk(KERN_WARNING PFX
+				       "unknown status opcode 0x%x\n", op);
+			break;
+		}
+	}
+
+exit_loop:
+	sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
+	mmiowb();
+
+	sky2_tx_check(hw, 0, tx_done[0]);
+	sky2_tx_check(hw, 1, tx_done[1]);
+
+	if (sky2_read16(hw, STAT_PUT_IDX) == hw->st_idx) {
+		/* need to restart TX timer */
+		if (is_ec_a1(hw)) {
+			sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP);
+			sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START);
+		}
+
+		netif_rx_complete(dev0);
+		hw->intr_mask |= Y2_IS_STAT_BMU;
+		sky2_write32(hw, B0_IMSK, hw->intr_mask);
+		mmiowb();
+		return 0;
+	} else {
+		*budget -= work_done;
+		dev0->quota -= work_done;
+		return 1;
+	}
+}
+
+static void sky2_hw_error(struct sky2_hw *hw, unsigned port, u32 status)
+{
+	struct net_device *dev = hw->dev[port];
+
+	printk(KERN_INFO PFX "%s: hw error interrupt status 0x%x\n",
+	       dev->name, status);
+
+	if (status & Y2_IS_PAR_RD1) {
+		printk(KERN_ERR PFX "%s: ram data read parity error\n",
+		       dev->name);
+		/* Clear IRQ */
+		sky2_write16(hw, RAM_BUFFER(port, B3_RI_CTRL), RI_CLR_RD_PERR);
+	}
+
+	if (status & Y2_IS_PAR_WR1) {
+		printk(KERN_ERR PFX "%s: ram data write parity error\n",
+		       dev->name);
+
+		sky2_write16(hw, RAM_BUFFER(port, B3_RI_CTRL), RI_CLR_WR_PERR);
+	}
+
+	if (status & Y2_IS_PAR_MAC1) {
+		printk(KERN_ERR PFX "%s: MAC parity error\n", dev->name);
+		sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_CLI_TX_PE);
+	}
+
+	if (status & Y2_IS_PAR_RX1) {
+		printk(KERN_ERR PFX "%s: RX parity error\n", dev->name);
+		sky2_write32(hw, Q_ADDR(rxqaddr[port], Q_CSR), BMU_CLR_IRQ_PAR);
+	}
+
+	if (status & Y2_IS_TCP_TXA1) {
+		printk(KERN_ERR PFX "%s: TCP segmentation error\n", dev->name);
+		sky2_write32(hw, Q_ADDR(txqaddr[port], Q_CSR), BMU_CLR_IRQ_TCP);
+	}
+}
+
+static void sky2_hw_intr(struct sky2_hw *hw)
+{
+	u32 status = sky2_read32(hw, B0_HWE_ISRC);
+
+	if (status & Y2_IS_TIST_OV)
+		sky2_write8(hw, GMAC_TI_ST_CTRL, GMT_ST_CLR_IRQ);
+
+	if (status & (Y2_IS_MST_ERR | Y2_IS_IRQ_STAT)) {
+		u16 pci_err;
+
+		pci_read_config_word(hw->pdev, PCI_STATUS, &pci_err);
+		printk(KERN_ERR PFX "%s: pci hw error (0x%x)\n",
+		       pci_name(hw->pdev), pci_err);
+
+		sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+		pci_write_config_word(hw->pdev, PCI_STATUS,
+				      pci_err | PCI_STATUS_ERROR_BITS);
+		sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
+	}
+
+	if (status & Y2_IS_PCI_EXP) {
+		/* PCI-Express uncorrectable Error occurred */
+		u32 pex_err;
+
+		pci_read_config_dword(hw->pdev, PEX_UNC_ERR_STAT, &pex_err);
+
+		printk(KERN_ERR PFX "%s: pci express error (0x%x)\n",
+		       pci_name(hw->pdev), pex_err);
+
+		/* clear the interrupt */
+		sky2_write32(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+		pci_write_config_dword(hw->pdev, PEX_UNC_ERR_STAT,
+				       0xffffffffUL);
+		sky2_write32(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
+
+		if (pex_err & PEX_FATAL_ERRORS) {
+			u32 hwmsk = sky2_read32(hw, B0_HWE_IMSK);
+			hwmsk &= ~Y2_IS_PCI_EXP;
+			sky2_write32(hw, B0_HWE_IMSK, hwmsk);
+		}
+	}
+
+	if (status & Y2_HWE_L1_MASK)
+		sky2_hw_error(hw, 0, status);
+	status >>= 8;
+	if (status & Y2_HWE_L1_MASK)
+		sky2_hw_error(hw, 1, status);
+}
+
+static void sky2_mac_intr(struct sky2_hw *hw, unsigned port)
+{
+	struct net_device *dev = hw->dev[port];
+	struct sky2_port *sky2 = netdev_priv(dev);
+	u8 status = sky2_read8(hw, SK_REG(port, GMAC_IRQ_SRC));
+
+	if (netif_msg_intr(sky2))
+		printk(KERN_INFO PFX "%s: mac interrupt status 0x%x\n",
+		       dev->name, status);
+
+	if (status & GM_IS_RX_FF_OR) {
+		++sky2->net_stats.rx_fifo_errors;
+		sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_CLI_RX_FO);
+	}
+
+	if (status & GM_IS_TX_FF_UR) {
+		++sky2->net_stats.tx_fifo_errors;
+		sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_CLI_TX_FU);
+	}
+}
+
+static void sky2_phy_intr(struct sky2_hw *hw, unsigned port)
+{
+	struct net_device *dev = hw->dev[port];
+	struct sky2_port *sky2 = netdev_priv(dev);
+
+	hw->intr_mask &= ~(port == 0 ? Y2_IS_IRQ_PHY1 : Y2_IS_IRQ_PHY2);
+	sky2_write32(hw, B0_IMSK, hw->intr_mask);
+	schedule_work(&sky2->phy_task);
+}
+
+static irqreturn_t sky2_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct sky2_hw *hw = dev_id;
+	struct net_device *dev0 = hw->dev[0];
+	u32 status;
+
+	status = sky2_read32(hw, B0_Y2_SP_ISRC2);
+	if (status == 0 || status == ~0)
+		return IRQ_NONE;
+
+	if (status & Y2_IS_HW_ERR)
+		sky2_hw_intr(hw);
+
+	/* Do NAPI for Rx and Tx status */
+	if (status & Y2_IS_STAT_BMU) {
+		hw->intr_mask &= ~Y2_IS_STAT_BMU;
+		sky2_write32(hw, B0_IMSK, hw->intr_mask);
+
+		if (likely(__netif_rx_schedule_prep(dev0))) {
+			prefetch(&hw->st_le[hw->st_idx]);
+			__netif_rx_schedule(dev0);
+		}
+	}
+
+	if (status & Y2_IS_IRQ_PHY1)
+		sky2_phy_intr(hw, 0);
+
+	if (status & Y2_IS_IRQ_PHY2)
+		sky2_phy_intr(hw, 1);
+
+	if (status & Y2_IS_IRQ_MAC1)
+		sky2_mac_intr(hw, 0);
+
+	if (status & Y2_IS_IRQ_MAC2)
+		sky2_mac_intr(hw, 1);
+
+	sky2_write32(hw, B0_Y2_SP_ICR, 2);
+
+	sky2_read32(hw, B0_IMSK);
+
+	return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void sky2_netpoll(struct net_device *dev)
+{
+	struct sky2_port *sky2 = netdev_priv(dev);
+
+	sky2_intr(sky2->hw->pdev->irq, sky2->hw, NULL);
+}
+#endif
+
+/* Chip internal frequency for clock calculations */
+static inline u32 sky2_mhz(const struct sky2_hw *hw)
+{
+	switch (hw->chip_id) {
+	case CHIP_ID_YUKON_EC:
+	case CHIP_ID_YUKON_EC_U:
+		return 125;	/* 125 Mhz */
+	case CHIP_ID_YUKON_FE:
+		return 100;	/* 100 Mhz */
+	default:		/* YUKON_XL */
+		return 156;	/* 156 Mhz */
+	}
+}
+
+static inline u32 sky2_us2clk(const struct sky2_hw *hw, u32 us)
+{
+	return sky2_mhz(hw) * us;
+}
+
+static inline u32 sky2_clk2us(const struct sky2_hw *hw, u32 clk)
+{
+	return clk / sky2_mhz(hw);
+}
+
+
+static int sky2_reset(struct sky2_hw *hw)
+{
+	u32 ctst;
+	u16 status;
+	u8 t8, pmd_type;
+	int i;
+
+	ctst = sky2_read32(hw, B0_CTST);
+
+	sky2_write8(hw, B0_CTST, CS_RST_CLR);
+	hw->chip_id = sky2_read8(hw, B2_CHIP_ID);
+	if (hw->chip_id < CHIP_ID_YUKON_XL || hw->chip_id > CHIP_ID_YUKON_FE) {
+		printk(KERN_ERR PFX "%s: unsupported chip type 0x%x\n",
+		       pci_name(hw->pdev), hw->chip_id);
+		return -EOPNOTSUPP;
+	}
+
+	/* ring for status responses */
+	hw->st_le = pci_alloc_consistent(hw->pdev, STATUS_LE_BYTES,
+					 &hw->st_dma);
+	if (!hw->st_le)
+		return -ENOMEM;
+
+	/* disable ASF */
+	if (hw->chip_id <= CHIP_ID_YUKON_EC) {
+		sky2_write8(hw, B28_Y2_ASF_STAT_CMD, Y2_ASF_RESET);
+		sky2_write16(hw, B0_CTST, Y2_ASF_DISABLE);
+	}
+
+	/* do a SW reset */
+	sky2_write8(hw, B0_CTST, CS_RST_SET);
+	sky2_write8(hw, B0_CTST, CS_RST_CLR);
+
+	/* clear PCI errors, if any */
+	pci_read_config_word(hw->pdev, PCI_STATUS, &status);
+	sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+	pci_write_config_word(hw->pdev, PCI_STATUS,
+			      status | PCI_STATUS_ERROR_BITS);
+
+	sky2_write8(hw, B0_CTST, CS_MRST_CLR);
+
+	/* clear any PEX errors */
+	if (is_pciex(hw)) {
+		u16 lstat;
+		pci_write_config_dword(hw->pdev, PEX_UNC_ERR_STAT,
+				       0xffffffffUL);
+		pci_read_config_word(hw->pdev, PEX_LNK_STAT, &lstat);
+	}
+
+	pmd_type = sky2_read8(hw, B2_PMD_TYP);
+	hw->copper = !(pmd_type == 'L' || pmd_type == 'S');
+
+	hw->ports = 1;
+	t8 = sky2_read8(hw, B2_Y2_HW_RES);
+	if ((t8 & CFG_DUAL_MAC_MSK) == CFG_DUAL_MAC_MSK) {
+		if (!(sky2_read8(hw, B2_Y2_CLK_GATE) & Y2_STATUS_LNK2_INAC))
+			++hw->ports;
+	}
+	hw->chip_rev = (sky2_read8(hw, B2_MAC_CFG) & CFG_CHIP_R_MSK) >> 4;
+
+	sky2_set_power_state(hw, PCI_D0);
+
+	for (i = 0; i < hw->ports; i++) {
+		sky2_write8(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_SET);
+		sky2_write8(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_CLR);
+	}
+
+	sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
+
+	/* Clear I2C IRQ noise */
+	sky2_write32(hw, B2_I2C_IRQ, 1);
+
+	/* turn off hardware timer (unused) */
+	sky2_write8(hw, B2_TI_CTRL, TIM_STOP);
+	sky2_write8(hw, B2_TI_CTRL, TIM_CLR_IRQ);
+
+	sky2_write8(hw, B0_Y2LED, LED_STAT_ON);
+
+	/* Turn off descriptor polling */
+	sky2_write32(hw, B28_DPT_CTRL, DPT_STOP);
+
+	/* Turn off receive timestamp */
+	sky2_write8(hw, GMAC_TI_ST_CTRL, GMT_ST_STOP);
+	sky2_write8(hw, GMAC_TI_ST_CTRL, GMT_ST_CLR_IRQ);
+
+	/* enable the Tx Arbiters */
+	for (i = 0; i < hw->ports; i++)
+		sky2_write8(hw, SK_REG(i, TXA_CTRL), TXA_ENA_ARB);
+
+	/* Initialize ram interface */
+	for (i = 0; i < hw->ports; i++) {
+		sky2_write8(hw, RAM_BUFFER(i, B3_RI_CTRL), RI_RST_CLR);
+
+		sky2_write8(hw, RAM_BUFFER(i, B3_RI_WTO_R1), SK_RI_TO_53);
+		sky2_write8(hw, RAM_BUFFER(i, B3_RI_WTO_XA1), SK_RI_TO_53);
+		sky2_write8(hw, RAM_BUFFER(i, B3_RI_WTO_XS1), SK_RI_TO_53);
+		sky2_write8(hw, RAM_BUFFER(i, B3_RI_RTO_R1), SK_RI_TO_53);
+		sky2_write8(hw, RAM_BUFFER(i, B3_RI_RTO_XA1), SK_RI_TO_53);
+		sky2_write8(hw, RAM_BUFFER(i, B3_RI_RTO_XS1), SK_RI_TO_53);
+		sky2_write8(hw, RAM_BUFFER(i, B3_RI_WTO_R2), SK_RI_TO_53);
+		sky2_write8(hw, RAM_BUFFER(i, B3_RI_WTO_XA2), SK_RI_TO_53);
+		sky2_write8(hw, RAM_BUFFER(i, B3_RI_WTO_XS2), SK_RI_TO_53);
+		sky2_write8(hw, RAM_BUFFER(i, B3_RI_RTO_R2), SK_RI_TO_53);
+		sky2_write8(hw, RAM_BUFFER(i, B3_RI_RTO_XA2), SK_RI_TO_53);
+		sky2_write8(hw, RAM_BUFFER(i, B3_RI_RTO_XS2), SK_RI_TO_53);
+	}
+
+	sky2_write32(hw, B0_HWE_IMSK, Y2_HWE_ALL_MASK);
+
+	for (i = 0; i < hw->ports; i++)
+		sky2_phy_reset(hw, i);
+
+	memset(hw->st_le, 0, STATUS_LE_BYTES);
+	hw->st_idx = 0;
+
+	sky2_write32(hw, STAT_CTRL, SC_STAT_RST_SET);
+	sky2_write32(hw, STAT_CTRL, SC_STAT_RST_CLR);
+
+	sky2_write32(hw, STAT_LIST_ADDR_LO, hw->st_dma);
+	sky2_write32(hw, STAT_LIST_ADDR_HI, (u64) hw->st_dma >> 32);
+
+	/* Set the list last index */
+	sky2_write16(hw, STAT_LAST_IDX, STATUS_RING_SIZE - 1);
+
+	/* These status setup values are copied from SysKonnect's driver */
+	if (is_ec_a1(hw)) {
+		/* WA for dev. #4.3 */
+		sky2_write16(hw, STAT_TX_IDX_TH, 0xfff);	/* Tx Threshold */
+
+		/* set Status-FIFO watermark */
+		sky2_write8(hw, STAT_FIFO_WM, 0x21);	/* WA for dev. #4.18 */
+
+		/* set Status-FIFO ISR watermark */
+		sky2_write8(hw, STAT_FIFO_ISR_WM, 0x07);	/* WA for dev. #4.18 */
+		sky2_write32(hw, STAT_TX_TIMER_INI, sky2_us2clk(hw, 10000));
+	} else {
+		sky2_write16(hw, STAT_TX_IDX_TH, 10);
+		sky2_write8(hw, STAT_FIFO_WM, 16);
+
+		/* set Status-FIFO ISR watermark */
+		if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev == 0)
+			sky2_write8(hw, STAT_FIFO_ISR_WM, 4);
+		else
+			sky2_write8(hw, STAT_FIFO_ISR_WM, 16);
+
+		sky2_write32(hw, STAT_TX_TIMER_INI, sky2_us2clk(hw, 1000));
+		sky2_write32(hw, STAT_LEV_TIMER_INI, sky2_us2clk(hw, 100));
+		sky2_write32(hw, STAT_ISR_TIMER_INI, sky2_us2clk(hw, 20));
+	}
+
+	/* enable status unit */
+	sky2_write32(hw, STAT_CTRL, SC_STAT_OP_ON);
+
+	sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START);
+	sky2_write8(hw, STAT_LEV_TIMER_CTRL, TIM_START);
+	sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_START);
+
+	return 0;
+}
+
+static inline u32 sky2_supported_modes(const struct sky2_hw *hw)
+{
+	u32 modes;
+	if (hw->copper) {
+		modes = SUPPORTED_10baseT_Half
+		    | SUPPORTED_10baseT_Full
+		    | SUPPORTED_100baseT_Half
+		    | SUPPORTED_100baseT_Full
+		    | SUPPORTED_Autoneg | SUPPORTED_TP;
+
+		if (hw->chip_id != CHIP_ID_YUKON_FE)
+			modes |= SUPPORTED_1000baseT_Half
+			    | SUPPORTED_1000baseT_Full;
+	} else
+		modes = SUPPORTED_1000baseT_Full | SUPPORTED_FIBRE
+		    | SUPPORTED_Autoneg;
+	return modes;
+}
+
+static int sky2_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+	struct sky2_port *sky2 = netdev_priv(dev);
+	struct sky2_hw *hw = sky2->hw;
+
+	ecmd->transceiver = XCVR_INTERNAL;
+	ecmd->supported = sky2_supported_modes(hw);
+	ecmd->phy_address = PHY_ADDR_MARV;
+	if (hw->copper) {
+		ecmd->supported = SUPPORTED_10baseT_Half
+		    | SUPPORTED_10baseT_Full
+		    | SUPPORTED_100baseT_Half
+		    | SUPPORTED_100baseT_Full
+		    | SUPPORTED_1000baseT_Half
+		    | SUPPORTED_1000baseT_Full
+		    | SUPPORTED_Autoneg | SUPPORTED_TP;
+		ecmd->port = PORT_TP;
+	} else
+		ecmd->port = PORT_FIBRE;
+
+	ecmd->advertising = sky2->advertising;
+	ecmd->autoneg = sky2->autoneg;
+	ecmd->speed = sky2->speed;
+	ecmd->duplex = sky2->duplex;
+	return 0;
+}
+
+static int sky2_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+	struct sky2_port *sky2 = netdev_priv(dev);
+	const struct sky2_hw *hw = sky2->hw;
+	u32 supported = sky2_supported_modes(hw);
+
+	if (ecmd->autoneg == AUTONEG_ENABLE) {
+		ecmd->advertising = supported;
+		sky2->duplex = -1;
+		sky2->speed = -1;
+	} else {
+		u32 setting;
+
+		switch (ecmd->speed) {
+		case SPEED_1000:
+			if (ecmd->duplex == DUPLEX_FULL)
+				setting = SUPPORTED_1000baseT_Full;
+			else if (ecmd->duplex == DUPLEX_HALF)
+				setting = SUPPORTED_1000baseT_Half;
+			else
+				return -EINVAL;
+			break;
+		case SPEED_100:
+			if (ecmd->duplex == DUPLEX_FULL)
+				setting = SUPPORTED_100baseT_Full;
+			else if (ecmd->duplex == DUPLEX_HALF)
+				setting = SUPPORTED_100baseT_Half;
+			else
+				return -EINVAL;
+			break;
+
+		case SPEED_10:
+			if (ecmd->duplex == DUPLEX_FULL)
+				setting = SUPPORTED_10baseT_Full;
+			else if (ecmd->duplex == DUPLEX_HALF)
+				setting = SUPPORTED_10baseT_Half;
+			else
+				return -EINVAL;
+			break;
+		default:
+			return -EINVAL;
+		}
+
+		if ((setting & supported) == 0)
+			return -EINVAL;
+
+		sky2->speed = ecmd->speed;
+		sky2->duplex = ecmd->duplex;
+	}
+
+	sky2->autoneg = ecmd->autoneg;
+	sky2->advertising = ecmd->advertising;
+
+	if (netif_running(dev))
+		sky2_phy_reinit(sky2);
+
+	return 0;
+}
+
+static void sky2_get_drvinfo(struct net_device *dev,
+			     struct ethtool_drvinfo *info)
+{
+	struct sky2_port *sky2 = netdev_priv(dev);
+
+	strcpy(info->driver, DRV_NAME);
+	strcpy(info->version, DRV_VERSION);
+	strcpy(info->fw_version, "N/A");
+	strcpy(info->bus_info, pci_name(sky2->hw->pdev));
+}
+
+static const struct sky2_stat {
+	char name[ETH_GSTRING_LEN];
+	u16 offset;
+} sky2_stats[] = {
+	{ "tx_bytes",	   GM_TXO_OK_HI },
+	{ "rx_bytes",	   GM_RXO_OK_HI },
+	{ "tx_broadcast",  GM_TXF_BC_OK },
+	{ "rx_broadcast",  GM_RXF_BC_OK },
+	{ "tx_multicast",  GM_TXF_MC_OK },
+	{ "rx_multicast",  GM_RXF_MC_OK },
+	{ "tx_unicast",    GM_TXF_UC_OK },
+	{ "rx_unicast",    GM_RXF_UC_OK },
+	{ "tx_mac_pause",  GM_TXF_MPAUSE },
+	{ "rx_mac_pause",  GM_RXF_MPAUSE },
+	{ "collisions",    GM_TXF_SNG_COL },
+	{ "late_collision",GM_TXF_LAT_COL },
+	{ "aborted", 	   GM_TXF_ABO_COL },
+	{ "multi_collisions", GM_TXF_MUL_COL },
+	{ "fifo_underrun", GM_TXE_FIFO_UR },
+	{ "fifo_overflow", GM_RXE_FIFO_OV },
+	{ "rx_toolong",    GM_RXF_LNG_ERR },
+	{ "rx_jabber",     GM_RXF_JAB_PKT },
+	{ "rx_runt", 	   GM_RXE_FRAG },
+	{ "rx_too_long",   GM_RXF_LNG_ERR },
+	{ "rx_fcs_error",   GM_RXF_FCS_ERR },
+};
+
+static u32 sky2_get_rx_csum(struct net_device *dev)
+{
+	struct sky2_port *sky2 = netdev_priv(dev);
+
+	return sky2->rx_csum;
+}
+
+static int sky2_set_rx_csum(struct net_device *dev, u32 data)
+{
+	struct sky2_port *sky2 = netdev_priv(dev);
+
+	sky2->rx_csum = data;
+
+	sky2_write32(sky2->hw, Q_ADDR(rxqaddr[sky2->port], Q_CSR),
+		     data ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM);
+
+	return 0;
+}
+
+static u32 sky2_get_msglevel(struct net_device *netdev)
+{
+	struct sky2_port *sky2 = netdev_priv(netdev);
+	return sky2->msg_enable;
+}
+
+static int sky2_nway_reset(struct net_device *dev)
+{
+	struct sky2_port *sky2 = netdev_priv(dev);
+
+	if (sky2->autoneg != AUTONEG_ENABLE)
+		return -EINVAL;
+
+	sky2_phy_reinit(sky2);
+
+	return 0;
+}
+
+static void sky2_phy_stats(struct sky2_port *sky2, u64 * data, unsigned count)
+{
+	struct sky2_hw *hw = sky2->hw;
+	unsigned port = sky2->port;
+	int i;
+
+	data[0] = (u64) gma_read32(hw, port, GM_TXO_OK_HI) << 32
+	    | (u64) gma_read32(hw, port, GM_TXO_OK_LO);
+	data[1] = (u64) gma_read32(hw, port, GM_RXO_OK_HI) << 32
+	    | (u64) gma_read32(hw, port, GM_RXO_OK_LO);
+
+	for (i = 2; i < count; i++)
+		data[i] = (u64) gma_read32(hw, port, sky2_stats[i].offset);
+}
+
+static void sky2_set_msglevel(struct net_device *netdev, u32 value)
+{
+	struct sky2_port *sky2 = netdev_priv(netdev);
+	sky2->msg_enable = value;
+}
+
+static int sky2_get_stats_count(struct net_device *dev)
+{
+	return ARRAY_SIZE(sky2_stats);
+}
+
+static void sky2_get_ethtool_stats(struct net_device *dev,
+				   struct ethtool_stats *stats, u64 * data)
+{
+	struct sky2_port *sky2 = netdev_priv(dev);
+
+	sky2_phy_stats(sky2, data, ARRAY_SIZE(sky2_stats));
+}
+
+static void sky2_get_strings(struct net_device *dev, u32 stringset, u8 * data)
+{
+	int i;
+
+	switch (stringset) {
+	case ETH_SS_STATS:
+		for (i = 0; i < ARRAY_SIZE(sky2_stats); i++)
+			memcpy(data + i * ETH_GSTRING_LEN,
+			       sky2_stats[i].name, ETH_GSTRING_LEN);
+		break;
+	}
+}
+
+/* Use hardware MIB variables for critical path statistics and
+ * transmit feedback not reported at interrupt.
+ * Other errors are accounted for in interrupt handler.
+ */
+static struct net_device_stats *sky2_get_stats(struct net_device *dev)
+{
+	struct sky2_port *sky2 = netdev_priv(dev);
+	u64 data[13];
+
+	sky2_phy_stats(sky2, data, ARRAY_SIZE(data));
+
+	sky2->net_stats.tx_bytes = data[0];
+	sky2->net_stats.rx_bytes = data[1];
+	sky2->net_stats.tx_packets = data[2] + data[4] + data[6];
+	sky2->net_stats.rx_packets = data[3] + data[5] + data[7];
+	sky2->net_stats.multicast = data[5] + data[7];
+	sky2->net_stats.collisions = data[10];
+	sky2->net_stats.tx_aborted_errors = data[12];
+
+	return &sky2->net_stats;
+}
+
+static int sky2_set_mac_address(struct net_device *dev, void *p)
+{
+	struct sky2_port *sky2 = netdev_priv(dev);
+	struct sockaddr *addr = p;
+
+	if (!is_valid_ether_addr(addr->sa_data))
+		return -EADDRNOTAVAIL;
+
+	memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
+	memcpy_toio(sky2->hw->regs + B2_MAC_1 + sky2->port * 8,
+		    dev->dev_addr, ETH_ALEN);
+	memcpy_toio(sky2->hw->regs + B2_MAC_2 + sky2->port * 8,
+		    dev->dev_addr, ETH_ALEN);
+
+	if (netif_running(dev))
+		sky2_phy_reinit(sky2);
+
+	return 0;
+}
+
+static void sky2_set_multicast(struct net_device *dev)
+{
+	struct sky2_port *sky2 = netdev_priv(dev);
+	struct sky2_hw *hw = sky2->hw;
+	unsigned port = sky2->port;
+	struct dev_mc_list *list = dev->mc_list;
+	u16 reg;
+	u8 filter[8];
+
+	memset(filter, 0, sizeof(filter));
+
+	reg = gma_read16(hw, port, GM_RX_CTRL);
+	reg |= GM_RXCR_UCF_ENA;
+
+	if (dev->flags & IFF_PROMISC)	/* promiscuous */
+		reg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
+	else if ((dev->flags & IFF_ALLMULTI) || dev->mc_count > 16)	/* all multicast */
+		memset(filter, 0xff, sizeof(filter));
+	else if (dev->mc_count == 0)	/* no multicast */
+		reg &= ~GM_RXCR_MCF_ENA;
+	else {
+		int i;
+		reg |= GM_RXCR_MCF_ENA;
+
+		for (i = 0; list && i < dev->mc_count; i++, list = list->next) {
+			u32 bit = ether_crc(ETH_ALEN, list->dmi_addr) & 0x3f;
+			filter[bit / 8] |= 1 << (bit % 8);
+		}
+	}
+
+	gma_write16(hw, port, GM_MC_ADDR_H1,
+		    (u16) filter[0] | ((u16) filter[1] << 8));
+	gma_write16(hw, port, GM_MC_ADDR_H2,
+		    (u16) filter[2] | ((u16) filter[3] << 8));
+	gma_write16(hw, port, GM_MC_ADDR_H3,
+		    (u16) filter[4] | ((u16) filter[5] << 8));
+	gma_write16(hw, port, GM_MC_ADDR_H4,
+		    (u16) filter[6] | ((u16) filter[7] << 8));
+
+	gma_write16(hw, port, GM_RX_CTRL, reg);
+}
+
+/* Can have one global because blinking is controlled by
+ * ethtool and that is always under RTNL mutex
+ */
+static void sky2_led(struct sky2_hw *hw, unsigned port, int on)
+{
+	u16 pg;
+
+	switch (hw->chip_id) {
+	case CHIP_ID_YUKON_XL:
+		pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR);
+		gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3);
+		gm_phy_write(hw, port, PHY_MARV_PHY_CTRL,
+			     on ? (PHY_M_LEDC_LOS_CTRL(1) |
+				   PHY_M_LEDC_INIT_CTRL(7) |
+				   PHY_M_LEDC_STA1_CTRL(7) |
+				   PHY_M_LEDC_STA0_CTRL(7))
+			     : 0);
+
+		gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg);
+		break;
+
+	default:
+		gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0);
+		gm_phy_write(hw, port, PHY_MARV_LED_OVER,
+			     on ? PHY_M_LED_MO_DUP(MO_LED_ON) |
+			     PHY_M_LED_MO_10(MO_LED_ON) |
+			     PHY_M_LED_MO_100(MO_LED_ON) |
+			     PHY_M_LED_MO_1000(MO_LED_ON) |
+			     PHY_M_LED_MO_RX(MO_LED_ON)
+			     : PHY_M_LED_MO_DUP(MO_LED_OFF) |
+			     PHY_M_LED_MO_10(MO_LED_OFF) |
+			     PHY_M_LED_MO_100(MO_LED_OFF) |
+			     PHY_M_LED_MO_1000(MO_LED_OFF) |
+			     PHY_M_LED_MO_RX(MO_LED_OFF));
+
+	}
+}
+
+/* blink LED's for finding board */
+static int sky2_phys_id(struct net_device *dev, u32 data)
+{
+	struct sky2_port *sky2 = netdev_priv(dev);
+	struct sky2_hw *hw = sky2->hw;
+	unsigned port = sky2->port;
+	u16 ledctrl, ledover = 0;
+	long ms;
+	int interrupted;
+	int onoff = 1;
+
+	if (!data || data > (u32) (MAX_SCHEDULE_TIMEOUT / HZ))
+		ms = jiffies_to_msecs(MAX_SCHEDULE_TIMEOUT);
+	else
+		ms = data * 1000;
+
+	/* save initial values */
+	down(&sky2->phy_sema);
+	if (hw->chip_id == CHIP_ID_YUKON_XL) {
+		u16 pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR);
+		gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3);
+		ledctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL);
+		gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg);
+	} else {
+		ledctrl = gm_phy_read(hw, port, PHY_MARV_LED_CTRL);
+		ledover = gm_phy_read(hw, port, PHY_MARV_LED_OVER);
+	}
+
+	interrupted = 0;
+	while (!interrupted && ms > 0) {
+		sky2_led(hw, port, onoff);
+		onoff = !onoff;
+
+		up(&sky2->phy_sema);
+		interrupted = msleep_interruptible(250);
+		down(&sky2->phy_sema);
+
+		ms -= 250;
+	}
+
+	/* resume regularly scheduled programming */
+	if (hw->chip_id == CHIP_ID_YUKON_XL) {
+		u16 pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR);
+		gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3);
+		gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ledctrl);
+		gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg);
+	} else {
+		gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl);
+		gm_phy_write(hw, port, PHY_MARV_LED_OVER, ledover);
+	}
+	up(&sky2->phy_sema);
+
+	return 0;
+}
+
+static void sky2_get_pauseparam(struct net_device *dev,
+				struct ethtool_pauseparam *ecmd)
+{
+	struct sky2_port *sky2 = netdev_priv(dev);
+
+	ecmd->tx_pause = sky2->tx_pause;
+	ecmd->rx_pause = sky2->rx_pause;
+	ecmd->autoneg = sky2->autoneg;
+}
+
+static int sky2_set_pauseparam(struct net_device *dev,
+			       struct ethtool_pauseparam *ecmd)
+{
+	struct sky2_port *sky2 = netdev_priv(dev);
+	int err = 0;
+
+	sky2->autoneg = ecmd->autoneg;
+	sky2->tx_pause = ecmd->tx_pause != 0;
+	sky2->rx_pause = ecmd->rx_pause != 0;
+
+	sky2_phy_reinit(sky2);
+
+	return err;
+}
+
+#ifdef CONFIG_PM
+static void sky2_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+	struct sky2_port *sky2 = netdev_priv(dev);
+
+	wol->supported = WAKE_MAGIC;
+	wol->wolopts = sky2->wol ? WAKE_MAGIC : 0;
+}
+
+static int sky2_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+	struct sky2_port *sky2 = netdev_priv(dev);
+	struct sky2_hw *hw = sky2->hw;
+
+	if (wol->wolopts != WAKE_MAGIC && wol->wolopts != 0)
+		return -EOPNOTSUPP;
+
+	sky2->wol = wol->wolopts == WAKE_MAGIC;
+
+	if (sky2->wol) {
+		memcpy_toio(hw->regs + WOL_MAC_ADDR, dev->dev_addr, ETH_ALEN);
+
+		sky2_write16(hw, WOL_CTRL_STAT,
+			     WOL_CTL_ENA_PME_ON_MAGIC_PKT |
+			     WOL_CTL_ENA_MAGIC_PKT_UNIT);
+	} else
+		sky2_write16(hw, WOL_CTRL_STAT, WOL_CTL_DEFAULT);
+
+	return 0;
+}
+#endif
+
+static int sky2_get_coalesce(struct net_device *dev,
+			     struct ethtool_coalesce *ecmd)
+{
+	struct sky2_port *sky2 = netdev_priv(dev);
+	struct sky2_hw *hw = sky2->hw;
+
+	if (sky2_read8(hw, STAT_TX_TIMER_CTRL) == TIM_STOP)
+		ecmd->tx_coalesce_usecs = 0;
+	else {
+		u32 clks = sky2_read32(hw, STAT_TX_TIMER_INI);
+		ecmd->tx_coalesce_usecs = sky2_clk2us(hw, clks);
+	}
+	ecmd->tx_max_coalesced_frames = sky2_read16(hw, STAT_TX_IDX_TH);
+
+	if (sky2_read8(hw, STAT_LEV_TIMER_CTRL) == TIM_STOP)
+		ecmd->rx_coalesce_usecs = 0;
+	else {
+		u32 clks = sky2_read32(hw, STAT_LEV_TIMER_INI);
+		ecmd->rx_coalesce_usecs = sky2_clk2us(hw, clks);
+	}
+	ecmd->rx_max_coalesced_frames = sky2_read8(hw, STAT_FIFO_WM);
+
+	if (sky2_read8(hw, STAT_ISR_TIMER_CTRL) == TIM_STOP)
+		ecmd->rx_coalesce_usecs_irq = 0;
+	else {
+		u32 clks = sky2_read32(hw, STAT_ISR_TIMER_INI);
+		ecmd->rx_coalesce_usecs_irq = sky2_clk2us(hw, clks);
+	}
+
+	ecmd->rx_max_coalesced_frames_irq = sky2_read8(hw, STAT_FIFO_ISR_WM);
+
+	return 0;
+}
+
+/* Note: this affect both ports */
+static int sky2_set_coalesce(struct net_device *dev,
+			     struct ethtool_coalesce *ecmd)
+{
+	struct sky2_port *sky2 = netdev_priv(dev);
+	struct sky2_hw *hw = sky2->hw;
+	const u32 tmin = sky2_clk2us(hw, 1);
+	const u32 tmax = 5000;
+
+	if (ecmd->tx_coalesce_usecs != 0 &&
+	    (ecmd->tx_coalesce_usecs < tmin || ecmd->tx_coalesce_usecs > tmax))
+		return -EINVAL;
+
+	if (ecmd->rx_coalesce_usecs != 0 &&
+	    (ecmd->rx_coalesce_usecs < tmin || ecmd->rx_coalesce_usecs > tmax))
+		return -EINVAL;
+
+	if (ecmd->rx_coalesce_usecs_irq != 0 &&
+	    (ecmd->rx_coalesce_usecs_irq < tmin || ecmd->rx_coalesce_usecs_irq > tmax))
+		return -EINVAL;
+
+	if (ecmd->tx_max_coalesced_frames > 0xffff)
+		return -EINVAL;
+	if (ecmd->rx_max_coalesced_frames > 0xff)
+		return -EINVAL;
+	if (ecmd->rx_max_coalesced_frames_irq > 0xff)
+		return -EINVAL;
+
+	if (ecmd->tx_coalesce_usecs == 0)
+		sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP);
+	else {
+		sky2_write32(hw, STAT_TX_TIMER_INI,
+			     sky2_us2clk(hw, ecmd->tx_coalesce_usecs));
+		sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START);
+	}
+	sky2_write16(hw, STAT_TX_IDX_TH, ecmd->tx_max_coalesced_frames);
+
+	if (ecmd->rx_coalesce_usecs == 0)
+		sky2_write8(hw, STAT_LEV_TIMER_CTRL, TIM_STOP);
+	else {
+		sky2_write32(hw, STAT_LEV_TIMER_INI,
+			     sky2_us2clk(hw, ecmd->rx_coalesce_usecs));
+		sky2_write8(hw, STAT_LEV_TIMER_CTRL, TIM_START);
+	}
+	sky2_write8(hw, STAT_FIFO_WM, ecmd->rx_max_coalesced_frames);
+
+	if (ecmd->rx_coalesce_usecs_irq == 0)
+		sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_STOP);
+	else {
+		sky2_write32(hw, STAT_TX_TIMER_INI,
+			     sky2_us2clk(hw, ecmd->rx_coalesce_usecs_irq));
+		sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_START);
+	}
+	sky2_write8(hw, STAT_FIFO_ISR_WM, ecmd->rx_max_coalesced_frames_irq);
+	return 0;
+}
+
+static void sky2_get_ringparam(struct net_device *dev,
+			       struct ethtool_ringparam *ering)
+{
+	struct sky2_port *sky2 = netdev_priv(dev);
+
+	ering->rx_max_pending = RX_MAX_PENDING;
+	ering->rx_mini_max_pending = 0;
+	ering->rx_jumbo_max_pending = 0;
+	ering->tx_max_pending = TX_RING_SIZE - 1;
+
+	ering->rx_pending = sky2->rx_pending;
+	ering->rx_mini_pending = 0;
+	ering->rx_jumbo_pending = 0;
+	ering->tx_pending = sky2->tx_pending;
+}
+
+static int sky2_set_ringparam(struct net_device *dev,
+			      struct ethtool_ringparam *ering)
+{
+	struct sky2_port *sky2 = netdev_priv(dev);
+	int err = 0;
+
+	if (ering->rx_pending > RX_MAX_PENDING ||
+	    ering->rx_pending < 8 ||
+	    ering->tx_pending < MAX_SKB_TX_LE ||
+	    ering->tx_pending > TX_RING_SIZE - 1)
+		return -EINVAL;
+
+	if (netif_running(dev))
+		sky2_down(dev);
+
+	sky2->rx_pending = ering->rx_pending;
+	sky2->tx_pending = ering->tx_pending;
+
+	if (netif_running(dev)) {
+		err = sky2_up(dev);
+		if (err)
+			dev_close(dev);
+		else
+			sky2_set_multicast(dev);
+	}
+
+	return err;
+}
+
+static int sky2_get_regs_len(struct net_device *dev)
+{
+	return 0x4000;
+}
+
+/*
+ * Returns copy of control register region
+ * Note: access to the RAM address register set will cause timeouts.
+ */
+static void sky2_get_regs(struct net_device *dev, struct ethtool_regs *regs,
+			  void *p)
+{
+	const struct sky2_port *sky2 = netdev_priv(dev);
+	const void __iomem *io = sky2->hw->regs;
+
+	BUG_ON(regs->len < B3_RI_WTO_R1);
+	regs->version = 1;
+	memset(p, 0, regs->len);
+
+	memcpy_fromio(p, io, B3_RAM_ADDR);
+
+	memcpy_fromio(p + B3_RI_WTO_R1,
+		      io + B3_RI_WTO_R1,
+		      regs->len - B3_RI_WTO_R1);
+}
+
+static struct ethtool_ops sky2_ethtool_ops = {
+	.get_settings = sky2_get_settings,
+	.set_settings = sky2_set_settings,
+	.get_drvinfo = sky2_get_drvinfo,
+	.get_msglevel = sky2_get_msglevel,
+	.set_msglevel = sky2_set_msglevel,
+	.nway_reset   = sky2_nway_reset,
+	.get_regs_len = sky2_get_regs_len,
+	.get_regs = sky2_get_regs,
+	.get_link = ethtool_op_get_link,
+	.get_sg = ethtool_op_get_sg,
+	.set_sg = ethtool_op_set_sg,
+	.get_tx_csum = ethtool_op_get_tx_csum,
+	.set_tx_csum = ethtool_op_set_tx_csum,
+	.get_tso = ethtool_op_get_tso,
+	.set_tso = ethtool_op_set_tso,
+	.get_rx_csum = sky2_get_rx_csum,
+	.set_rx_csum = sky2_set_rx_csum,
+	.get_strings = sky2_get_strings,
+	.get_coalesce = sky2_get_coalesce,
+	.set_coalesce = sky2_set_coalesce,
+	.get_ringparam = sky2_get_ringparam,
+	.set_ringparam = sky2_set_ringparam,
+	.get_pauseparam = sky2_get_pauseparam,
+	.set_pauseparam = sky2_set_pauseparam,
+#ifdef CONFIG_PM
+	.get_wol = sky2_get_wol,
+	.set_wol = sky2_set_wol,
+#endif
+	.phys_id = sky2_phys_id,
+	.get_stats_count = sky2_get_stats_count,
+	.get_ethtool_stats = sky2_get_ethtool_stats,
+	.get_perm_addr	= ethtool_op_get_perm_addr,
+};
+
+/* Initialize network device */
+static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw,
+						     unsigned port, int highmem)
+{
+	struct sky2_port *sky2;
+	struct net_device *dev = alloc_etherdev(sizeof(*sky2));
+
+	if (!dev) {
+		printk(KERN_ERR "sky2 etherdev alloc failed");
+		return NULL;
+	}
+
+	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &hw->pdev->dev);
+	dev->irq = hw->pdev->irq;
+	dev->open = sky2_up;
+	dev->stop = sky2_down;
+	dev->do_ioctl = sky2_ioctl;
+	dev->hard_start_xmit = sky2_xmit_frame;
+	dev->get_stats = sky2_get_stats;
+	dev->set_multicast_list = sky2_set_multicast;
+	dev->set_mac_address = sky2_set_mac_address;
+	dev->change_mtu = sky2_change_mtu;
+	SET_ETHTOOL_OPS(dev, &sky2_ethtool_ops);
+	dev->tx_timeout = sky2_tx_timeout;
+	dev->watchdog_timeo = TX_WATCHDOG;
+	if (port == 0)
+		dev->poll = sky2_poll;
+	dev->weight = NAPI_WEIGHT;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = sky2_netpoll;
+#endif
+
+	sky2 = netdev_priv(dev);
+	sky2->netdev = dev;
+	sky2->hw = hw;
+	sky2->msg_enable = netif_msg_init(debug, default_msg);
+
+	spin_lock_init(&sky2->tx_lock);
+	/* Auto speed and flow control */
+	sky2->autoneg = AUTONEG_ENABLE;
+	sky2->tx_pause = 1;
+	sky2->rx_pause = 1;
+	sky2->duplex = -1;
+	sky2->speed = -1;
+	sky2->advertising = sky2_supported_modes(hw);
+
+ 	/* Receive checksum disabled for Yukon XL
+	 * because of observed problems with incorrect
+	 * values when multiple packets are received in one interrupt
+	 */
+	sky2->rx_csum = (hw->chip_id != CHIP_ID_YUKON_XL);
+
+	INIT_WORK(&sky2->phy_task, sky2_phy_task, sky2);
+	init_MUTEX(&sky2->phy_sema);
+	sky2->tx_pending = TX_DEF_PENDING;
+	sky2->rx_pending = is_ec_a1(hw) ? 8 : RX_DEF_PENDING;
+	sky2->rx_bufsize = sky2_buf_size(ETH_DATA_LEN);
+
+	hw->dev[port] = dev;
+
+	sky2->port = port;
+
+	dev->features |= NETIF_F_LLTX;
+	if (hw->chip_id != CHIP_ID_YUKON_EC_U)
+		dev->features |= NETIF_F_TSO;
+	if (highmem)
+		dev->features |= NETIF_F_HIGHDMA;
+	dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
+
+#ifdef SKY2_VLAN_TAG_USED
+	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+	dev->vlan_rx_register = sky2_vlan_rx_register;
+	dev->vlan_rx_kill_vid = sky2_vlan_rx_kill_vid;
+#endif
+
+	/* read the mac address */
+	memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port * 8, ETH_ALEN);
+	memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
+
+	/* device is off until link detection */
+	netif_carrier_off(dev);
+	netif_stop_queue(dev);
+
+	return dev;
+}
+
+static inline void sky2_show_addr(struct net_device *dev)
+{
+	const struct sky2_port *sky2 = netdev_priv(dev);
+
+	if (netif_msg_probe(sky2))
+		printk(KERN_INFO PFX "%s: addr %02x:%02x:%02x:%02x:%02x:%02x\n",
+		       dev->name,
+		       dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
+		       dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
+}
+
+static int __devinit sky2_probe(struct pci_dev *pdev,
+				const struct pci_device_id *ent)
+{
+	struct net_device *dev, *dev1 = NULL;
+	struct sky2_hw *hw;
+	int err, pm_cap, using_dac = 0;
+
+	err = pci_enable_device(pdev);
+	if (err) {
+		printk(KERN_ERR PFX "%s cannot enable PCI device\n",
+		       pci_name(pdev));
+		goto err_out;
+	}
+
+	err = pci_request_regions(pdev, DRV_NAME);
+	if (err) {
+		printk(KERN_ERR PFX "%s cannot obtain PCI resources\n",
+		       pci_name(pdev));
+		goto err_out;
+	}
+
+	pci_set_master(pdev);
+
+	/* Find power-management capability. */
+	pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
+	if (pm_cap == 0) {
+		printk(KERN_ERR PFX "Cannot find PowerManagement capability, "
+		       "aborting.\n");
+		err = -EIO;
+		goto err_out_free_regions;
+	}
+
+	if (sizeof(dma_addr_t) > sizeof(u32)) {
+		err = pci_set_dma_mask(pdev, DMA_64BIT_MASK);
+		if (!err)
+			using_dac = 1;
+	}
+
+	if (!using_dac) {
+		err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+		if (err) {
+			printk(KERN_ERR PFX "%s no usable DMA configuration\n",
+			       pci_name(pdev));
+			goto err_out_free_regions;
+		}
+	}
+#ifdef __BIG_ENDIAN
+	/* byte swap descriptors in hardware */
+	{
+		u32 reg;
+
+		pci_read_config_dword(pdev, PCI_DEV_REG2, &reg);
+		reg |= PCI_REV_DESC;
+		pci_write_config_dword(pdev, PCI_DEV_REG2, reg);
+	}
+#endif
+
+	err = -ENOMEM;
+	hw = kmalloc(sizeof(*hw), GFP_KERNEL);
+	if (!hw) {
+		printk(KERN_ERR PFX "%s: cannot allocate hardware struct\n",
+		       pci_name(pdev));
+		goto err_out_free_regions;
+	}
+
+	memset(hw, 0, sizeof(*hw));
+	hw->pdev = pdev;
+
+	hw->regs = ioremap_nocache(pci_resource_start(pdev, 0), 0x4000);
+	if (!hw->regs) {
+		printk(KERN_ERR PFX "%s: cannot map device registers\n",
+		       pci_name(pdev));
+		goto err_out_free_hw;
+	}
+	hw->pm_cap = pm_cap;
+
+	err = sky2_reset(hw);
+	if (err)
+		goto err_out_iounmap;
+
+	printk(KERN_INFO PFX "v%s addr 0x%lx irq %d Yukon-%s (0x%x) rev %d\n",
+	       DRV_VERSION, pci_resource_start(pdev, 0), pdev->irq,
+	       yukon2_name[hw->chip_id - CHIP_ID_YUKON_XL],
+	       hw->chip_id, hw->chip_rev);
+
+	dev = sky2_init_netdev(hw, 0, using_dac);
+	if (!dev)
+		goto err_out_free_pci;
+
+	err = register_netdev(dev);
+	if (err) {
+		printk(KERN_ERR PFX "%s: cannot register net device\n",
+		       pci_name(pdev));
+		goto err_out_free_netdev;
+	}
+
+	sky2_show_addr(dev);
+
+	if (hw->ports > 1 && (dev1 = sky2_init_netdev(hw, 1, using_dac))) {
+		if (register_netdev(dev1) == 0)
+			sky2_show_addr(dev1);
+		else {
+			/* Failure to register second port need not be fatal */
+			printk(KERN_WARNING PFX
+			       "register of second port failed\n");
+			hw->dev[1] = NULL;
+			free_netdev(dev1);
+		}
+	}
+
+	err = request_irq(pdev->irq, sky2_intr, SA_SHIRQ, DRV_NAME, hw);
+	if (err) {
+		printk(KERN_ERR PFX "%s: cannot assign irq %d\n",
+		       pci_name(pdev), pdev->irq);
+		goto err_out_unregister;
+	}
+
+	hw->intr_mask = Y2_IS_BASE;
+	sky2_write32(hw, B0_IMSK, hw->intr_mask);
+
+	pci_set_drvdata(pdev, hw);
+
+	return 0;
+
+err_out_unregister:
+	if (dev1) {
+		unregister_netdev(dev1);
+		free_netdev(dev1);
+	}
+	unregister_netdev(dev);
+err_out_free_netdev:
+	free_netdev(dev);
+err_out_free_pci:
+	sky2_write8(hw, B0_CTST, CS_RST_SET);
+	pci_free_consistent(hw->pdev, STATUS_LE_BYTES, hw->st_le, hw->st_dma);
+err_out_iounmap:
+	iounmap(hw->regs);
+err_out_free_hw:
+	kfree(hw);
+err_out_free_regions:
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+err_out:
+	return err;
+}
+
+static void __devexit sky2_remove(struct pci_dev *pdev)
+{
+	struct sky2_hw *hw = pci_get_drvdata(pdev);
+	struct net_device *dev0, *dev1;
+
+	if (!hw)
+		return;
+
+	dev0 = hw->dev[0];
+	dev1 = hw->dev[1];
+	if (dev1)
+		unregister_netdev(dev1);
+	unregister_netdev(dev0);
+
+	sky2_write32(hw, B0_IMSK, 0);
+	sky2_set_power_state(hw, PCI_D3hot);
+	sky2_write16(hw, B0_Y2LED, LED_STAT_OFF);
+	sky2_write8(hw, B0_CTST, CS_RST_SET);
+	sky2_read8(hw, B0_CTST);
+
+	free_irq(pdev->irq, hw);
+	pci_free_consistent(pdev, STATUS_LE_BYTES, hw->st_le, hw->st_dma);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+
+	if (dev1)
+		free_netdev(dev1);
+	free_netdev(dev0);
+	iounmap(hw->regs);
+	kfree(hw);
+
+	pci_set_drvdata(pdev, NULL);
+}
+
+#ifdef CONFIG_PM
+static int sky2_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct sky2_hw *hw = pci_get_drvdata(pdev);
+	int i;
+
+	for (i = 0; i < 2; i++) {
+		struct net_device *dev = hw->dev[i];
+
+		if (dev) {
+			if (!netif_running(dev))
+				continue;
+
+			sky2_down(dev);
+			netif_device_detach(dev);
+		}
+	}
+
+	return sky2_set_power_state(hw, pci_choose_state(pdev, state));
+}
+
+static int sky2_resume(struct pci_dev *pdev)
+{
+	struct sky2_hw *hw = pci_get_drvdata(pdev);
+	int i;
+
+	pci_restore_state(pdev);
+	pci_enable_wake(pdev, PCI_D0, 0);
+	sky2_set_power_state(hw, PCI_D0);
+
+	sky2_reset(hw);
+
+	for (i = 0; i < 2; i++) {
+		struct net_device *dev = hw->dev[i];
+		if (dev) {
+			if (netif_running(dev)) {
+				netif_device_attach(dev);
+				if (sky2_up(dev))
+					dev_close(dev);
+			}
+		}
+	}
+	return 0;
+}
+#endif
+
+static struct pci_driver sky2_driver = {
+	.name = DRV_NAME,
+	.id_table = sky2_id_table,
+	.probe = sky2_probe,
+	.remove = __devexit_p(sky2_remove),
+#ifdef CONFIG_PM
+	.suspend = sky2_suspend,
+	.resume = sky2_resume,
+#endif
+};
+
+static int __init sky2_init_module(void)
+{
+	return pci_register_driver(&sky2_driver);
+}
+
+static void __exit sky2_cleanup_module(void)
+{
+	pci_unregister_driver(&sky2_driver);
+}
+
+module_init(sky2_init_module);
+module_exit(sky2_cleanup_module);
+
+MODULE_DESCRIPTION("Marvell Yukon 2 Gigabit Ethernet driver");
+MODULE_AUTHOR("Stephen Hemminger <shemminger@osdl.org>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h
new file mode 100644
index 000000000000..95518921001c
--- /dev/null
+++ b/drivers/net/sky2.h
@@ -0,0 +1,1922 @@
+/*
+ * Definitions for the new Marvell Yukon 2 driver.
+ */
+#ifndef _SKY2_H
+#define _SKY2_H
+
+/* PCI config registers */
+#define PCI_DEV_REG1	0x40
+#define PCI_DEV_REG2	0x44
+#define PCI_DEV_STATUS  0x7c
+#define PCI_OS_PCI_X    (1<<26)
+
+#define PEX_LNK_STAT	0xf2
+#define PEX_UNC_ERR_STAT 0x104
+#define PEX_DEV_CTRL	0xe8
+
+/* Yukon-2 */
+enum pci_dev_reg_1 {
+	PCI_Y2_PIG_ENA	 = 1<<31, /* Enable Plug-in-Go (YUKON-2) */
+	PCI_Y2_DLL_DIS	 = 1<<30, /* Disable PCI DLL (YUKON-2) */
+	PCI_Y2_PHY2_COMA = 1<<29, /* Set PHY 2 to Coma Mode (YUKON-2) */
+	PCI_Y2_PHY1_COMA = 1<<28, /* Set PHY 1 to Coma Mode (YUKON-2) */
+	PCI_Y2_PHY2_POWD = 1<<27, /* Set PHY 2 to Power Down (YUKON-2) */
+	PCI_Y2_PHY1_POWD = 1<<26, /* Set PHY 1 to Power Down (YUKON-2) */
+};
+
+enum pci_dev_reg_2 {
+	PCI_VPD_WR_THR	= 0xffL<<24,	/* Bit 31..24:	VPD Write Threshold */
+	PCI_DEV_SEL	= 0x7fL<<17,	/* Bit 23..17:	EEPROM Device Select */
+	PCI_VPD_ROM_SZ	= 7L<<14,	/* Bit 16..14:	VPD ROM Size	*/
+
+	PCI_PATCH_DIR	= 0xfL<<8,	/* Bit 11.. 8:	Ext Patches dir 3..0 */
+	PCI_EXT_PATCHS	= 0xfL<<4,	/* Bit	7.. 4:	Extended Patches 3..0 */
+	PCI_EN_DUMMY_RD	= 1<<3,		/* Enable Dummy Read */
+	PCI_REV_DESC	= 1<<2,		/* Reverse Desc. Bytes */
+
+	PCI_USEDATA64	= 1<<0,		/* Use 64Bit Data bus ext */
+};
+
+
+#define PCI_STATUS_ERROR_BITS (PCI_STATUS_DETECTED_PARITY | \
+			       PCI_STATUS_SIG_SYSTEM_ERROR | \
+			       PCI_STATUS_REC_MASTER_ABORT | \
+			       PCI_STATUS_REC_TARGET_ABORT | \
+			       PCI_STATUS_PARITY)
+
+enum pex_dev_ctrl {
+	PEX_DC_MAX_RRS_MSK	= 7<<12, /* Bit 14..12:	Max. Read Request Size */
+	PEX_DC_EN_NO_SNOOP	= 1<<11,/* Enable No Snoop */
+	PEX_DC_EN_AUX_POW	= 1<<10,/* Enable AUX Power */
+	PEX_DC_EN_PHANTOM	= 1<<9,	/* Enable Phantom Functions */
+	PEX_DC_EN_EXT_TAG	= 1<<8,	/* Enable Extended Tag Field */
+	PEX_DC_MAX_PLS_MSK	= 7<<5,	/* Bit  7.. 5:	Max. Payload Size Mask */
+	PEX_DC_EN_REL_ORD	= 1<<4,	/* Enable Relaxed Ordering */
+	PEX_DC_EN_UNS_RQ_RP	= 1<<3,	/* Enable Unsupported Request Reporting */
+	PEX_DC_EN_FAT_ER_RP	= 1<<2,	/* Enable Fatal Error Reporting */
+	PEX_DC_EN_NFA_ER_RP	= 1<<1,	/* Enable Non-Fatal Error Reporting */
+	PEX_DC_EN_COR_ER_RP	= 1<<0,	/* Enable Correctable Error Reporting */
+};
+#define  PEX_DC_MAX_RD_RQ_SIZE(x) (((x)<<12) & PEX_DC_MAX_RRS_MSK)
+
+/* PEX_UNC_ERR_STAT	 PEX Uncorrectable Errors Status Register (Yukon-2) */
+enum pex_err {
+	PEX_UNSUP_REQ 	= 1<<20, /* Unsupported Request Error */
+
+	PEX_MALFOR_TLP	= 1<<18, /* Malformed TLP */
+
+	PEX_UNEXP_COMP	= 1<<16, /* Unexpected Completion */
+
+	PEX_COMP_TO	= 1<<14, /* Completion Timeout */
+	PEX_FLOW_CTRL_P	= 1<<13, /* Flow Control Protocol Error */
+	PEX_POIS_TLP	= 1<<12, /* Poisoned TLP */
+
+	PEX_DATA_LINK_P = 1<<4,	/* Data Link Protocol Error */
+	PEX_FATAL_ERRORS= (PEX_MALFOR_TLP | PEX_FLOW_CTRL_P | PEX_DATA_LINK_P),
+};
+
+
+enum csr_regs {
+	B0_RAP		= 0x0000,
+	B0_CTST		= 0x0004,
+	B0_Y2LED	= 0x0005,
+	B0_POWER_CTRL	= 0x0007,
+	B0_ISRC		= 0x0008,
+	B0_IMSK		= 0x000c,
+	B0_HWE_ISRC	= 0x0010,
+	B0_HWE_IMSK	= 0x0014,
+
+	/* Special ISR registers (Yukon-2 only) */
+	B0_Y2_SP_ISRC2	= 0x001c,
+	B0_Y2_SP_ISRC3	= 0x0020,
+	B0_Y2_SP_EISR	= 0x0024,
+	B0_Y2_SP_LISR	= 0x0028,
+	B0_Y2_SP_ICR	= 0x002c,
+
+	B2_MAC_1	= 0x0100,
+	B2_MAC_2	= 0x0108,
+	B2_MAC_3	= 0x0110,
+	B2_CONN_TYP	= 0x0118,
+	B2_PMD_TYP	= 0x0119,
+	B2_MAC_CFG	= 0x011a,
+	B2_CHIP_ID	= 0x011b,
+	B2_E_0		= 0x011c,
+
+	B2_Y2_CLK_GATE  = 0x011d,
+	B2_Y2_HW_RES	= 0x011e,
+	B2_E_3		= 0x011f,
+	B2_Y2_CLK_CTRL	= 0x0120,
+
+	B2_TI_INI	= 0x0130,
+	B2_TI_VAL	= 0x0134,
+	B2_TI_CTRL	= 0x0138,
+	B2_TI_TEST	= 0x0139,
+
+	B2_TST_CTRL1	= 0x0158,
+	B2_TST_CTRL2	= 0x0159,
+	B2_GP_IO	= 0x015c,
+
+	B2_I2C_CTRL	= 0x0160,
+	B2_I2C_DATA	= 0x0164,
+	B2_I2C_IRQ	= 0x0168,
+	B2_I2C_SW	= 0x016c,
+
+	B3_RAM_ADDR	= 0x0180,
+	B3_RAM_DATA_LO	= 0x0184,
+	B3_RAM_DATA_HI	= 0x0188,
+
+/* RAM Interface Registers */
+/* Yukon-2: use RAM_BUFFER() to access the RAM buffer */
+/*
+ * The HW-Spec. calls this registers Timeout Value 0..11. But this names are
+ * not usable in SW. Please notice these are NOT real timeouts, these are
+ * the number of qWords transferred continuously.
+ */
+#define RAM_BUFFER(port, reg)	(reg | (port <<6))
+
+	B3_RI_WTO_R1	= 0x0190,
+	B3_RI_WTO_XA1	= 0x0191,
+	B3_RI_WTO_XS1	= 0x0192,
+	B3_RI_RTO_R1	= 0x0193,
+	B3_RI_RTO_XA1	= 0x0194,
+	B3_RI_RTO_XS1	= 0x0195,
+	B3_RI_WTO_R2	= 0x0196,
+	B3_RI_WTO_XA2	= 0x0197,
+	B3_RI_WTO_XS2	= 0x0198,
+	B3_RI_RTO_R2	= 0x0199,
+	B3_RI_RTO_XA2	= 0x019a,
+	B3_RI_RTO_XS2	= 0x019b,
+	B3_RI_TO_VAL	= 0x019c,
+	B3_RI_CTRL	= 0x01a0,
+	B3_RI_TEST	= 0x01a2,
+	B3_MA_TOINI_RX1	= 0x01b0,
+	B3_MA_TOINI_RX2	= 0x01b1,
+	B3_MA_TOINI_TX1	= 0x01b2,
+	B3_MA_TOINI_TX2	= 0x01b3,
+	B3_MA_TOVAL_RX1	= 0x01b4,
+	B3_MA_TOVAL_RX2	= 0x01b5,
+	B3_MA_TOVAL_TX1	= 0x01b6,
+	B3_MA_TOVAL_TX2	= 0x01b7,
+	B3_MA_TO_CTRL	= 0x01b8,
+	B3_MA_TO_TEST	= 0x01ba,
+	B3_MA_RCINI_RX1	= 0x01c0,
+	B3_MA_RCINI_RX2	= 0x01c1,
+	B3_MA_RCINI_TX1	= 0x01c2,
+	B3_MA_RCINI_TX2	= 0x01c3,
+	B3_MA_RCVAL_RX1	= 0x01c4,
+	B3_MA_RCVAL_RX2	= 0x01c5,
+	B3_MA_RCVAL_TX1	= 0x01c6,
+	B3_MA_RCVAL_TX2	= 0x01c7,
+	B3_MA_RC_CTRL	= 0x01c8,
+	B3_MA_RC_TEST	= 0x01ca,
+	B3_PA_TOINI_RX1	= 0x01d0,
+	B3_PA_TOINI_RX2	= 0x01d4,
+	B3_PA_TOINI_TX1	= 0x01d8,
+	B3_PA_TOINI_TX2	= 0x01dc,
+	B3_PA_TOVAL_RX1	= 0x01e0,
+	B3_PA_TOVAL_RX2	= 0x01e4,
+	B3_PA_TOVAL_TX1	= 0x01e8,
+	B3_PA_TOVAL_TX2	= 0x01ec,
+	B3_PA_CTRL	= 0x01f0,
+	B3_PA_TEST	= 0x01f2,
+
+	Y2_CFG_SPC	= 0x1c00,
+};
+
+/*	B0_CTST			16 bit	Control/Status register */
+enum {
+	Y2_VMAIN_AVAIL	= 1<<17,/* VMAIN available (YUKON-2 only) */
+	Y2_VAUX_AVAIL	= 1<<16,/* VAUX available (YUKON-2 only) */
+	Y2_ASF_ENABLE	= 1<<13,/* ASF Unit Enable (YUKON-2 only) */
+	Y2_ASF_DISABLE	= 1<<12,/* ASF Unit Disable (YUKON-2 only) */
+	Y2_CLK_RUN_ENA	= 1<<11,/* CLK_RUN Enable  (YUKON-2 only) */
+	Y2_CLK_RUN_DIS	= 1<<10,/* CLK_RUN Disable (YUKON-2 only) */
+	Y2_LED_STAT_ON	= 1<<9, /* Status LED On  (YUKON-2 only) */
+	Y2_LED_STAT_OFF	= 1<<8, /* Status LED Off (YUKON-2 only) */
+
+	CS_ST_SW_IRQ	= 1<<7,	/* Set IRQ SW Request */
+	CS_CL_SW_IRQ	= 1<<6,	/* Clear IRQ SW Request */
+	CS_STOP_DONE	= 1<<5,	/* Stop Master is finished */
+	CS_STOP_MAST	= 1<<4,	/* Command Bit to stop the master */
+	CS_MRST_CLR	= 1<<3,	/* Clear Master reset	*/
+	CS_MRST_SET	= 1<<2,	/* Set Master reset	*/
+	CS_RST_CLR	= 1<<1,	/* Clear Software reset	*/
+	CS_RST_SET	= 1,	/* Set   Software reset	*/
+};
+
+/*	B0_LED			 8 Bit	LED register */
+enum {
+/* Bit  7.. 2:	reserved */
+	LED_STAT_ON	= 1<<1,	/* Status LED on	*/
+	LED_STAT_OFF	= 1,	/* Status LED off	*/
+};
+
+/*	B0_POWER_CTRL	 8 Bit	Power Control reg (YUKON only) */
+enum {
+	PC_VAUX_ENA	= 1<<7,	/* Switch VAUX Enable  */
+	PC_VAUX_DIS	= 1<<6,	/* Switch VAUX Disable */
+	PC_VCC_ENA	= 1<<5,	/* Switch VCC Enable  */
+	PC_VCC_DIS	= 1<<4,	/* Switch VCC Disable */
+	PC_VAUX_ON	= 1<<3,	/* Switch VAUX On  */
+	PC_VAUX_OFF	= 1<<2,	/* Switch VAUX Off */
+	PC_VCC_ON	= 1<<1,	/* Switch VCC On  */
+	PC_VCC_OFF	= 1<<0,	/* Switch VCC Off */
+};
+
+/*	B2_IRQM_MSK 	32 bit	IRQ Moderation Mask */
+
+/*	B0_Y2_SP_ISRC2	32 bit	Special Interrupt Source Reg 2 */
+/*	B0_Y2_SP_ISRC3	32 bit	Special Interrupt Source Reg 3 */
+/*	B0_Y2_SP_EISR	32 bit	Enter ISR Reg */
+/*	B0_Y2_SP_LISR	32 bit	Leave ISR Reg */
+enum {
+	Y2_IS_HW_ERR	= 1<<31,	/* Interrupt HW Error */
+	Y2_IS_STAT_BMU	= 1<<30,	/* Status BMU Interrupt */
+	Y2_IS_ASF	= 1<<29,	/* ASF subsystem Interrupt */
+
+	Y2_IS_POLL_CHK	= 1<<27,	/* Check IRQ from polling unit */
+	Y2_IS_TWSI_RDY	= 1<<26,	/* IRQ on end of TWSI Tx */
+	Y2_IS_IRQ_SW	= 1<<25,	/* SW forced IRQ	*/
+	Y2_IS_TIMINT	= 1<<24,	/* IRQ from Timer	*/
+
+	Y2_IS_IRQ_PHY2	= 1<<12,	/* Interrupt from PHY 2 */
+	Y2_IS_IRQ_MAC2	= 1<<11,	/* Interrupt from MAC 2 */
+	Y2_IS_CHK_RX2	= 1<<10,	/* Descriptor error Rx 2 */
+	Y2_IS_CHK_TXS2	= 1<<9,		/* Descriptor error TXS 2 */
+	Y2_IS_CHK_TXA2	= 1<<8,		/* Descriptor error TXA 2 */
+
+	Y2_IS_IRQ_PHY1	= 1<<4,		/* Interrupt from PHY 1 */
+	Y2_IS_IRQ_MAC1	= 1<<3,		/* Interrupt from MAC 1 */
+	Y2_IS_CHK_RX1	= 1<<2,		/* Descriptor error Rx 1 */
+	Y2_IS_CHK_TXS1	= 1<<1,		/* Descriptor error TXS 1 */
+	Y2_IS_CHK_TXA1	= 1<<0,		/* Descriptor error TXA 1 */
+
+	Y2_IS_BASE	= Y2_IS_HW_ERR | Y2_IS_STAT_BMU |
+			  Y2_IS_POLL_CHK | Y2_IS_TWSI_RDY |
+			  Y2_IS_IRQ_SW | Y2_IS_TIMINT,
+	Y2_IS_PORT_1	= Y2_IS_IRQ_PHY1 | Y2_IS_IRQ_MAC1 |
+			  Y2_IS_CHK_RX1 | Y2_IS_CHK_TXA1 | Y2_IS_CHK_TXS1,
+	Y2_IS_PORT_2	= Y2_IS_IRQ_PHY2 | Y2_IS_IRQ_MAC2 |
+			  Y2_IS_CHK_RX2 | Y2_IS_CHK_TXA2 | Y2_IS_CHK_TXS2,
+};
+
+/*	B2_IRQM_HWE_MSK	32 bit	IRQ Moderation HW Error Mask */
+enum {
+	IS_ERR_MSK	= 0x00003fff,/* 		All Error bits */
+
+	IS_IRQ_TIST_OV	= 1<<13, /* Time Stamp Timer Overflow (YUKON only) */
+	IS_IRQ_SENSOR	= 1<<12, /* IRQ from Sensor (YUKON only) */
+	IS_IRQ_MST_ERR	= 1<<11, /* IRQ master error detected */
+	IS_IRQ_STAT	= 1<<10, /* IRQ status exception */
+	IS_NO_STAT_M1	= 1<<9,	/* No Rx Status from MAC 1 */
+	IS_NO_STAT_M2	= 1<<8,	/* No Rx Status from MAC 2 */
+	IS_NO_TIST_M1	= 1<<7,	/* No Time Stamp from MAC 1 */
+	IS_NO_TIST_M2	= 1<<6,	/* No Time Stamp from MAC 2 */
+	IS_RAM_RD_PAR	= 1<<5,	/* RAM Read  Parity Error */
+	IS_RAM_WR_PAR	= 1<<4,	/* RAM Write Parity Error */
+	IS_M1_PAR_ERR	= 1<<3,	/* MAC 1 Parity Error */
+	IS_M2_PAR_ERR	= 1<<2,	/* MAC 2 Parity Error */
+	IS_R1_PAR_ERR	= 1<<1,	/* Queue R1 Parity Error */
+	IS_R2_PAR_ERR	= 1<<0,	/* Queue R2 Parity Error */
+};
+
+/* Hardware error interrupt mask for Yukon 2 */
+enum {
+	Y2_IS_TIST_OV	= 1<<29,/* Time Stamp Timer overflow interrupt */
+	Y2_IS_SENSOR	= 1<<28, /* Sensor interrupt */
+	Y2_IS_MST_ERR	= 1<<27, /* Master error interrupt */
+	Y2_IS_IRQ_STAT	= 1<<26, /* Status exception interrupt */
+	Y2_IS_PCI_EXP	= 1<<25, /* PCI-Express interrupt */
+	Y2_IS_PCI_NEXP	= 1<<24, /* PCI-Express error similar to PCI error */
+						/* Link 2 */
+	Y2_IS_PAR_RD2	= 1<<13, /* Read RAM parity error interrupt */
+	Y2_IS_PAR_WR2	= 1<<12, /* Write RAM parity error interrupt */
+	Y2_IS_PAR_MAC2	= 1<<11, /* MAC hardware fault interrupt */
+	Y2_IS_PAR_RX2	= 1<<10, /* Parity Error Rx Queue 2 */
+	Y2_IS_TCP_TXS2	= 1<<9, /* TCP length mismatch sync Tx queue IRQ */
+	Y2_IS_TCP_TXA2	= 1<<8, /* TCP length mismatch async Tx queue IRQ */
+						/* Link 1 */
+	Y2_IS_PAR_RD1	= 1<<5, /* Read RAM parity error interrupt */
+	Y2_IS_PAR_WR1	= 1<<4, /* Write RAM parity error interrupt */
+	Y2_IS_PAR_MAC1	= 1<<3, /* MAC hardware fault interrupt */
+	Y2_IS_PAR_RX1	= 1<<2, /* Parity Error Rx Queue 1 */
+	Y2_IS_TCP_TXS1	= 1<<1, /* TCP length mismatch sync Tx queue IRQ */
+	Y2_IS_TCP_TXA1	= 1<<0, /* TCP length mismatch async Tx queue IRQ */
+
+	Y2_HWE_L1_MASK	= Y2_IS_PAR_RD1 | Y2_IS_PAR_WR1 | Y2_IS_PAR_MAC1 |
+			  Y2_IS_PAR_RX1 | Y2_IS_TCP_TXS1| Y2_IS_TCP_TXA1,
+	Y2_HWE_L2_MASK	= Y2_IS_PAR_RD2 | Y2_IS_PAR_WR2 | Y2_IS_PAR_MAC2 |
+			  Y2_IS_PAR_RX2 | Y2_IS_TCP_TXS2| Y2_IS_TCP_TXA2,
+
+	Y2_HWE_ALL_MASK	= Y2_IS_TIST_OV | Y2_IS_MST_ERR | Y2_IS_IRQ_STAT |
+			  Y2_IS_PCI_EXP |
+			  Y2_HWE_L1_MASK | Y2_HWE_L2_MASK,
+};
+
+/*	B28_DPT_CTRL	 8 bit	Descriptor Poll Timer Ctrl Reg */
+enum {
+	DPT_START	= 1<<1,
+	DPT_STOP	= 1<<0,
+};
+
+/*	B2_TST_CTRL1	 8 bit	Test Control Register 1 */
+enum {
+	TST_FRC_DPERR_MR = 1<<7, /* force DATAPERR on MST RD */
+	TST_FRC_DPERR_MW = 1<<6, /* force DATAPERR on MST WR */
+	TST_FRC_DPERR_TR = 1<<5, /* force DATAPERR on TRG RD */
+	TST_FRC_DPERR_TW = 1<<4, /* force DATAPERR on TRG WR */
+	TST_FRC_APERR_M	 = 1<<3, /* force ADDRPERR on MST */
+	TST_FRC_APERR_T	 = 1<<2, /* force ADDRPERR on TRG */
+	TST_CFG_WRITE_ON = 1<<1, /* Enable  Config Reg WR */
+	TST_CFG_WRITE_OFF= 1<<0, /* Disable Config Reg WR */
+};
+
+/*	B2_MAC_CFG		 8 bit	MAC Configuration / Chip Revision */
+enum {
+	CFG_CHIP_R_MSK	  = 0xf<<4,	/* Bit 7.. 4: Chip Revision */
+					/* Bit 3.. 2:	reserved */
+	CFG_DIS_M2_CLK	  = 1<<1,	/* Disable Clock for 2nd MAC */
+	CFG_SNG_MAC	  = 1<<0,	/* MAC Config: 0=2 MACs / 1=1 MAC*/
+};
+
+/*	B2_CHIP_ID		 8 bit 	Chip Identification Number */
+enum {
+	CHIP_ID_GENESIS	   = 0x0a, /* Chip ID for GENESIS */
+	CHIP_ID_YUKON	   = 0xb0, /* Chip ID for YUKON */
+	CHIP_ID_YUKON_LITE = 0xb1, /* Chip ID for YUKON-Lite (Rev. A1-A3) */
+	CHIP_ID_YUKON_LP   = 0xb2, /* Chip ID for YUKON-LP */
+	CHIP_ID_YUKON_XL   = 0xb3, /* Chip ID for YUKON-2 XL */
+	CHIP_ID_YUKON_EC_U = 0xb4, /* Chip ID for YUKON-2 EC Ultra */
+	CHIP_ID_YUKON_EC   = 0xb6, /* Chip ID for YUKON-2 EC */
+ 	CHIP_ID_YUKON_FE   = 0xb7, /* Chip ID for YUKON-2 FE */
+
+	CHIP_REV_YU_EC_A1    = 0,  /* Chip Rev. for Yukon-EC A1/A0 */
+	CHIP_REV_YU_EC_A2    = 1,  /* Chip Rev. for Yukon-EC A2 */
+	CHIP_REV_YU_EC_A3    = 2,  /* Chip Rev. for Yukon-EC A3 */
+};
+
+/*	B2_Y2_CLK_GATE	 8 bit	Clock Gating (Yukon-2 only) */
+enum {
+	Y2_STATUS_LNK2_INAC	= 1<<7, /* Status Link 2 inactive (0 = active) */
+	Y2_CLK_GAT_LNK2_DIS	= 1<<6, /* Disable clock gating Link 2 */
+	Y2_COR_CLK_LNK2_DIS	= 1<<5, /* Disable Core clock Link 2 */
+	Y2_PCI_CLK_LNK2_DIS	= 1<<4, /* Disable PCI clock Link 2 */
+	Y2_STATUS_LNK1_INAC	= 1<<3, /* Status Link 1 inactive (0 = active) */
+	Y2_CLK_GAT_LNK1_DIS	= 1<<2, /* Disable clock gating Link 1 */
+	Y2_COR_CLK_LNK1_DIS	= 1<<1, /* Disable Core clock Link 1 */
+	Y2_PCI_CLK_LNK1_DIS	= 1<<0, /* Disable PCI clock Link 1 */
+};
+
+/*	B2_Y2_HW_RES	8 bit	HW Resources (Yukon-2 only) */
+enum {
+	CFG_LED_MODE_MSK	= 7<<2,	/* Bit  4.. 2:	LED Mode Mask */
+	CFG_LINK_2_AVAIL	= 1<<1,	/* Link 2 available */
+	CFG_LINK_1_AVAIL	= 1<<0,	/* Link 1 available */
+};
+#define CFG_LED_MODE(x)		(((x) & CFG_LED_MODE_MSK) >> 2)
+#define CFG_DUAL_MAC_MSK	(CFG_LINK_2_AVAIL | CFG_LINK_1_AVAIL)
+
+
+/* B2_Y2_CLK_CTRL	32 bit	Clock Frequency Control Register (Yukon-2/EC) */
+enum {
+	Y2_CLK_DIV_VAL_MSK	= 0xff<<16,/* Bit 23..16: Clock Divisor Value */
+#define	Y2_CLK_DIV_VAL(x)	(((x)<<16) & Y2_CLK_DIV_VAL_MSK)
+	Y2_CLK_DIV_VAL2_MSK	= 7<<21,   /* Bit 23..21: Clock Divisor Value */
+	Y2_CLK_SELECT2_MSK	= 0x1f<<16,/* Bit 20..16: Clock Select */
+#define Y2_CLK_DIV_VAL_2(x)	(((x)<<21) & Y2_CLK_DIV_VAL2_MSK)
+#define Y2_CLK_SEL_VAL_2(x)	(((x)<<16) & Y2_CLK_SELECT2_MSK)
+	Y2_CLK_DIV_ENA		= 1<<1, /* Enable  Core Clock Division */
+	Y2_CLK_DIV_DIS		= 1<<0,	/* Disable Core Clock Division */
+};
+
+/*	B2_TI_CTRL		 8 bit	Timer control */
+/*	B2_IRQM_CTRL	 8 bit	IRQ Moderation Timer Control */
+enum {
+	TIM_START	= 1<<2,	/* Start Timer */
+	TIM_STOP	= 1<<1,	/* Stop  Timer */
+	TIM_CLR_IRQ	= 1<<0,	/* Clear Timer IRQ (!IRQM) */
+};
+
+/*	B2_TI_TEST		 8 Bit	Timer Test */
+/*	B2_IRQM_TEST	 8 bit	IRQ Moderation Timer Test */
+/*	B28_DPT_TST		 8 bit	Descriptor Poll Timer Test Reg */
+enum {
+	TIM_T_ON	= 1<<2,	/* Test mode on */
+	TIM_T_OFF	= 1<<1,	/* Test mode off */
+	TIM_T_STEP	= 1<<0,	/* Test step */
+};
+
+/*	B3_RAM_ADDR		32 bit	RAM Address, to read or write */
+					/* Bit 31..19:	reserved */
+#define RAM_ADR_RAN	0x0007ffffL	/* Bit 18.. 0:	RAM Address Range */
+/* RAM Interface Registers */
+
+/*	B3_RI_CTRL		16 bit	RAM Interface Control Register */
+enum {
+	RI_CLR_RD_PERR	= 1<<9,	/* Clear IRQ RAM Read Parity Err */
+	RI_CLR_WR_PERR	= 1<<8,	/* Clear IRQ RAM Write Parity Err*/
+
+	RI_RST_CLR	= 1<<1,	/* Clear RAM Interface Reset */
+	RI_RST_SET	= 1<<0,	/* Set   RAM Interface Reset */
+};
+
+#define SK_RI_TO_53	36		/* RAM interface timeout */
+
+
+/* Port related registers FIFO, and Arbiter */
+#define SK_REG(port,reg)	(((port)<<7)+(reg))
+
+/* Transmit Arbiter Registers MAC 1 and 2, use SK_REG() to access */
+/*	TXA_ITI_INI		32 bit	Tx Arb Interval Timer Init Val */
+/*	TXA_ITI_VAL		32 bit	Tx Arb Interval Timer Value */
+/*	TXA_LIM_INI		32 bit	Tx Arb Limit Counter Init Val */
+/*	TXA_LIM_VAL		32 bit	Tx Arb Limit Counter Value */
+
+#define TXA_MAX_VAL	0x00ffffffUL	/* Bit 23.. 0:	Max TXA Timer/Cnt Val */
+
+/*	TXA_CTRL		 8 bit	Tx Arbiter Control Register */
+enum {
+	TXA_ENA_FSYNC	= 1<<7,	/* Enable  force of sync Tx queue */
+	TXA_DIS_FSYNC	= 1<<6,	/* Disable force of sync Tx queue */
+	TXA_ENA_ALLOC	= 1<<5,	/* Enable  alloc of free bandwidth */
+	TXA_DIS_ALLOC	= 1<<4,	/* Disable alloc of free bandwidth */
+	TXA_START_RC	= 1<<3,	/* Start sync Rate Control */
+	TXA_STOP_RC	= 1<<2,	/* Stop  sync Rate Control */
+	TXA_ENA_ARB	= 1<<1,	/* Enable  Tx Arbiter */
+	TXA_DIS_ARB	= 1<<0,	/* Disable Tx Arbiter */
+};
+
+/*
+ *	Bank 4 - 5
+ */
+/* Transmit Arbiter Registers MAC 1 and 2, use SK_REG() to access */
+enum {
+	TXA_ITI_INI	= 0x0200,/* 32 bit	Tx Arb Interval Timer Init Val*/
+	TXA_ITI_VAL	= 0x0204,/* 32 bit	Tx Arb Interval Timer Value */
+	TXA_LIM_INI	= 0x0208,/* 32 bit	Tx Arb Limit Counter Init Val */
+	TXA_LIM_VAL	= 0x020c,/* 32 bit	Tx Arb Limit Counter Value */
+	TXA_CTRL	= 0x0210,/*  8 bit	Tx Arbiter Control Register */
+	TXA_TEST	= 0x0211,/*  8 bit	Tx Arbiter Test Register */
+	TXA_STAT	= 0x0212,/*  8 bit	Tx Arbiter Status Register */
+};
+
+
+enum {
+	B6_EXT_REG	= 0x0300,/* External registers (GENESIS only) */
+	B7_CFG_SPC	= 0x0380,/* copy of the Configuration register */
+	B8_RQ1_REGS	= 0x0400,/* Receive Queue 1 */
+	B8_RQ2_REGS	= 0x0480,/* Receive Queue 2 */
+	B8_TS1_REGS	= 0x0600,/* Transmit sync queue 1 */
+	B8_TA1_REGS	= 0x0680,/* Transmit async queue 1 */
+	B8_TS2_REGS	= 0x0700,/* Transmit sync queue 2 */
+	B8_TA2_REGS	= 0x0780,/* Transmit sync queue 2 */
+	B16_RAM_REGS	= 0x0800,/* RAM Buffer Registers */
+};
+
+/* Queue Register Offsets, use Q_ADDR() to access */
+enum {
+	B8_Q_REGS = 0x0400, /* base of Queue registers */
+	Q_D	= 0x00,	/* 8*32	bit	Current Descriptor */
+	Q_DA_L	= 0x20,	/* 32 bit	Current Descriptor Address Low dWord */
+	Q_DA_H	= 0x24,	/* 32 bit	Current Descriptor Address High dWord */
+	Q_AC_L	= 0x28,	/* 32 bit	Current Address Counter Low dWord */
+	Q_AC_H	= 0x2c,	/* 32 bit	Current Address Counter High dWord */
+	Q_BC	= 0x30,	/* 32 bit	Current Byte Counter */
+	Q_CSR	= 0x34,	/* 32 bit	BMU Control/Status Register */
+	Q_F	= 0x38,	/* 32 bit	Flag Register */
+	Q_T1	= 0x3c,	/* 32 bit	Test Register 1 */
+	Q_T1_TR	= 0x3c,	/*  8 bit	Test Register 1 Transfer SM */
+	Q_T1_WR	= 0x3d,	/*  8 bit	Test Register 1 Write Descriptor SM */
+	Q_T1_RD	= 0x3e,	/*  8 bit	Test Register 1 Read Descriptor SM */
+	Q_T1_SV	= 0x3f,	/*  8 bit	Test Register 1 Supervisor SM */
+	Q_T2	= 0x40,	/* 32 bit	Test Register 2	*/
+	Q_T3	= 0x44,	/* 32 bit	Test Register 3	*/
+
+/* Yukon-2 */
+	Q_DONE	= 0x24,	/* 16 bit	Done Index 		(Yukon-2 only) */
+	Q_WM	= 0x40,	/* 16 bit	FIFO Watermark */
+	Q_AL	= 0x42,	/*  8 bit	FIFO Alignment */
+	Q_RSP	= 0x44,	/* 16 bit	FIFO Read Shadow Pointer */
+	Q_RSL	= 0x46,	/*  8 bit	FIFO Read Shadow Level */
+	Q_RP	= 0x48,	/*  8 bit	FIFO Read Pointer */
+	Q_RL	= 0x4a,	/*  8 bit	FIFO Read Level */
+	Q_WP	= 0x4c,	/*  8 bit	FIFO Write Pointer */
+	Q_WSP	= 0x4d,	/*  8 bit	FIFO Write Shadow Pointer */
+	Q_WL	= 0x4e,	/*  8 bit	FIFO Write Level */
+	Q_WSL	= 0x4f,	/*  8 bit	FIFO Write Shadow Level */
+};
+#define Q_ADDR(reg, offs) (B8_Q_REGS + (reg) + (offs))
+
+
+/* Queue Prefetch Unit Offsets, use Y2_QADDR() to address (Yukon-2 only)*/
+enum {
+	Y2_B8_PREF_REGS		= 0x0450,
+
+	PREF_UNIT_CTRL		= 0x00,	/* 32 bit	Control register */
+	PREF_UNIT_LAST_IDX	= 0x04,	/* 16 bit	Last Index */
+	PREF_UNIT_ADDR_LO	= 0x08,	/* 32 bit	List start addr, low part */
+	PREF_UNIT_ADDR_HI	= 0x0c,	/* 32 bit	List start addr, high part*/
+	PREF_UNIT_GET_IDX	= 0x10,	/* 16 bit	Get Index */
+	PREF_UNIT_PUT_IDX	= 0x14,	/* 16 bit	Put Index */
+	PREF_UNIT_FIFO_WP	= 0x20,	/*  8 bit	FIFO write pointer */
+	PREF_UNIT_FIFO_RP	= 0x24,	/*  8 bit	FIFO read pointer */
+	PREF_UNIT_FIFO_WM	= 0x28,	/*  8 bit	FIFO watermark */
+	PREF_UNIT_FIFO_LEV	= 0x2c,	/*  8 bit	FIFO level */
+
+	PREF_UNIT_MASK_IDX	= 0x0fff,
+};
+#define Y2_QADDR(q,reg)		(Y2_B8_PREF_REGS + (q) + (reg))
+
+/* RAM Buffer Register Offsets */
+enum {
+
+	RB_START	= 0x00,/* 32 bit	RAM Buffer Start Address */
+	RB_END	= 0x04,/* 32 bit	RAM Buffer End Address */
+	RB_WP	= 0x08,/* 32 bit	RAM Buffer Write Pointer */
+	RB_RP	= 0x0c,/* 32 bit	RAM Buffer Read Pointer */
+	RB_RX_UTPP	= 0x10,/* 32 bit	Rx Upper Threshold, Pause Packet */
+	RB_RX_LTPP	= 0x14,/* 32 bit	Rx Lower Threshold, Pause Packet */
+	RB_RX_UTHP	= 0x18,/* 32 bit	Rx Upper Threshold, High Prio */
+	RB_RX_LTHP	= 0x1c,/* 32 bit	Rx Lower Threshold, High Prio */
+	/* 0x10 - 0x1f:	reserved at Tx RAM Buffer Registers */
+	RB_PC	= 0x20,/* 32 bit	RAM Buffer Packet Counter */
+	RB_LEV	= 0x24,/* 32 bit	RAM Buffer Level Register */
+	RB_CTRL	= 0x28,/* 32 bit	RAM Buffer Control Register */
+	RB_TST1	= 0x29,/*  8 bit	RAM Buffer Test Register 1 */
+	RB_TST2	= 0x2a,/*  8 bit	RAM Buffer Test Register 2 */
+};
+
+/* Receive and Transmit Queues */
+enum {
+	Q_R1	= 0x0000,	/* Receive Queue 1 */
+	Q_R2	= 0x0080,	/* Receive Queue 2 */
+	Q_XS1	= 0x0200,	/* Synchronous Transmit Queue 1 */
+	Q_XA1	= 0x0280,	/* Asynchronous Transmit Queue 1 */
+	Q_XS2	= 0x0300,	/* Synchronous Transmit Queue 2 */
+	Q_XA2	= 0x0380,	/* Asynchronous Transmit Queue 2 */
+};
+
+/* Different PHY Types */
+enum {
+	PHY_ADDR_MARV	= 0,
+};
+
+#define RB_ADDR(offs, queue) (B16_RAM_REGS + (queue) + (offs))
+
+
+enum {
+	LNK_SYNC_INI	= 0x0c30,/* 32 bit	Link Sync Cnt Init Value */
+	LNK_SYNC_VAL	= 0x0c34,/* 32 bit	Link Sync Cnt Current Value */
+	LNK_SYNC_CTRL	= 0x0c38,/*  8 bit	Link Sync Cnt Control Register */
+	LNK_SYNC_TST	= 0x0c39,/*  8 bit	Link Sync Cnt Test Register */
+
+	LNK_LED_REG	= 0x0c3c,/*  8 bit	Link LED Register */
+
+/* Receive GMAC FIFO (YUKON and Yukon-2) */
+
+	RX_GMF_EA	= 0x0c40,/* 32 bit	Rx GMAC FIFO End Address */
+	RX_GMF_AF_THR	= 0x0c44,/* 32 bit	Rx GMAC FIFO Almost Full Thresh. */
+	RX_GMF_CTRL_T	= 0x0c48,/* 32 bit	Rx GMAC FIFO Control/Test */
+	RX_GMF_FL_MSK	= 0x0c4c,/* 32 bit	Rx GMAC FIFO Flush Mask */
+	RX_GMF_FL_THR	= 0x0c50,/* 32 bit	Rx GMAC FIFO Flush Threshold */
+	RX_GMF_TR_THR	= 0x0c54,/* 32 bit	Rx Truncation Threshold (Yukon-2) */
+	RX_GMF_UP_THR	= 0x0c58,/*  8 bit	Rx Upper Pause Thr (Yukon-EC_U) */
+	RX_GMF_LP_THR	= 0x0c5a,/*  8 bit	Rx Lower Pause Thr (Yukon-EC_U) */
+	RX_GMF_VLAN	= 0x0c5c,/* 32 bit	Rx VLAN Type Register (Yukon-2) */
+	RX_GMF_WP	= 0x0c60,/* 32 bit	Rx GMAC FIFO Write Pointer */
+
+	RX_GMF_WLEV	= 0x0c68,/* 32 bit	Rx GMAC FIFO Write Level */
+
+	RX_GMF_RP	= 0x0c70,/* 32 bit	Rx GMAC FIFO Read Pointer */
+
+	RX_GMF_RLEV	= 0x0c78,/* 32 bit	Rx GMAC FIFO Read Level */
+};
+
+
+/*	Q_BC			32 bit	Current Byte Counter */
+
+/* BMU Control Status Registers */
+/*	B0_R1_CSR		32 bit	BMU Ctrl/Stat Rx Queue 1 */
+/*	B0_R2_CSR		32 bit	BMU Ctrl/Stat Rx Queue 2 */
+/*	B0_XA1_CSR		32 bit	BMU Ctrl/Stat Sync Tx Queue 1 */
+/*	B0_XS1_CSR		32 bit	BMU Ctrl/Stat Async Tx Queue 1 */
+/*	B0_XA2_CSR		32 bit	BMU Ctrl/Stat Sync Tx Queue 2 */
+/*	B0_XS2_CSR		32 bit	BMU Ctrl/Stat Async Tx Queue 2 */
+/*	Q_CSR			32 bit	BMU Control/Status Register */
+
+/* Rx BMU Control / Status Registers (Yukon-2) */
+enum {
+	BMU_IDLE	= 1<<31, /* BMU Idle State */
+	BMU_RX_TCP_PKT	= 1<<30, /* Rx TCP Packet (when RSS Hash enabled) */
+	BMU_RX_IP_PKT	= 1<<29, /* Rx IP  Packet (when RSS Hash enabled) */
+
+	BMU_ENA_RX_RSS_HASH = 1<<15, /* Enable  Rx RSS Hash */
+	BMU_DIS_RX_RSS_HASH = 1<<14, /* Disable Rx RSS Hash */
+	BMU_ENA_RX_CHKSUM = 1<<13, /* Enable  Rx TCP/IP Checksum Check */
+	BMU_DIS_RX_CHKSUM = 1<<12, /* Disable Rx TCP/IP Checksum Check */
+	BMU_CLR_IRQ_PAR	= 1<<11, /* Clear IRQ on Parity errors (Rx) */
+	BMU_CLR_IRQ_TCP	= 1<<11, /* Clear IRQ on TCP segment. error (Tx) */
+	BMU_CLR_IRQ_CHK	= 1<<10, /* Clear IRQ Check */
+	BMU_STOP	= 1<<9, /* Stop  Rx/Tx Queue */
+	BMU_START	= 1<<8, /* Start Rx/Tx Queue */
+	BMU_FIFO_OP_ON	= 1<<7, /* FIFO Operational On */
+	BMU_FIFO_OP_OFF	= 1<<6, /* FIFO Operational Off */
+	BMU_FIFO_ENA	= 1<<5, /* Enable FIFO */
+	BMU_FIFO_RST	= 1<<4, /* Reset  FIFO */
+	BMU_OP_ON	= 1<<3, /* BMU Operational On */
+	BMU_OP_OFF	= 1<<2, /* BMU Operational Off */
+	BMU_RST_CLR	= 1<<1, /* Clear BMU Reset (Enable) */
+	BMU_RST_SET	= 1<<0, /* Set   BMU Reset */
+
+	BMU_CLR_RESET	= BMU_FIFO_RST | BMU_OP_OFF | BMU_RST_CLR,
+	BMU_OPER_INIT	= BMU_CLR_IRQ_PAR | BMU_CLR_IRQ_CHK | BMU_START |
+			  BMU_FIFO_ENA | BMU_OP_ON,
+
+	BMU_WM_DEFAULT = 0x600,
+};
+
+/* Tx BMU Control / Status Registers (Yukon-2) */
+								/* Bit 31: same as for Rx */
+enum {
+	BMU_TX_IPIDINCR_ON	= 1<<13, /* Enable  IP ID Increment */
+	BMU_TX_IPIDINCR_OFF	= 1<<12, /* Disable IP ID Increment */
+	BMU_TX_CLR_IRQ_TCP	= 1<<11, /* Clear IRQ on TCP segment length mismatch */
+};
+
+/* Queue Prefetch Unit Offsets, use Y2_QADDR() to address (Yukon-2 only)*/
+/* PREF_UNIT_CTRL	32 bit	Prefetch Control register */
+enum {
+	PREF_UNIT_OP_ON		= 1<<3,	/* prefetch unit operational */
+	PREF_UNIT_OP_OFF	= 1<<2,	/* prefetch unit not operational */
+	PREF_UNIT_RST_CLR	= 1<<1,	/* Clear Prefetch Unit Reset */
+	PREF_UNIT_RST_SET	= 1<<0,	/* Set   Prefetch Unit Reset */
+};
+
+/* RAM Buffer Register Offsets, use RB_ADDR(Queue, Offs) to access */
+/*	RB_START		32 bit	RAM Buffer Start Address */
+/*	RB_END			32 bit	RAM Buffer End Address */
+/*	RB_WP			32 bit	RAM Buffer Write Pointer */
+/*	RB_RP			32 bit	RAM Buffer Read Pointer */
+/*	RB_RX_UTPP		32 bit	Rx Upper Threshold, Pause Pack */
+/*	RB_RX_LTPP		32 bit	Rx Lower Threshold, Pause Pack */
+/*	RB_RX_UTHP		32 bit	Rx Upper Threshold, High Prio */
+/*	RB_RX_LTHP		32 bit	Rx Lower Threshold, High Prio */
+/*	RB_PC			32 bit	RAM Buffer Packet Counter */
+/*	RB_LEV			32 bit	RAM Buffer Level Register */
+
+#define RB_MSK	0x0007ffff	/* Bit 18.. 0:	RAM Buffer Pointer Bits */
+/*	RB_TST2			 8 bit	RAM Buffer Test Register 2 */
+/*	RB_TST1			 8 bit	RAM Buffer Test Register 1 */
+
+/*	RB_CTRL			 8 bit	RAM Buffer Control Register */
+enum {
+	RB_ENA_STFWD	= 1<<5,	/* Enable  Store & Forward */
+	RB_DIS_STFWD	= 1<<4,	/* Disable Store & Forward */
+	RB_ENA_OP_MD	= 1<<3,	/* Enable  Operation Mode */
+	RB_DIS_OP_MD	= 1<<2,	/* Disable Operation Mode */
+	RB_RST_CLR	= 1<<1,	/* Clear RAM Buf STM Reset */
+	RB_RST_SET	= 1<<0,	/* Set   RAM Buf STM Reset */
+};
+
+
+/* Transmit GMAC FIFO (YUKON only) */
+enum {
+	TX_GMF_EA	= 0x0d40,/* 32 bit	Tx GMAC FIFO End Address */
+	TX_GMF_AE_THR	= 0x0d44,/* 32 bit	Tx GMAC FIFO Almost Empty Thresh.*/
+	TX_GMF_CTRL_T	= 0x0d48,/* 32 bit	Tx GMAC FIFO Control/Test */
+
+	TX_GMF_WP	= 0x0d60,/* 32 bit 	Tx GMAC FIFO Write Pointer */
+	TX_GMF_WSP	= 0x0d64,/* 32 bit 	Tx GMAC FIFO Write Shadow Ptr. */
+	TX_GMF_WLEV	= 0x0d68,/* 32 bit 	Tx GMAC FIFO Write Level */
+
+	TX_GMF_RP	= 0x0d70,/* 32 bit 	Tx GMAC FIFO Read Pointer */
+	TX_GMF_RSTP	= 0x0d74,/* 32 bit 	Tx GMAC FIFO Restart Pointer */
+	TX_GMF_RLEV	= 0x0d78,/* 32 bit 	Tx GMAC FIFO Read Level */
+};
+
+/* Descriptor Poll Timer Registers */
+enum {
+	B28_DPT_INI	= 0x0e00,/* 24 bit	Descriptor Poll Timer Init Val */
+	B28_DPT_VAL	= 0x0e04,/* 24 bit	Descriptor Poll Timer Curr Val */
+	B28_DPT_CTRL	= 0x0e08,/*  8 bit	Descriptor Poll Timer Ctrl Reg */
+
+	B28_DPT_TST	= 0x0e0a,/*  8 bit	Descriptor Poll Timer Test Reg */
+};
+
+/* Time Stamp Timer Registers (YUKON only) */
+enum {
+	GMAC_TI_ST_VAL	= 0x0e14,/* 32 bit	Time Stamp Timer Curr Val */
+	GMAC_TI_ST_CTRL	= 0x0e18,/*  8 bit	Time Stamp Timer Ctrl Reg */
+	GMAC_TI_ST_TST	= 0x0e1a,/*  8 bit	Time Stamp Timer Test Reg */
+};
+
+/* Polling Unit Registers (Yukon-2 only) */
+enum {
+	POLL_CTRL	= 0x0e20, /* 32 bit	Polling Unit Control Reg */
+	POLL_LAST_IDX	= 0x0e24,/* 16 bit	Polling Unit List Last Index */
+
+	POLL_LIST_ADDR_LO= 0x0e28,/* 32 bit	Poll. List Start Addr (low) */
+	POLL_LIST_ADDR_HI= 0x0e2c,/* 32 bit	Poll. List Start Addr (high) */
+};
+
+/* ASF Subsystem Registers (Yukon-2 only) */
+enum {
+	B28_Y2_SMB_CONFIG  = 0x0e40,/* 32 bit	ASF SMBus Config Register */
+	B28_Y2_SMB_CSD_REG = 0x0e44,/* 32 bit	ASF SMB Control/Status/Data */
+	B28_Y2_ASF_IRQ_V_BASE=0x0e60,/* 32 bit	ASF IRQ Vector Base */
+
+	B28_Y2_ASF_STAT_CMD= 0x0e68,/* 32 bit	ASF Status and Command Reg */
+	B28_Y2_ASF_HOST_COM= 0x0e6c,/* 32 bit	ASF Host Communication Reg */
+	B28_Y2_DATA_REG_1  = 0x0e70,/* 32 bit	ASF/Host Data Register 1 */
+	B28_Y2_DATA_REG_2  = 0x0e74,/* 32 bit	ASF/Host Data Register 2 */
+	B28_Y2_DATA_REG_3  = 0x0e78,/* 32 bit	ASF/Host Data Register 3 */
+	B28_Y2_DATA_REG_4  = 0x0e7c,/* 32 bit	ASF/Host Data Register 4 */
+};
+
+/* Status BMU Registers (Yukon-2 only)*/
+enum {
+	STAT_CTRL	= 0x0e80,/* 32 bit	Status BMU Control Reg */
+	STAT_LAST_IDX	= 0x0e84,/* 16 bit	Status BMU Last Index */
+
+	STAT_LIST_ADDR_LO= 0x0e88,/* 32 bit	Status List Start Addr (low) */
+	STAT_LIST_ADDR_HI= 0x0e8c,/* 32 bit	Status List Start Addr (high) */
+	STAT_TXA1_RIDX	= 0x0e90,/* 16 bit	Status TxA1 Report Index Reg */
+	STAT_TXS1_RIDX	= 0x0e92,/* 16 bit	Status TxS1 Report Index Reg */
+	STAT_TXA2_RIDX	= 0x0e94,/* 16 bit	Status TxA2 Report Index Reg */
+	STAT_TXS2_RIDX	= 0x0e96,/* 16 bit	Status TxS2 Report Index Reg */
+	STAT_TX_IDX_TH	= 0x0e98,/* 16 bit	Status Tx Index Threshold Reg */
+	STAT_PUT_IDX	= 0x0e9c,/* 16 bit	Status Put Index Reg */
+
+/* FIFO Control/Status Registers (Yukon-2 only)*/
+	STAT_FIFO_WP	= 0x0ea0,/*  8 bit	Status FIFO Write Pointer Reg */
+	STAT_FIFO_RP	= 0x0ea4,/*  8 bit	Status FIFO Read Pointer Reg */
+	STAT_FIFO_RSP	= 0x0ea6,/*  8 bit	Status FIFO Read Shadow Ptr */
+	STAT_FIFO_LEVEL	= 0x0ea8,/*  8 bit	Status FIFO Level Reg */
+	STAT_FIFO_SHLVL	= 0x0eaa,/*  8 bit	Status FIFO Shadow Level Reg */
+	STAT_FIFO_WM	= 0x0eac,/*  8 bit	Status FIFO Watermark Reg */
+	STAT_FIFO_ISR_WM= 0x0ead,/*  8 bit	Status FIFO ISR Watermark Reg */
+
+/* Level and ISR Timer Registers (Yukon-2 only)*/
+	STAT_LEV_TIMER_INI= 0x0eb0,/* 32 bit	Level Timer Init. Value Reg */
+	STAT_LEV_TIMER_CNT= 0x0eb4,/* 32 bit	Level Timer Counter Reg */
+	STAT_LEV_TIMER_CTRL= 0x0eb8,/*  8 bit	Level Timer Control Reg */
+	STAT_LEV_TIMER_TEST= 0x0eb9,/*  8 bit	Level Timer Test Reg */
+	STAT_TX_TIMER_INI  = 0x0ec0,/* 32 bit	Tx Timer Init. Value Reg */
+	STAT_TX_TIMER_CNT  = 0x0ec4,/* 32 bit	Tx Timer Counter Reg */
+	STAT_TX_TIMER_CTRL = 0x0ec8,/*  8 bit	Tx Timer Control Reg */
+	STAT_TX_TIMER_TEST = 0x0ec9,/*  8 bit	Tx Timer Test Reg */
+	STAT_ISR_TIMER_INI = 0x0ed0,/* 32 bit	ISR Timer Init. Value Reg */
+	STAT_ISR_TIMER_CNT = 0x0ed4,/* 32 bit	ISR Timer Counter Reg */
+	STAT_ISR_TIMER_CTRL= 0x0ed8,/*  8 bit	ISR Timer Control Reg */
+	STAT_ISR_TIMER_TEST= 0x0ed9,/*  8 bit	ISR Timer Test Reg */
+};
+
+enum {
+	LINKLED_OFF 	     = 0x01,
+	LINKLED_ON  	     = 0x02,
+	LINKLED_LINKSYNC_OFF = 0x04,
+	LINKLED_LINKSYNC_ON  = 0x08,
+	LINKLED_BLINK_OFF    = 0x10,
+	LINKLED_BLINK_ON     = 0x20,
+};
+
+/* GMAC and GPHY Control Registers (YUKON only) */
+enum {
+	GMAC_CTRL	= 0x0f00,/* 32 bit	GMAC Control Reg */
+	GPHY_CTRL	= 0x0f04,/* 32 bit	GPHY Control Reg */
+	GMAC_IRQ_SRC	= 0x0f08,/*  8 bit	GMAC Interrupt Source Reg */
+	GMAC_IRQ_MSK	= 0x0f0c,/*  8 bit	GMAC Interrupt Mask Reg */
+	GMAC_LINK_CTRL	= 0x0f10,/* 16 bit	Link Control Reg */
+
+/* Wake-up Frame Pattern Match Control Registers (YUKON only) */
+
+	WOL_REG_OFFS	= 0x20,/* HW-Bug: Address is + 0x20 against spec. */
+
+	WOL_CTRL_STAT	= 0x0f20,/* 16 bit	WOL Control/Status Reg */
+	WOL_MATCH_CTL	= 0x0f22,/*  8 bit	WOL Match Control Reg */
+	WOL_MATCH_RES	= 0x0f23,/*  8 bit	WOL Match Result Reg */
+	WOL_MAC_ADDR	= 0x0f24,/* 32 bit	WOL MAC Address */
+	WOL_PATT_PME	= 0x0f2a,/*  8 bit	WOL PME Match Enable (Yukon-2) */
+	WOL_PATT_ASFM	= 0x0f2b,/*  8 bit	WOL ASF Match Enable (Yukon-2) */
+	WOL_PATT_RPTR	= 0x0f2c,/*  8 bit	WOL Pattern Read Pointer */
+
+/* WOL Pattern Length Registers (YUKON only) */
+
+	WOL_PATT_LEN_LO	= 0x0f30,/* 32 bit	WOL Pattern Length 3..0 */
+	WOL_PATT_LEN_HI	= 0x0f34,/* 24 bit	WOL Pattern Length 6..4 */
+
+/* WOL Pattern Counter Registers (YUKON only) */
+
+
+	WOL_PATT_CNT_0	= 0x0f38,/* 32 bit	WOL Pattern Counter 3..0 */
+	WOL_PATT_CNT_4	= 0x0f3c,/* 24 bit	WOL Pattern Counter 6..4 */
+};
+
+enum {
+	WOL_PATT_RAM_1	= 0x1000,/*  WOL Pattern RAM Link 1 */
+	WOL_PATT_RAM_2	= 0x1400,/*  WOL Pattern RAM Link 2 */
+};
+
+enum {
+	BASE_GMAC_1	= 0x2800,/* GMAC 1 registers */
+	BASE_GMAC_2	= 0x3800,/* GMAC 2 registers */
+};
+
+/*
+ * Marvel-PHY Registers, indirect addressed over GMAC
+ */
+enum {
+	PHY_MARV_CTRL		= 0x00,/* 16 bit r/w	PHY Control Register */
+	PHY_MARV_STAT		= 0x01,/* 16 bit r/o	PHY Status Register */
+	PHY_MARV_ID0		= 0x02,/* 16 bit r/o	PHY ID0 Register */
+	PHY_MARV_ID1		= 0x03,/* 16 bit r/o	PHY ID1 Register */
+	PHY_MARV_AUNE_ADV	= 0x04,/* 16 bit r/w	Auto-Neg. Advertisement */
+	PHY_MARV_AUNE_LP	= 0x05,/* 16 bit r/o	Link Part Ability Reg */
+	PHY_MARV_AUNE_EXP	= 0x06,/* 16 bit r/o	Auto-Neg. Expansion Reg */
+	PHY_MARV_NEPG		= 0x07,/* 16 bit r/w	Next Page Register */
+	PHY_MARV_NEPG_LP	= 0x08,/* 16 bit r/o	Next Page Link Partner */
+	/* Marvel-specific registers */
+	PHY_MARV_1000T_CTRL	= 0x09,/* 16 bit r/w	1000Base-T Control Reg */
+	PHY_MARV_1000T_STAT	= 0x0a,/* 16 bit r/o	1000Base-T Status Reg */
+	PHY_MARV_EXT_STAT	= 0x0f,/* 16 bit r/o	Extended Status Reg */
+	PHY_MARV_PHY_CTRL	= 0x10,/* 16 bit r/w	PHY Specific Ctrl Reg */
+	PHY_MARV_PHY_STAT	= 0x11,/* 16 bit r/o	PHY Specific Stat Reg */
+	PHY_MARV_INT_MASK	= 0x12,/* 16 bit r/w	Interrupt Mask Reg */
+	PHY_MARV_INT_STAT	= 0x13,/* 16 bit r/o	Interrupt Status Reg */
+	PHY_MARV_EXT_CTRL	= 0x14,/* 16 bit r/w	Ext. PHY Specific Ctrl */
+	PHY_MARV_RXE_CNT	= 0x15,/* 16 bit r/w	Receive Error Counter */
+	PHY_MARV_EXT_ADR	= 0x16,/* 16 bit r/w	Ext. Ad. for Cable Diag. */
+	PHY_MARV_PORT_IRQ	= 0x17,/* 16 bit r/o	Port 0 IRQ (88E1111 only) */
+	PHY_MARV_LED_CTRL	= 0x18,/* 16 bit r/w	LED Control Reg */
+	PHY_MARV_LED_OVER	= 0x19,/* 16 bit r/w	Manual LED Override Reg */
+	PHY_MARV_EXT_CTRL_2	= 0x1a,/* 16 bit r/w	Ext. PHY Specific Ctrl 2 */
+	PHY_MARV_EXT_P_STAT	= 0x1b,/* 16 bit r/w	Ext. PHY Spec. Stat Reg */
+	PHY_MARV_CABLE_DIAG	= 0x1c,/* 16 bit r/o	Cable Diagnostic Reg */
+	PHY_MARV_PAGE_ADDR	= 0x1d,/* 16 bit r/w	Extended Page Address Reg */
+	PHY_MARV_PAGE_DATA	= 0x1e,/* 16 bit r/w	Extended Page Data Reg */
+
+/* for 10/100 Fast Ethernet PHY (88E3082 only) */
+	PHY_MARV_FE_LED_PAR	= 0x16,/* 16 bit r/w	LED Parallel Select Reg. */
+	PHY_MARV_FE_LED_SER	= 0x17,/* 16 bit r/w	LED Stream Select S. LED */
+	PHY_MARV_FE_VCT_TX	= 0x1a,/* 16 bit r/w	VCT Reg. for TXP/N Pins */
+	PHY_MARV_FE_VCT_RX	= 0x1b,/* 16 bit r/o	VCT Reg. for RXP/N Pins */
+	PHY_MARV_FE_SPEC_2	= 0x1c,/* 16 bit r/w	Specific Control Reg. 2 */
+};
+
+enum {
+	PHY_CT_RESET	= 1<<15, /* Bit 15: (sc)	clear all PHY related regs */
+	PHY_CT_LOOP	= 1<<14, /* Bit 14:	enable Loopback over PHY */
+	PHY_CT_SPS_LSB	= 1<<13, /* Bit 13:	Speed select, lower bit */
+	PHY_CT_ANE	= 1<<12, /* Bit 12:	Auto-Negotiation Enabled */
+	PHY_CT_PDOWN	= 1<<11, /* Bit 11:	Power Down Mode */
+	PHY_CT_ISOL	= 1<<10, /* Bit 10:	Isolate Mode */
+	PHY_CT_RE_CFG	= 1<<9, /* Bit  9:	(sc) Restart Auto-Negotiation */
+	PHY_CT_DUP_MD	= 1<<8, /* Bit  8:	Duplex Mode */
+	PHY_CT_COL_TST	= 1<<7, /* Bit  7:	Collision Test enabled */
+	PHY_CT_SPS_MSB	= 1<<6, /* Bit  6:	Speed select, upper bit */
+};
+
+enum {
+	PHY_CT_SP1000	= PHY_CT_SPS_MSB, /* enable speed of 1000 Mbps */
+	PHY_CT_SP100	= PHY_CT_SPS_LSB, /* enable speed of  100 Mbps */
+	PHY_CT_SP10	= 0,		  /* enable speed of   10 Mbps */
+};
+
+enum {
+	PHY_ST_EXT_ST	= 1<<8, /* Bit  8:	Extended Status Present */
+
+	PHY_ST_PRE_SUP	= 1<<6, /* Bit  6:	Preamble Suppression */
+	PHY_ST_AN_OVER	= 1<<5, /* Bit  5:	Auto-Negotiation Over */
+	PHY_ST_REM_FLT	= 1<<4, /* Bit  4:	Remote Fault Condition Occured */
+	PHY_ST_AN_CAP	= 1<<3, /* Bit  3:	Auto-Negotiation Capability */
+	PHY_ST_LSYNC	= 1<<2, /* Bit  2:	Link Synchronized */
+	PHY_ST_JAB_DET	= 1<<1, /* Bit  1:	Jabber Detected */
+	PHY_ST_EXT_REG	= 1<<0, /* Bit  0:	Extended Register available */
+};
+
+enum {
+	PHY_I1_OUI_MSK	= 0x3f<<10, /* Bit 15..10:	Organization Unique ID */
+	PHY_I1_MOD_NUM	= 0x3f<<4, /* Bit  9.. 4:	Model Number */
+	PHY_I1_REV_MSK	= 0xf, /* Bit  3.. 0:	Revision Number */
+};
+
+/* different Marvell PHY Ids */
+enum {
+	PHY_MARV_ID0_VAL= 0x0141, /* Marvell Unique Identifier */
+
+	PHY_BCOM_ID1_A1	= 0x6041,
+	PHY_BCOM_ID1_B2	= 0x6043,
+	PHY_BCOM_ID1_C0	= 0x6044,
+	PHY_BCOM_ID1_C5	= 0x6047,
+
+	PHY_MARV_ID1_B0	= 0x0C23, /* Yukon (PHY 88E1011) */
+	PHY_MARV_ID1_B2	= 0x0C25, /* Yukon-Plus (PHY 88E1011) */
+	PHY_MARV_ID1_C2	= 0x0CC2, /* Yukon-EC (PHY 88E1111) */
+	PHY_MARV_ID1_Y2	= 0x0C91, /* Yukon-2 (PHY 88E1112) */
+};
+
+/* Advertisement register bits */
+enum {
+	PHY_AN_NXT_PG	= 1<<15, /* Bit 15:	Request Next Page */
+	PHY_AN_ACK	= 1<<14, /* Bit 14:	(ro) Acknowledge Received */
+	PHY_AN_RF	= 1<<13, /* Bit 13:	Remote Fault Bits */
+
+	PHY_AN_PAUSE_ASYM = 1<<11,/* Bit 11:	Try for asymmetric */
+	PHY_AN_PAUSE_CAP = 1<<10, /* Bit 10:	Try for pause */
+	PHY_AN_100BASE4	= 1<<9, /* Bit 9:	Try for 100mbps 4k packets */
+	PHY_AN_100FULL	= 1<<8, /* Bit 8:	Try for 100mbps full-duplex */
+	PHY_AN_100HALF	= 1<<7, /* Bit 7:	Try for 100mbps half-duplex */
+	PHY_AN_10FULL	= 1<<6, /* Bit 6:	Try for 10mbps full-duplex */
+	PHY_AN_10HALF	= 1<<5, /* Bit 5:	Try for 10mbps half-duplex */
+	PHY_AN_CSMA	= 1<<0, /* Bit 0:	Only selector supported */
+	PHY_AN_SEL	= 0x1f, /* Bit 4..0:	Selector Field, 00001=Ethernet*/
+	PHY_AN_FULL	= PHY_AN_100FULL | PHY_AN_10FULL | PHY_AN_CSMA,
+	PHY_AN_ALL	= PHY_AN_10HALF | PHY_AN_10FULL |
+		  	  PHY_AN_100HALF | PHY_AN_100FULL,
+};
+
+/*****  PHY_BCOM_1000T_STAT	16 bit r/o	1000Base-T Status Reg *****/
+/*****  PHY_MARV_1000T_STAT	16 bit r/o	1000Base-T Status Reg *****/
+enum {
+	PHY_B_1000S_MSF	= 1<<15, /* Bit 15:	Master/Slave Fault */
+	PHY_B_1000S_MSR	= 1<<14, /* Bit 14:	Master/Slave Result */
+	PHY_B_1000S_LRS	= 1<<13, /* Bit 13:	Local Receiver Status */
+	PHY_B_1000S_RRS	= 1<<12, /* Bit 12:	Remote Receiver Status */
+	PHY_B_1000S_LP_FD	= 1<<11, /* Bit 11:	Link Partner can FD */
+	PHY_B_1000S_LP_HD	= 1<<10, /* Bit 10:	Link Partner can HD */
+									/* Bit  9..8:	reserved */
+	PHY_B_1000S_IEC	= 0xff, /* Bit  7..0:	Idle Error Count */
+};
+
+/** Marvell-Specific */
+enum {
+	PHY_M_AN_NXT_PG	= 1<<15, /* Request Next Page */
+	PHY_M_AN_ACK	= 1<<14, /* (ro)	Acknowledge Received */
+	PHY_M_AN_RF	= 1<<13, /* Remote Fault */
+
+	PHY_M_AN_ASP	= 1<<11, /* Asymmetric Pause */
+	PHY_M_AN_PC	= 1<<10, /* MAC Pause implemented */
+	PHY_M_AN_100_T4	= 1<<9, /* Not cap. 100Base-T4 (always 0) */
+	PHY_M_AN_100_FD	= 1<<8, /* Advertise 100Base-TX Full Duplex */
+	PHY_M_AN_100_HD	= 1<<7, /* Advertise 100Base-TX Half Duplex */
+	PHY_M_AN_10_FD	= 1<<6, /* Advertise 10Base-TX Full Duplex */
+	PHY_M_AN_10_HD	= 1<<5, /* Advertise 10Base-TX Half Duplex */
+	PHY_M_AN_SEL_MSK =0x1f<<4,	/* Bit  4.. 0: Selector Field Mask */
+};
+
+/* special defines for FIBER (88E1011S only) */
+enum {
+	PHY_M_AN_ASP_X	= 1<<8, /* Asymmetric Pause */
+	PHY_M_AN_PC_X	= 1<<7, /* MAC Pause implemented */
+	PHY_M_AN_1000X_AHD	= 1<<6, /* Advertise 10000Base-X Half Duplex */
+	PHY_M_AN_1000X_AFD	= 1<<5, /* Advertise 10000Base-X Full Duplex */
+};
+
+/* Pause Bits (PHY_M_AN_ASP_X and PHY_M_AN_PC_X) encoding */
+enum {
+	PHY_M_P_NO_PAUSE_X	= 0<<7,/* Bit  8.. 7:	no Pause Mode */
+	PHY_M_P_SYM_MD_X	= 1<<7, /* Bit  8.. 7:	symmetric Pause Mode */
+	PHY_M_P_ASYM_MD_X	= 2<<7,/* Bit  8.. 7:	asymmetric Pause Mode */
+	PHY_M_P_BOTH_MD_X	= 3<<7,/* Bit  8.. 7:	both Pause Mode */
+};
+
+/*****  PHY_MARV_1000T_CTRL	16 bit r/w	1000Base-T Control Reg *****/
+enum {
+	PHY_M_1000C_TEST	= 7<<13,/* Bit 15..13:	Test Modes */
+	PHY_M_1000C_MSE	= 1<<12, /* Manual Master/Slave Enable */
+	PHY_M_1000C_MSC	= 1<<11, /* M/S Configuration (1=Master) */
+	PHY_M_1000C_MPD	= 1<<10, /* Multi-Port Device */
+	PHY_M_1000C_AFD	= 1<<9, /* Advertise Full Duplex */
+	PHY_M_1000C_AHD	= 1<<8, /* Advertise Half Duplex */
+};
+
+/*****  PHY_MARV_PHY_CTRL	16 bit r/w	PHY Specific Ctrl Reg *****/
+enum {
+	PHY_M_PC_TX_FFD_MSK	= 3<<14,/* Bit 15..14: Tx FIFO Depth Mask */
+	PHY_M_PC_RX_FFD_MSK	= 3<<12,/* Bit 13..12: Rx FIFO Depth Mask */
+	PHY_M_PC_ASS_CRS_TX	= 1<<11, /* Assert CRS on Transmit */
+	PHY_M_PC_FL_GOOD	= 1<<10, /* Force Link Good */
+	PHY_M_PC_EN_DET_MSK	= 3<<8,/* Bit  9.. 8: Energy Detect Mask */
+	PHY_M_PC_ENA_EXT_D	= 1<<7, /* Enable Ext. Distance (10BT) */
+	PHY_M_PC_MDIX_MSK	= 3<<5,/* Bit  6.. 5: MDI/MDIX Config. Mask */
+	PHY_M_PC_DIS_125CLK	= 1<<4, /* Disable 125 CLK */
+	PHY_M_PC_MAC_POW_UP	= 1<<3, /* MAC Power up */
+	PHY_M_PC_SQE_T_ENA	= 1<<2, /* SQE Test Enabled */
+	PHY_M_PC_POL_R_DIS	= 1<<1, /* Polarity Reversal Disabled */
+	PHY_M_PC_DIS_JABBER	= 1<<0, /* Disable Jabber */
+};
+
+enum {
+	PHY_M_PC_EN_DET		= 2<<8,	/* Energy Detect (Mode 1) */
+	PHY_M_PC_EN_DET_PLUS	= 3<<8, /* Energy Detect Plus (Mode 2) */
+};
+
+#define PHY_M_PC_MDI_XMODE(x)	(((x)<<5) & PHY_M_PC_MDIX_MSK)
+
+enum {
+	PHY_M_PC_MAN_MDI	= 0, /* 00 = Manual MDI configuration */
+	PHY_M_PC_MAN_MDIX	= 1, /* 01 = Manual MDIX configuration */
+	PHY_M_PC_ENA_AUTO	= 3, /* 11 = Enable Automatic Crossover */
+};
+
+/* for 10/100 Fast Ethernet PHY (88E3082 only) */
+enum {
+	PHY_M_PC_ENA_DTE_DT	= 1<<15, /* Enable Data Terminal Equ. (DTE) Detect */
+	PHY_M_PC_ENA_ENE_DT	= 1<<14, /* Enable Energy Detect (sense & pulse) */
+	PHY_M_PC_DIS_NLP_CK	= 1<<13, /* Disable Normal Link Puls (NLP) Check */
+	PHY_M_PC_ENA_LIP_NP	= 1<<12, /* Enable Link Partner Next Page Reg. */
+	PHY_M_PC_DIS_NLP_GN	= 1<<11, /* Disable Normal Link Puls Generation */
+
+	PHY_M_PC_DIS_SCRAMB	= 1<<9, /* Disable Scrambler */
+	PHY_M_PC_DIS_FEFI	= 1<<8, /* Disable Far End Fault Indic. (FEFI) */
+
+	PHY_M_PC_SH_TP_SEL	= 1<<6, /* Shielded Twisted Pair Select */
+	PHY_M_PC_RX_FD_MSK	= 3<<2,/* Bit  3.. 2: Rx FIFO Depth Mask */
+};
+
+/*****  PHY_MARV_PHY_STAT	16 bit r/o	PHY Specific Status Reg *****/
+enum {
+	PHY_M_PS_SPEED_MSK	= 3<<14, /* Bit 15..14: Speed Mask */
+	PHY_M_PS_SPEED_1000	= 1<<15, /*		10 = 1000 Mbps */
+	PHY_M_PS_SPEED_100	= 1<<14, /*		01 =  100 Mbps */
+	PHY_M_PS_SPEED_10	= 0,	 /*		00 =   10 Mbps */
+	PHY_M_PS_FULL_DUP	= 1<<13, /* Full Duplex */
+	PHY_M_PS_PAGE_REC	= 1<<12, /* Page Received */
+	PHY_M_PS_SPDUP_RES	= 1<<11, /* Speed & Duplex Resolved */
+	PHY_M_PS_LINK_UP	= 1<<10, /* Link Up */
+	PHY_M_PS_CABLE_MSK	= 7<<7,  /* Bit  9.. 7: Cable Length Mask */
+	PHY_M_PS_MDI_X_STAT	= 1<<6,  /* MDI Crossover Stat (1=MDIX) */
+	PHY_M_PS_DOWNS_STAT	= 1<<5,  /* Downshift Status (1=downsh.) */
+	PHY_M_PS_ENDET_STAT	= 1<<4,  /* Energy Detect Status (1=act) */
+	PHY_M_PS_TX_P_EN	= 1<<3,  /* Tx Pause Enabled */
+	PHY_M_PS_RX_P_EN	= 1<<2,  /* Rx Pause Enabled */
+	PHY_M_PS_POL_REV	= 1<<1,  /* Polarity Reversed */
+	PHY_M_PS_JABBER		= 1<<0,  /* Jabber */
+};
+
+#define PHY_M_PS_PAUSE_MSK	(PHY_M_PS_TX_P_EN | PHY_M_PS_RX_P_EN)
+
+/* for 10/100 Fast Ethernet PHY (88E3082 only) */
+enum {
+	PHY_M_PS_DTE_DETECT	= 1<<15, /* Data Terminal Equipment (DTE) Detected */
+	PHY_M_PS_RES_SPEED	= 1<<14, /* Resolved Speed (1=100 Mbps, 0=10 Mbps */
+};
+
+enum {
+	PHY_M_IS_AN_ERROR	= 1<<15, /* Auto-Negotiation Error */
+	PHY_M_IS_LSP_CHANGE	= 1<<14, /* Link Speed Changed */
+	PHY_M_IS_DUP_CHANGE	= 1<<13, /* Duplex Mode Changed */
+	PHY_M_IS_AN_PR		= 1<<12, /* Page Received */
+	PHY_M_IS_AN_COMPL	= 1<<11, /* Auto-Negotiation Completed */
+	PHY_M_IS_LST_CHANGE	= 1<<10, /* Link Status Changed */
+	PHY_M_IS_SYMB_ERROR	= 1<<9, /* Symbol Error */
+	PHY_M_IS_FALSE_CARR	= 1<<8, /* False Carrier */
+	PHY_M_IS_FIFO_ERROR	= 1<<7, /* FIFO Overflow/Underrun Error */
+	PHY_M_IS_MDI_CHANGE	= 1<<6, /* MDI Crossover Changed */
+	PHY_M_IS_DOWNSH_DET	= 1<<5, /* Downshift Detected */
+	PHY_M_IS_END_CHANGE	= 1<<4, /* Energy Detect Changed */
+
+	PHY_M_IS_DTE_CHANGE	= 1<<2, /* DTE Power Det. Status Changed */
+	PHY_M_IS_POL_CHANGE	= 1<<1, /* Polarity Changed */
+	PHY_M_IS_JABBER		= 1<<0, /* Jabber */
+
+	PHY_M_DEF_MSK		= PHY_M_IS_LSP_CHANGE | PHY_M_IS_LST_CHANGE
+				 | PHY_M_IS_FIFO_ERROR,
+	PHY_M_AN_MSK	       = PHY_M_IS_AN_ERROR | PHY_M_IS_AN_COMPL,
+};
+
+
+/*****  PHY_MARV_EXT_CTRL	16 bit r/w	Ext. PHY Specific Ctrl *****/
+enum {
+	PHY_M_EC_ENA_BC_EXT = 1<<15, /* Enable Block Carr. Ext. (88E1111 only) */
+	PHY_M_EC_ENA_LIN_LB = 1<<14, /* Enable Line Loopback (88E1111 only) */
+
+	PHY_M_EC_DIS_LINK_P = 1<<12, /* Disable Link Pulses (88E1111 only) */
+	PHY_M_EC_M_DSC_MSK  = 3<<10, /* Bit 11..10:	Master Downshift Counter */
+					/* (88E1011 only) */
+	PHY_M_EC_S_DSC_MSK  = 3<<8,/* Bit  9.. 8:	Slave  Downshift Counter */
+				       /* (88E1011 only) */
+	PHY_M_EC_M_DSC_MSK2 = 7<<9,/* Bit 11.. 9:	Master Downshift Counter */
+					/* (88E1111 only) */
+	PHY_M_EC_DOWN_S_ENA = 1<<8, /* Downshift Enable (88E1111 only) */
+					/* !!! Errata in spec. (1 = disable) */
+	PHY_M_EC_RX_TIM_CT  = 1<<7, /* RGMII Rx Timing Control*/
+	PHY_M_EC_MAC_S_MSK  = 7<<4,/* Bit  6.. 4:	Def. MAC interface speed */
+	PHY_M_EC_FIB_AN_ENA = 1<<3, /* Fiber Auto-Neg. Enable (88E1011S only) */
+	PHY_M_EC_DTE_D_ENA  = 1<<2, /* DTE Detect Enable (88E1111 only) */
+	PHY_M_EC_TX_TIM_CT  = 1<<1, /* RGMII Tx Timing Control */
+	PHY_M_EC_TRANS_DIS  = 1<<0, /* Transmitter Disable (88E1111 only) */};
+
+#define PHY_M_EC_M_DSC(x)	((x)<<10 & PHY_M_EC_M_DSC_MSK)
+					/* 00=1x; 01=2x; 10=3x; 11=4x */
+#define PHY_M_EC_S_DSC(x)	((x)<<8 & PHY_M_EC_S_DSC_MSK)
+					/* 00=dis; 01=1x; 10=2x; 11=3x */
+#define PHY_M_EC_DSC_2(x)	((x)<<9 & PHY_M_EC_M_DSC_MSK2)
+					/* 000=1x; 001=2x; 010=3x; 011=4x */
+#define PHY_M_EC_MAC_S(x)	((x)<<4 & PHY_M_EC_MAC_S_MSK)
+					/* 01X=0; 110=2.5; 111=25 (MHz) */
+
+/* for Yukon-2 Gigabit Ethernet PHY (88E1112 only) */
+enum {
+	PHY_M_PC_DIS_LINK_Pa	= 1<<15,/* Disable Link Pulses */
+	PHY_M_PC_DSC_MSK	= 7<<12,/* Bit 14..12:	Downshift Counter */
+	PHY_M_PC_DOWN_S_ENA	= 1<<11,/* Downshift Enable */
+};
+/* !!! Errata in spec. (1 = disable) */
+
+#define PHY_M_PC_DSC(x)			(((x)<<12) & PHY_M_PC_DSC_MSK)
+											/* 100=5x; 101=6x; 110=7x; 111=8x */
+enum {
+	MAC_TX_CLK_0_MHZ	= 2,
+	MAC_TX_CLK_2_5_MHZ	= 6,
+	MAC_TX_CLK_25_MHZ 	= 7,
+};
+
+/*****  PHY_MARV_LED_CTRL	16 bit r/w	LED Control Reg *****/
+enum {
+	PHY_M_LEDC_DIS_LED	= 1<<15, /* Disable LED */
+	PHY_M_LEDC_PULS_MSK	= 7<<12,/* Bit 14..12: Pulse Stretch Mask */
+	PHY_M_LEDC_F_INT	= 1<<11, /* Force Interrupt */
+	PHY_M_LEDC_BL_R_MSK	= 7<<8,/* Bit 10.. 8: Blink Rate Mask */
+	PHY_M_LEDC_DP_C_LSB	= 1<<7, /* Duplex Control (LSB, 88E1111 only) */
+	PHY_M_LEDC_TX_C_LSB	= 1<<6, /* Tx Control (LSB, 88E1111 only) */
+	PHY_M_LEDC_LK_C_MSK	= 7<<3,/* Bit  5.. 3: Link Control Mask */
+					/* (88E1111 only) */
+};
+
+enum {
+	PHY_M_LEDC_LINK_MSK	= 3<<3,/* Bit  4.. 3: Link Control Mask */
+									/* (88E1011 only) */
+	PHY_M_LEDC_DP_CTRL	= 1<<2, /* Duplex Control */
+	PHY_M_LEDC_DP_C_MSB	= 1<<2, /* Duplex Control (MSB, 88E1111 only) */
+	PHY_M_LEDC_RX_CTRL	= 1<<1, /* Rx Activity / Link */
+	PHY_M_LEDC_TX_CTRL	= 1<<0, /* Tx Activity / Link */
+	PHY_M_LEDC_TX_C_MSB	= 1<<0, /* Tx Control (MSB, 88E1111 only) */
+};
+
+#define PHY_M_LED_PULS_DUR(x)	(((x)<<12) & PHY_M_LEDC_PULS_MSK)
+
+/*****  PHY_MARV_PHY_STAT (page 3)16 bit r/w	Polarity Control Reg. *****/
+enum {
+	PHY_M_POLC_LS1M_MSK	= 0xf<<12, /* Bit 15..12: LOS,STAT1 Mix % Mask */
+	PHY_M_POLC_IS0M_MSK	= 0xf<<8,  /* Bit 11.. 8: INIT,STAT0 Mix % Mask */
+	PHY_M_POLC_LOS_MSK	= 0x3<<6,  /* Bit  7.. 6: LOS Pol. Ctrl. Mask */
+	PHY_M_POLC_INIT_MSK	= 0x3<<4,  /* Bit  5.. 4: INIT Pol. Ctrl. Mask */
+	PHY_M_POLC_STA1_MSK	= 0x3<<2,  /* Bit  3.. 2: STAT1 Pol. Ctrl. Mask */
+	PHY_M_POLC_STA0_MSK	= 0x3,     /* Bit  1.. 0: STAT0 Pol. Ctrl. Mask */
+};
+
+#define PHY_M_POLC_LS1_P_MIX(x)	(((x)<<12) & PHY_M_POLC_LS1M_MSK)
+#define PHY_M_POLC_IS0_P_MIX(x)	(((x)<<8) & PHY_M_POLC_IS0M_MSK)
+#define PHY_M_POLC_LOS_CTRL(x)	(((x)<<6) & PHY_M_POLC_LOS_MSK)
+#define PHY_M_POLC_INIT_CTRL(x)	(((x)<<4) & PHY_M_POLC_INIT_MSK)
+#define PHY_M_POLC_STA1_CTRL(x)	(((x)<<2) & PHY_M_POLC_STA1_MSK)
+#define PHY_M_POLC_STA0_CTRL(x)	(((x)<<0) & PHY_M_POLC_STA0_MSK)
+
+enum {
+	PULS_NO_STR	= 0,/* no pulse stretching */
+	PULS_21MS	= 1,/* 21 ms to 42 ms */
+	PULS_42MS	= 2,/* 42 ms to 84 ms */
+	PULS_84MS	= 3,/* 84 ms to 170 ms */
+	PULS_170MS	= 4,/* 170 ms to 340 ms */
+	PULS_340MS	= 5,/* 340 ms to 670 ms */
+	PULS_670MS	= 6,/* 670 ms to 1.3 s */
+	PULS_1300MS	= 7,/* 1.3 s to 2.7 s */
+};
+
+#define PHY_M_LED_BLINK_RT(x)	(((x)<<8) & PHY_M_LEDC_BL_R_MSK)
+
+enum {
+	BLINK_42MS	= 0,/* 42 ms */
+	BLINK_84MS	= 1,/* 84 ms */
+	BLINK_170MS	= 2,/* 170 ms */
+	BLINK_340MS	= 3,/* 340 ms */
+	BLINK_670MS	= 4,/* 670 ms */
+};
+
+/*****  PHY_MARV_LED_OVER	16 bit r/w	Manual LED Override Reg *****/
+#define PHY_M_LED_MO_SGMII(x)	((x)<<14) /* Bit 15..14:  SGMII AN Timer */
+										/* Bit 13..12:	reserved */
+#define PHY_M_LED_MO_DUP(x)	((x)<<10) /* Bit 11..10:  Duplex */
+#define PHY_M_LED_MO_10(x)	((x)<<8) /* Bit  9.. 8:  Link 10 */
+#define PHY_M_LED_MO_100(x)	((x)<<6) /* Bit  7.. 6:  Link 100 */
+#define PHY_M_LED_MO_1000(x)	((x)<<4) /* Bit  5.. 4:  Link 1000 */
+#define PHY_M_LED_MO_RX(x)	((x)<<2) /* Bit  3.. 2:  Rx */
+#define PHY_M_LED_MO_TX(x)	((x)<<0) /* Bit  1.. 0:  Tx */
+
+enum {
+	MO_LED_NORM	= 0,
+	MO_LED_BLINK	= 1,
+	MO_LED_OFF	= 2,
+	MO_LED_ON	= 3,
+};
+
+/*****  PHY_MARV_EXT_CTRL_2	16 bit r/w	Ext. PHY Specific Ctrl 2 *****/
+enum {
+	PHY_M_EC2_FI_IMPED	= 1<<6, /* Fiber Input  Impedance */
+	PHY_M_EC2_FO_IMPED	= 1<<5, /* Fiber Output Impedance */
+	PHY_M_EC2_FO_M_CLK	= 1<<4, /* Fiber Mode Clock Enable */
+	PHY_M_EC2_FO_BOOST	= 1<<3, /* Fiber Output Boost */
+	PHY_M_EC2_FO_AM_MSK	= 7,/* Bit  2.. 0:	Fiber Output Amplitude */
+};
+
+/*****  PHY_MARV_EXT_P_STAT 16 bit r/w	Ext. PHY Specific Status *****/
+enum {
+	PHY_M_FC_AUTO_SEL	= 1<<15, /* Fiber/Copper Auto Sel. Dis. */
+	PHY_M_FC_AN_REG_ACC	= 1<<14, /* Fiber/Copper AN Reg. Access */
+	PHY_M_FC_RESOLUTION	= 1<<13, /* Fiber/Copper Resolution */
+	PHY_M_SER_IF_AN_BP	= 1<<12, /* Ser. IF AN Bypass Enable */
+	PHY_M_SER_IF_BP_ST	= 1<<11, /* Ser. IF AN Bypass Status */
+	PHY_M_IRQ_POLARITY	= 1<<10, /* IRQ polarity */
+	PHY_M_DIS_AUT_MED	= 1<<9, /* Disable Aut. Medium Reg. Selection */
+	/* (88E1111 only) */
+
+	PHY_M_UNDOC1		= 1<<7, /* undocumented bit !! */
+	PHY_M_DTE_POW_STAT	= 1<<4, /* DTE Power Status (88E1111 only) */
+	PHY_M_MODE_MASK	= 0xf, /* Bit  3.. 0: copy of HWCFG MODE[3:0] */
+};
+
+/* for 10/100 Fast Ethernet PHY (88E3082 only) */
+/*****  PHY_MARV_FE_LED_PAR		16 bit r/w	LED Parallel Select Reg. *****/
+									/* Bit 15..12: reserved (used internally) */
+enum {
+	PHY_M_FELP_LED2_MSK = 0xf<<8,	/* Bit 11.. 8: LED2 Mask (LINK) */
+	PHY_M_FELP_LED1_MSK = 0xf<<4,	/* Bit  7.. 4: LED1 Mask (ACT) */
+	PHY_M_FELP_LED0_MSK = 0xf, /* Bit  3.. 0: LED0 Mask (SPEED) */
+};
+
+#define PHY_M_FELP_LED2_CTRL(x)	(((x)<<8) & PHY_M_FELP_LED2_MSK)
+#define PHY_M_FELP_LED1_CTRL(x)	(((x)<<4) & PHY_M_FELP_LED1_MSK)
+#define PHY_M_FELP_LED0_CTRL(x)	(((x)<<0) & PHY_M_FELP_LED0_MSK)
+
+enum {
+	LED_PAR_CTRL_COLX	= 0x00,
+	LED_PAR_CTRL_ERROR	= 0x01,
+	LED_PAR_CTRL_DUPLEX	= 0x02,
+	LED_PAR_CTRL_DP_COL	= 0x03,
+	LED_PAR_CTRL_SPEED	= 0x04,
+	LED_PAR_CTRL_LINK	= 0x05,
+	LED_PAR_CTRL_TX		= 0x06,
+	LED_PAR_CTRL_RX		= 0x07,
+	LED_PAR_CTRL_ACT	= 0x08,
+	LED_PAR_CTRL_LNK_RX	= 0x09,
+	LED_PAR_CTRL_LNK_AC	= 0x0a,
+	LED_PAR_CTRL_ACT_BL	= 0x0b,
+	LED_PAR_CTRL_TX_BL	= 0x0c,
+	LED_PAR_CTRL_RX_BL	= 0x0d,
+	LED_PAR_CTRL_COL_BL	= 0x0e,
+	LED_PAR_CTRL_INACT	= 0x0f
+};
+
+/*****,PHY_MARV_FE_SPEC_2		16 bit r/w	Specific Control Reg. 2 *****/
+enum {
+	PHY_M_FESC_DIS_WAIT	= 1<<2, /* Disable TDR Waiting Period */
+	PHY_M_FESC_ENA_MCLK	= 1<<1, /* Enable MAC Rx Clock in sleep mode */
+	PHY_M_FESC_SEL_CL_A	= 1<<0, /* Select Class A driver (100B-TX) */
+};
+
+/* for Yukon-2 Gigabit Ethernet PHY (88E1112 only) */
+/*****  PHY_MARV_PHY_CTRL (page 2)		16 bit r/w	MAC Specific Ctrl *****/
+enum {
+	PHY_M_MAC_MD_MSK	= 7<<7, /* Bit  9.. 7: Mode Select Mask */
+	PHY_M_MAC_MD_AUTO	= 3,/* Auto Copper/1000Base-X */
+	PHY_M_MAC_MD_COPPER	= 5,/* Copper only */
+	PHY_M_MAC_MD_1000BX	= 7,/* 1000Base-X only */
+};
+#define PHY_M_MAC_MODE_SEL(x)	(((x)<<7) & PHY_M_MAC_MD_MSK)
+
+/*****  PHY_MARV_PHY_CTRL (page 3)		16 bit r/w	LED Control Reg. *****/
+enum {
+	PHY_M_LEDC_LOS_MSK	= 0xf<<12,/* Bit 15..12: LOS LED Ctrl. Mask */
+	PHY_M_LEDC_INIT_MSK	= 0xf<<8, /* Bit 11.. 8: INIT LED Ctrl. Mask */
+	PHY_M_LEDC_STA1_MSK	= 0xf<<4,/* Bit  7.. 4: STAT1 LED Ctrl. Mask */
+	PHY_M_LEDC_STA0_MSK	= 0xf, /* Bit  3.. 0: STAT0 LED Ctrl. Mask */
+};
+
+#define PHY_M_LEDC_LOS_CTRL(x)	(((x)<<12) & PHY_M_LEDC_LOS_MSK)
+#define PHY_M_LEDC_INIT_CTRL(x)	(((x)<<8) & PHY_M_LEDC_INIT_MSK)
+#define PHY_M_LEDC_STA1_CTRL(x)	(((x)<<4) & PHY_M_LEDC_STA1_MSK)
+#define PHY_M_LEDC_STA0_CTRL(x)	(((x)<<0) & PHY_M_LEDC_STA0_MSK)
+
+/* GMAC registers  */
+/* Port Registers */
+enum {
+	GM_GP_STAT	= 0x0000,	/* 16 bit r/o	General Purpose Status */
+	GM_GP_CTRL	= 0x0004,	/* 16 bit r/w	General Purpose Control */
+	GM_TX_CTRL	= 0x0008,	/* 16 bit r/w	Transmit Control Reg. */
+	GM_RX_CTRL	= 0x000c,	/* 16 bit r/w	Receive Control Reg. */
+	GM_TX_FLOW_CTRL	= 0x0010,	/* 16 bit r/w	Transmit Flow-Control */
+	GM_TX_PARAM	= 0x0014,	/* 16 bit r/w	Transmit Parameter Reg. */
+	GM_SERIAL_MODE	= 0x0018,	/* 16 bit r/w	Serial Mode Register */
+/* Source Address Registers */
+	GM_SRC_ADDR_1L	= 0x001c,	/* 16 bit r/w	Source Address 1 (low) */
+	GM_SRC_ADDR_1M	= 0x0020,	/* 16 bit r/w	Source Address 1 (middle) */
+	GM_SRC_ADDR_1H	= 0x0024,	/* 16 bit r/w	Source Address 1 (high) */
+	GM_SRC_ADDR_2L	= 0x0028,	/* 16 bit r/w	Source Address 2 (low) */
+	GM_SRC_ADDR_2M	= 0x002c,	/* 16 bit r/w	Source Address 2 (middle) */
+	GM_SRC_ADDR_2H	= 0x0030,	/* 16 bit r/w	Source Address 2 (high) */
+
+/* Multicast Address Hash Registers */
+	GM_MC_ADDR_H1	= 0x0034,	/* 16 bit r/w	Multicast Address Hash 1 */
+	GM_MC_ADDR_H2	= 0x0038,	/* 16 bit r/w	Multicast Address Hash 2 */
+	GM_MC_ADDR_H3	= 0x003c,	/* 16 bit r/w	Multicast Address Hash 3 */
+	GM_MC_ADDR_H4	= 0x0040,	/* 16 bit r/w	Multicast Address Hash 4 */
+
+/* Interrupt Source Registers */
+	GM_TX_IRQ_SRC	= 0x0044,	/* 16 bit r/o	Tx Overflow IRQ Source */
+	GM_RX_IRQ_SRC	= 0x0048,	/* 16 bit r/o	Rx Overflow IRQ Source */
+	GM_TR_IRQ_SRC	= 0x004c,	/* 16 bit r/o	Tx/Rx Over. IRQ Source */
+
+/* Interrupt Mask Registers */
+	GM_TX_IRQ_MSK	= 0x0050,	/* 16 bit r/w	Tx Overflow IRQ Mask */
+	GM_RX_IRQ_MSK	= 0x0054,	/* 16 bit r/w	Rx Overflow IRQ Mask */
+	GM_TR_IRQ_MSK	= 0x0058,	/* 16 bit r/w	Tx/Rx Over. IRQ Mask */
+
+/* Serial Management Interface (SMI) Registers */
+	GM_SMI_CTRL	= 0x0080,	/* 16 bit r/w	SMI Control Register */
+	GM_SMI_DATA	= 0x0084,	/* 16 bit r/w	SMI Data Register */
+	GM_PHY_ADDR	= 0x0088,	/* 16 bit r/w	GPHY Address Register */
+};
+
+/* MIB Counters */
+#define GM_MIB_CNT_BASE	0x0100		/* Base Address of MIB Counters */
+#define GM_MIB_CNT_SIZE	44		/* Number of MIB Counters */
+
+/*
+ * MIB Counters base address definitions (low word) -
+ * use offset 4 for access to high word	(32 bit r/o)
+ */
+enum {
+	GM_RXF_UC_OK  = GM_MIB_CNT_BASE + 0,	/* Unicast Frames Received OK */
+	GM_RXF_BC_OK	= GM_MIB_CNT_BASE + 8,	/* Broadcast Frames Received OK */
+	GM_RXF_MPAUSE	= GM_MIB_CNT_BASE + 16,	/* Pause MAC Ctrl Frames Received */
+	GM_RXF_MC_OK	= GM_MIB_CNT_BASE + 24,	/* Multicast Frames Received OK */
+	GM_RXF_FCS_ERR	= GM_MIB_CNT_BASE + 32,	/* Rx Frame Check Seq. Error */
+	/* GM_MIB_CNT_BASE + 40:	reserved */
+	GM_RXO_OK_LO	= GM_MIB_CNT_BASE + 48,	/* Octets Received OK Low */
+	GM_RXO_OK_HI	= GM_MIB_CNT_BASE + 56,	/* Octets Received OK High */
+	GM_RXO_ERR_LO	= GM_MIB_CNT_BASE + 64,	/* Octets Received Invalid Low */
+	GM_RXO_ERR_HI	= GM_MIB_CNT_BASE + 72,	/* Octets Received Invalid High */
+	GM_RXF_SHT	= GM_MIB_CNT_BASE + 80,	/* Frames <64 Byte Received OK */
+	GM_RXE_FRAG	= GM_MIB_CNT_BASE + 88,	/* Frames <64 Byte Received with FCS Err */
+	GM_RXF_64B	= GM_MIB_CNT_BASE + 96,	/* 64 Byte Rx Frame */
+	GM_RXF_127B	= GM_MIB_CNT_BASE + 104,	/* 65-127 Byte Rx Frame */
+	GM_RXF_255B	= GM_MIB_CNT_BASE + 112,	/* 128-255 Byte Rx Frame */
+	GM_RXF_511B	= GM_MIB_CNT_BASE + 120,	/* 256-511 Byte Rx Frame */
+	GM_RXF_1023B	= GM_MIB_CNT_BASE + 128,	/* 512-1023 Byte Rx Frame */
+	GM_RXF_1518B	= GM_MIB_CNT_BASE + 136,	/* 1024-1518 Byte Rx Frame */
+	GM_RXF_MAX_SZ	= GM_MIB_CNT_BASE + 144,	/* 1519-MaxSize Byte Rx Frame */
+	GM_RXF_LNG_ERR	= GM_MIB_CNT_BASE + 152,	/* Rx Frame too Long Error */
+	GM_RXF_JAB_PKT	= GM_MIB_CNT_BASE + 160,	/* Rx Jabber Packet Frame */
+	/* GM_MIB_CNT_BASE + 168:	reserved */
+	GM_RXE_FIFO_OV	= GM_MIB_CNT_BASE + 176,	/* Rx FIFO overflow Event */
+	/* GM_MIB_CNT_BASE + 184:	reserved */
+	GM_TXF_UC_OK	= GM_MIB_CNT_BASE + 192,	/* Unicast Frames Xmitted OK */
+	GM_TXF_BC_OK	= GM_MIB_CNT_BASE + 200,	/* Broadcast Frames Xmitted OK */
+	GM_TXF_MPAUSE	= GM_MIB_CNT_BASE + 208,	/* Pause MAC Ctrl Frames Xmitted */
+	GM_TXF_MC_OK	= GM_MIB_CNT_BASE + 216,	/* Multicast Frames Xmitted OK */
+	GM_TXO_OK_LO	= GM_MIB_CNT_BASE + 224,	/* Octets Transmitted OK Low */
+	GM_TXO_OK_HI	= GM_MIB_CNT_BASE + 232,	/* Octets Transmitted OK High */
+	GM_TXF_64B	= GM_MIB_CNT_BASE + 240,	/* 64 Byte Tx Frame */
+	GM_TXF_127B	= GM_MIB_CNT_BASE + 248,	/* 65-127 Byte Tx Frame */
+	GM_TXF_255B	= GM_MIB_CNT_BASE + 256,	/* 128-255 Byte Tx Frame */
+	GM_TXF_511B	= GM_MIB_CNT_BASE + 264,	/* 256-511 Byte Tx Frame */
+	GM_TXF_1023B	= GM_MIB_CNT_BASE + 272,	/* 512-1023 Byte Tx Frame */
+	GM_TXF_1518B	= GM_MIB_CNT_BASE + 280,	/* 1024-1518 Byte Tx Frame */
+	GM_TXF_MAX_SZ	= GM_MIB_CNT_BASE + 288,	/* 1519-MaxSize Byte Tx Frame */
+
+	GM_TXF_COL	= GM_MIB_CNT_BASE + 304,	/* Tx Collision */
+	GM_TXF_LAT_COL	= GM_MIB_CNT_BASE + 312,	/* Tx Late Collision */
+	GM_TXF_ABO_COL	= GM_MIB_CNT_BASE + 320,	/* Tx aborted due to Exces. Col. */
+	GM_TXF_MUL_COL	= GM_MIB_CNT_BASE + 328,	/* Tx Multiple Collision */
+	GM_TXF_SNG_COL	= GM_MIB_CNT_BASE + 336,	/* Tx Single Collision */
+	GM_TXE_FIFO_UR	= GM_MIB_CNT_BASE + 344,	/* Tx FIFO Underrun Event */
+};
+
+/* GMAC Bit Definitions */
+/*	GM_GP_STAT	16 bit r/o	General Purpose Status Register */
+enum {
+	GM_GPSR_SPEED		= 1<<15, /* Bit 15:	Port Speed (1 = 100 Mbps) */
+	GM_GPSR_DUPLEX		= 1<<14, /* Bit 14:	Duplex Mode (1 = Full) */
+	GM_GPSR_FC_TX_DIS	= 1<<13, /* Bit 13:	Tx Flow-Control Mode Disabled */
+	GM_GPSR_LINK_UP		= 1<<12, /* Bit 12:	Link Up Status */
+	GM_GPSR_PAUSE		= 1<<11, /* Bit 11:	Pause State */
+	GM_GPSR_TX_ACTIVE	= 1<<10, /* Bit 10:	Tx in Progress */
+	GM_GPSR_EXC_COL		= 1<<9,	/* Bit  9:	Excessive Collisions Occured */
+	GM_GPSR_LAT_COL		= 1<<8,	/* Bit  8:	Late Collisions Occured */
+
+	GM_GPSR_PHY_ST_CH	= 1<<5,	/* Bit  5:	PHY Status Change */
+	GM_GPSR_GIG_SPEED	= 1<<4,	/* Bit  4:	Gigabit Speed (1 = 1000 Mbps) */
+	GM_GPSR_PART_MODE	= 1<<3,	/* Bit  3:	Partition mode */
+	GM_GPSR_FC_RX_DIS	= 1<<2,	/* Bit  2:	Rx Flow-Control Mode Disabled */
+	GM_GPSR_PROM_EN		= 1<<1,	/* Bit  1:	Promiscuous Mode Enabled */
+};
+
+/*	GM_GP_CTRL	16 bit r/w	General Purpose Control Register */
+enum {
+	GM_GPCR_PROM_ENA	= 1<<14,	/* Bit 14:	Enable Promiscuous Mode */
+	GM_GPCR_FC_TX_DIS	= 1<<13, /* Bit 13:	Disable Tx Flow-Control Mode */
+	GM_GPCR_TX_ENA		= 1<<12, /* Bit 12:	Enable Transmit */
+	GM_GPCR_RX_ENA		= 1<<11, /* Bit 11:	Enable Receive */
+	GM_GPCR_BURST_ENA	= 1<<10, /* Bit 10:	Enable Burst Mode */
+	GM_GPCR_LOOP_ENA	= 1<<9,	/* Bit  9:	Enable MAC Loopback Mode */
+	GM_GPCR_PART_ENA	= 1<<8,	/* Bit  8:	Enable Partition Mode */
+	GM_GPCR_GIGS_ENA	= 1<<7,	/* Bit  7:	Gigabit Speed (1000 Mbps) */
+	GM_GPCR_FL_PASS		= 1<<6,	/* Bit  6:	Force Link Pass */
+	GM_GPCR_DUP_FULL	= 1<<5,	/* Bit  5:	Full Duplex Mode */
+	GM_GPCR_FC_RX_DIS	= 1<<4,	/* Bit  4:	Disable Rx Flow-Control Mode */
+	GM_GPCR_SPEED_100	= 1<<3,   /* Bit  3:	Port Speed 100 Mbps */
+	GM_GPCR_AU_DUP_DIS	= 1<<2,	/* Bit  2:	Disable Auto-Update Duplex */
+	GM_GPCR_AU_FCT_DIS	= 1<<1,	/* Bit  1:	Disable Auto-Update Flow-C. */
+	GM_GPCR_AU_SPD_DIS	= 1<<0,	/* Bit  0:	Disable Auto-Update Speed */
+};
+
+#define GM_GPCR_SPEED_1000	(GM_GPCR_GIGS_ENA | GM_GPCR_SPEED_100)
+#define GM_GPCR_AU_ALL_DIS	(GM_GPCR_AU_DUP_DIS | GM_GPCR_AU_FCT_DIS|GM_GPCR_AU_SPD_DIS)
+
+/*	GM_TX_CTRL			16 bit r/w	Transmit Control Register */
+enum {
+	GM_TXCR_FORCE_JAM	= 1<<15, /* Bit 15:	Force Jam / Flow-Control */
+	GM_TXCR_CRC_DIS		= 1<<14, /* Bit 14:	Disable insertion of CRC */
+	GM_TXCR_PAD_DIS		= 1<<13, /* Bit 13:	Disable padding of packets */
+	GM_TXCR_COL_THR_MSK	= 1<<10, /* Bit 12..10:	Collision Threshold */
+};
+
+#define TX_COL_THR(x)		(((x)<<10) & GM_TXCR_COL_THR_MSK)
+#define TX_COL_DEF		0x04
+
+/*	GM_RX_CTRL			16 bit r/w	Receive Control Register */
+enum {
+	GM_RXCR_UCF_ENA	= 1<<15, /* Bit 15:	Enable Unicast filtering */
+	GM_RXCR_MCF_ENA	= 1<<14, /* Bit 14:	Enable Multicast filtering */
+	GM_RXCR_CRC_DIS	= 1<<13, /* Bit 13:	Remove 4-byte CRC */
+	GM_RXCR_PASS_FC	= 1<<12, /* Bit 12:	Pass FC packets to FIFO */
+};
+
+/*	GM_TX_PARAM		16 bit r/w	Transmit Parameter Register */
+enum {
+	GM_TXPA_JAMLEN_MSK	= 0x03<<14,	/* Bit 15..14:	Jam Length */
+	GM_TXPA_JAMIPG_MSK	= 0x1f<<9,	/* Bit 13..9:	Jam IPG */
+	GM_TXPA_JAMDAT_MSK	= 0x1f<<4,	/* Bit  8..4:	IPG Jam to Data */
+	GM_TXPA_BO_LIM_MSK	= 0x0f,		/* Bit  3.. 0: Backoff Limit Mask */
+
+	TX_JAM_LEN_DEF		= 0x03,
+	TX_JAM_IPG_DEF		= 0x0b,
+	TX_IPG_JAM_DEF		= 0x1c,
+	TX_BOF_LIM_DEF		= 0x04,
+};
+
+#define TX_JAM_LEN_VAL(x)	(((x)<<14) & GM_TXPA_JAMLEN_MSK)
+#define TX_JAM_IPG_VAL(x)	(((x)<<9)  & GM_TXPA_JAMIPG_MSK)
+#define TX_IPG_JAM_DATA(x)	(((x)<<4)  & GM_TXPA_JAMDAT_MSK)
+#define TX_BACK_OFF_LIM(x)	((x) & GM_TXPA_BO_LIM_MSK)
+
+
+/*	GM_SERIAL_MODE			16 bit r/w	Serial Mode Register */
+enum {
+	GM_SMOD_DATABL_MSK	= 0x1f<<11, /* Bit 15..11:	Data Blinder (r/o) */
+	GM_SMOD_LIMIT_4		= 1<<10, /* Bit 10:	4 consecutive Tx trials */
+	GM_SMOD_VLAN_ENA	= 1<<9,	/* Bit  9:	Enable VLAN  (Max. Frame Len) */
+	GM_SMOD_JUMBO_ENA	= 1<<8,	/* Bit  8:	Enable Jumbo (Max. Frame Len) */
+	 GM_SMOD_IPG_MSK	= 0x1f	/* Bit 4..0:	Inter-Packet Gap (IPG) */
+};
+
+#define DATA_BLIND_VAL(x)	(((x)<<11) & GM_SMOD_DATABL_MSK)
+#define DATA_BLIND_DEF		0x04
+
+#define IPG_DATA_VAL(x)		(x & GM_SMOD_IPG_MSK)
+#define IPG_DATA_DEF		0x1e
+
+/*	GM_SMI_CTRL			16 bit r/w	SMI Control Register */
+enum {
+	GM_SMI_CT_PHY_A_MSK	= 0x1f<<11,/* Bit 15..11:	PHY Device Address */
+	GM_SMI_CT_REG_A_MSK	= 0x1f<<6,/* Bit 10.. 6:	PHY Register Address */
+	GM_SMI_CT_OP_RD		= 1<<5,	/* Bit  5:	OpCode Read (0=Write)*/
+	GM_SMI_CT_RD_VAL	= 1<<4,	/* Bit  4:	Read Valid (Read completed) */
+	GM_SMI_CT_BUSY		= 1<<3,	/* Bit  3:	Busy (Operation in progress) */
+};
+
+#define GM_SMI_CT_PHY_AD(x)	(((x)<<11) & GM_SMI_CT_PHY_A_MSK)
+#define GM_SMI_CT_REG_AD(x)	(((x)<<6) & GM_SMI_CT_REG_A_MSK)
+
+/*	GM_PHY_ADDR				16 bit r/w	GPHY Address Register */
+enum {
+	GM_PAR_MIB_CLR	= 1<<5,	/* Bit  5:	Set MIB Clear Counter Mode */
+	GM_PAR_MIB_TST	= 1<<4,	/* Bit  4:	MIB Load Counter (Test Mode) */
+};
+
+/* Receive Frame Status Encoding */
+enum {
+	GMR_FS_LEN	= 0xffff<<16, /* Bit 31..16:	Rx Frame Length */
+	GMR_FS_VLAN	= 1<<13, /* VLAN Packet */
+	GMR_FS_JABBER	= 1<<12, /* Jabber Packet */
+	GMR_FS_UN_SIZE	= 1<<11, /* Undersize Packet */
+	GMR_FS_MC	= 1<<10, /* Multicast Packet */
+	GMR_FS_BC	= 1<<9,  /* Broadcast Packet */
+	GMR_FS_RX_OK	= 1<<8,  /* Receive OK (Good Packet) */
+	GMR_FS_GOOD_FC	= 1<<7,  /* Good Flow-Control Packet */
+	GMR_FS_BAD_FC	= 1<<6,  /* Bad  Flow-Control Packet */
+	GMR_FS_MII_ERR	= 1<<5,  /* MII Error */
+	GMR_FS_LONG_ERR	= 1<<4,  /* Too Long Packet */
+	GMR_FS_FRAGMENT	= 1<<3,  /* Fragment */
+
+	GMR_FS_CRC_ERR	= 1<<1,  /* CRC Error */
+	GMR_FS_RX_FF_OV	= 1<<0,  /* Rx FIFO Overflow */
+
+	GMR_FS_ANY_ERR	= GMR_FS_RX_FF_OV | GMR_FS_CRC_ERR |
+			  GMR_FS_FRAGMENT | GMR_FS_LONG_ERR |
+		  	  GMR_FS_MII_ERR | GMR_FS_BAD_FC | GMR_FS_GOOD_FC |
+			  GMR_FS_UN_SIZE | GMR_FS_JABBER,
+};
+
+/*	RX_GMF_CTRL_T	32 bit	Rx GMAC FIFO Control/Test */
+enum {
+	RX_TRUNC_ON	= 1<<27,  	/* enable  packet truncation */
+	RX_TRUNC_OFF	= 1<<26, 	/* disable packet truncation */
+	RX_VLAN_STRIP_ON = 1<<25,	/* enable  VLAN stripping */
+	RX_VLAN_STRIP_OFF = 1<<24,	/* disable VLAN stripping */
+
+	GMF_WP_TST_ON	= 1<<14,	/* Write Pointer Test On */
+	GMF_WP_TST_OFF	= 1<<13,	/* Write Pointer Test Off */
+	GMF_WP_STEP	= 1<<12,	/* Write Pointer Step/Increment */
+
+	GMF_RP_TST_ON	= 1<<10,	/* Read Pointer Test On */
+	GMF_RP_TST_OFF	= 1<<9,		/* Read Pointer Test Off */
+	GMF_RP_STEP	= 1<<8,		/* Read Pointer Step/Increment */
+	GMF_RX_F_FL_ON	= 1<<7,		/* Rx FIFO Flush Mode On */
+	GMF_RX_F_FL_OFF	= 1<<6,		/* Rx FIFO Flush Mode Off */
+	GMF_CLI_RX_FO	= 1<<5,		/* Clear IRQ Rx FIFO Overrun */
+	GMF_CLI_RX_C	= 1<<4,		/* Clear IRQ Rx Frame Complete */
+
+	GMF_OPER_ON	= 1<<3,		/* Operational Mode On */
+	GMF_OPER_OFF	= 1<<2,		/* Operational Mode Off */
+	GMF_RST_CLR	= 1<<1,		/* Clear GMAC FIFO Reset */
+	GMF_RST_SET	= 1<<0,		/* Set   GMAC FIFO Reset */
+
+	RX_GMF_FL_THR_DEF = 0xa,	/* flush threshold (default) */
+
+	GMF_RX_CTRL_DEF	= GMF_OPER_ON | GMF_RX_F_FL_ON,
+};
+
+
+/*	TX_GMF_CTRL_T	32 bit	Tx GMAC FIFO Control/Test */
+enum {
+	TX_STFW_DIS	= 1<<31,/* Disable Store & Forward (Yukon-EC Ultra) */
+	TX_STFW_ENA	= 1<<30,/* Enable  Store & Forward (Yukon-EC Ultra) */
+
+	TX_VLAN_TAG_ON	= 1<<25,/* enable  VLAN tagging */
+	TX_VLAN_TAG_OFF	= 1<<24,/* disable VLAN tagging */
+
+	GMF_WSP_TST_ON	= 1<<18,/* Write Shadow Pointer Test On */
+	GMF_WSP_TST_OFF	= 1<<17,/* Write Shadow Pointer Test Off */
+	GMF_WSP_STEP	= 1<<16,/* Write Shadow Pointer Step/Increment */
+
+	GMF_CLI_TX_FU	= 1<<6,	/* Clear IRQ Tx FIFO Underrun */
+	GMF_CLI_TX_FC	= 1<<5,	/* Clear IRQ Tx Frame Complete */
+	GMF_CLI_TX_PE	= 1<<4,	/* Clear IRQ Tx Parity Error */
+};
+
+/*	GMAC_TI_ST_CTRL	 8 bit	Time Stamp Timer Ctrl Reg (YUKON only) */
+enum {
+	GMT_ST_START	= 1<<2,	/* Start Time Stamp Timer */
+	GMT_ST_STOP	= 1<<1,	/* Stop  Time Stamp Timer */
+	GMT_ST_CLR_IRQ	= 1<<0,	/* Clear Time Stamp Timer IRQ */
+};
+
+/* B28_Y2_ASF_STAT_CMD		32 bit	ASF Status and Command Reg */
+enum {
+	Y2_ASF_OS_PRES	= 1<<4,	/* ASF operation system present */
+	Y2_ASF_RESET	= 1<<3,	/* ASF system in reset state */
+	Y2_ASF_RUNNING	= 1<<2,	/* ASF system operational */
+	Y2_ASF_CLR_HSTI = 1<<1,	/* Clear ASF IRQ */
+	Y2_ASF_IRQ	= 1<<0,	/* Issue an IRQ to ASF system */
+
+	Y2_ASF_UC_STATE = 3<<2,	/* ASF uC State */
+	Y2_ASF_CLK_HALT	= 0,	/* ASF system clock stopped */
+};
+
+/* B28_Y2_ASF_HOST_COM	32 bit	ASF Host Communication Reg */
+enum {
+	Y2_ASF_CLR_ASFI = 1<<1,	/* Clear host IRQ */
+	Y2_ASF_HOST_IRQ = 1<<0,	/* Issue an IRQ to HOST system */
+};
+
+/*	STAT_CTRL		32 bit	Status BMU control register (Yukon-2 only) */
+enum {
+	SC_STAT_CLR_IRQ	= 1<<4,	/* Status Burst IRQ clear */
+	SC_STAT_OP_ON	= 1<<3,	/* Operational Mode On */
+	SC_STAT_OP_OFF	= 1<<2,	/* Operational Mode Off */
+	SC_STAT_RST_CLR	= 1<<1,	/* Clear Status Unit Reset (Enable) */
+	SC_STAT_RST_SET	= 1<<0,	/* Set   Status Unit Reset */
+};
+
+/*	GMAC_CTRL		32 bit	GMAC Control Reg (YUKON only) */
+enum {
+	GMC_H_BURST_ON	= 1<<7,	/* Half Duplex Burst Mode On */
+	GMC_H_BURST_OFF	= 1<<6,	/* Half Duplex Burst Mode Off */
+	GMC_F_LOOPB_ON	= 1<<5,	/* FIFO Loopback On */
+	GMC_F_LOOPB_OFF	= 1<<4,	/* FIFO Loopback Off */
+	GMC_PAUSE_ON	= 1<<3,	/* Pause On */
+	GMC_PAUSE_OFF	= 1<<2,	/* Pause Off */
+	GMC_RST_CLR	= 1<<1,	/* Clear GMAC Reset */
+	GMC_RST_SET	= 1<<0,	/* Set   GMAC Reset */
+};
+
+/*	GPHY_CTRL		32 bit	GPHY Control Reg (YUKON only) */
+enum {
+	GPC_SEL_BDT	= 1<<28, /* Select Bi-Dir. Transfer for MDC/MDIO */
+	GPC_INT_POL_HI	= 1<<27, /* IRQ Polarity is Active HIGH */
+	GPC_75_OHM	= 1<<26, /* Use 75 Ohm Termination instead of 50 */
+	GPC_DIS_FC	= 1<<25, /* Disable Automatic Fiber/Copper Detection */
+	GPC_DIS_SLEEP	= 1<<24, /* Disable Energy Detect */
+	GPC_HWCFG_M_3	= 1<<23, /* HWCFG_MODE[3] */
+	GPC_HWCFG_M_2	= 1<<22, /* HWCFG_MODE[2] */
+	GPC_HWCFG_M_1	= 1<<21, /* HWCFG_MODE[1] */
+	GPC_HWCFG_M_0	= 1<<20, /* HWCFG_MODE[0] */
+	GPC_ANEG_0	= 1<<19, /* ANEG[0] */
+	GPC_ENA_XC	= 1<<18, /* Enable MDI crossover */
+	GPC_DIS_125	= 1<<17, /* Disable 125 MHz clock */
+	GPC_ANEG_3	= 1<<16, /* ANEG[3] */
+	GPC_ANEG_2	= 1<<15, /* ANEG[2] */
+	GPC_ANEG_1	= 1<<14, /* ANEG[1] */
+	GPC_ENA_PAUSE	= 1<<13, /* Enable Pause (SYM_OR_REM) */
+	GPC_PHYADDR_4	= 1<<12, /* Bit 4 of Phy Addr */
+	GPC_PHYADDR_3	= 1<<11, /* Bit 3 of Phy Addr */
+	GPC_PHYADDR_2	= 1<<10, /* Bit 2 of Phy Addr */
+	GPC_PHYADDR_1	= 1<<9,	 /* Bit 1 of Phy Addr */
+	GPC_PHYADDR_0	= 1<<8,	 /* Bit 0 of Phy Addr */
+						/* Bits  7..2:	reserved */
+	GPC_RST_CLR	= 1<<1,	/* Clear GPHY Reset */
+	GPC_RST_SET	= 1<<0,	/* Set   GPHY Reset */
+};
+
+/*	GMAC_IRQ_SRC	 8 bit	GMAC Interrupt Source Reg (YUKON only) */
+/*	GMAC_IRQ_MSK	 8 bit	GMAC Interrupt Mask   Reg (YUKON only) */
+enum {
+	GM_IS_TX_CO_OV	= 1<<5,	/* Transmit Counter Overflow IRQ */
+	GM_IS_RX_CO_OV	= 1<<4,	/* Receive Counter Overflow IRQ */
+	GM_IS_TX_FF_UR	= 1<<3,	/* Transmit FIFO Underrun */
+	GM_IS_TX_COMPL	= 1<<2,	/* Frame Transmission Complete */
+	GM_IS_RX_FF_OR	= 1<<1,	/* Receive FIFO Overrun */
+	GM_IS_RX_COMPL	= 1<<0,	/* Frame Reception Complete */
+
+#define GMAC_DEF_MSK     GM_IS_TX_FF_UR
+
+/*	GMAC_LINK_CTRL	16 bit	GMAC Link Control Reg (YUKON only) */
+						/* Bits 15.. 2:	reserved */
+	GMLC_RST_CLR	= 1<<1,	/* Clear GMAC Link Reset */
+	GMLC_RST_SET	= 1<<0,	/* Set   GMAC Link Reset */
+
+
+/*	WOL_CTRL_STAT	16 bit	WOL Control/Status Reg */
+	WOL_CTL_LINK_CHG_OCC		= 1<<15,
+	WOL_CTL_MAGIC_PKT_OCC		= 1<<14,
+	WOL_CTL_PATTERN_OCC		= 1<<13,
+	WOL_CTL_CLEAR_RESULT		= 1<<12,
+	WOL_CTL_ENA_PME_ON_LINK_CHG	= 1<<11,
+	WOL_CTL_DIS_PME_ON_LINK_CHG	= 1<<10,
+	WOL_CTL_ENA_PME_ON_MAGIC_PKT	= 1<<9,
+	WOL_CTL_DIS_PME_ON_MAGIC_PKT	= 1<<8,
+	WOL_CTL_ENA_PME_ON_PATTERN	= 1<<7,
+	WOL_CTL_DIS_PME_ON_PATTERN	= 1<<6,
+	WOL_CTL_ENA_LINK_CHG_UNIT	= 1<<5,
+	WOL_CTL_DIS_LINK_CHG_UNIT	= 1<<4,
+	WOL_CTL_ENA_MAGIC_PKT_UNIT	= 1<<3,
+	WOL_CTL_DIS_MAGIC_PKT_UNIT	= 1<<2,
+	WOL_CTL_ENA_PATTERN_UNIT	= 1<<1,
+	WOL_CTL_DIS_PATTERN_UNIT	= 1<<0,
+};
+
+#define WOL_CTL_DEFAULT				\
+	(WOL_CTL_DIS_PME_ON_LINK_CHG |	\
+	WOL_CTL_DIS_PME_ON_PATTERN |	\
+	WOL_CTL_DIS_PME_ON_MAGIC_PKT |	\
+	WOL_CTL_DIS_LINK_CHG_UNIT |		\
+	WOL_CTL_DIS_PATTERN_UNIT |		\
+	WOL_CTL_DIS_MAGIC_PKT_UNIT)
+
+/*	WOL_MATCH_CTL	 8 bit	WOL Match Control Reg */
+#define WOL_CTL_PATT_ENA(x)	(1 << (x))
+
+
+/* Control flags */
+enum {
+	UDPTCP	= 1<<0,
+	CALSUM	= 1<<1,
+	WR_SUM	= 1<<2,
+	INIT_SUM= 1<<3,
+	LOCK_SUM= 1<<4,
+	INS_VLAN= 1<<5,
+	FRC_STAT= 1<<6,
+	EOP	= 1<<7,
+};
+
+enum {
+	HW_OWNER 	= 1<<7,
+	OP_TCPWRITE	= 0x11,
+	OP_TCPSTART	= 0x12,
+	OP_TCPINIT	= 0x14,
+	OP_TCPLCK	= 0x18,
+	OP_TCPCHKSUM	= OP_TCPSTART,
+	OP_TCPIS	= OP_TCPINIT | OP_TCPSTART,
+	OP_TCPLW	= OP_TCPLCK | OP_TCPWRITE,
+	OP_TCPLSW	= OP_TCPLCK | OP_TCPSTART | OP_TCPWRITE,
+	OP_TCPLISW	= OP_TCPLCK | OP_TCPINIT | OP_TCPSTART | OP_TCPWRITE,
+
+	OP_ADDR64	= 0x21,
+	OP_VLAN		= 0x22,
+	OP_ADDR64VLAN	= OP_ADDR64 | OP_VLAN,
+	OP_LRGLEN	= 0x24,
+	OP_LRGLENVLAN	= OP_LRGLEN | OP_VLAN,
+	OP_BUFFER	= 0x40,
+	OP_PACKET	= 0x41,
+	OP_LARGESEND	= 0x43,
+
+/* YUKON-2 STATUS opcodes defines */
+	OP_RXSTAT	= 0x60,
+	OP_RXTIMESTAMP	= 0x61,
+	OP_RXVLAN	= 0x62,
+	OP_RXCHKS	= 0x64,
+	OP_RXCHKSVLAN	= OP_RXCHKS | OP_RXVLAN,
+	OP_RXTIMEVLAN	= OP_RXTIMESTAMP | OP_RXVLAN,
+	OP_RSS_HASH	= 0x65,
+	OP_TXINDEXLE	= 0x68,
+};
+
+/* Yukon 2 hardware interface
+ * Not tested on big endian
+ */
+struct sky2_tx_le {
+	union {
+		__le32	addr;
+		struct {
+			__le16	offset;
+			__le16	start;
+		} csum  __attribute((packed));
+		struct {
+			__le16	size;
+			__le16	rsvd;
+		} tso  __attribute((packed));
+	} tx;
+	__le16	length;	/* also vlan tag or checksum start */
+	u8	ctrl;
+	u8	opcode;
+} __attribute((packed));
+
+struct sky2_rx_le {
+	__le32	addr;
+	__le16	length;
+	u8	ctrl;
+	u8	opcode;
+} __attribute((packed));;
+
+struct sky2_status_le {
+	__le32	status;	/* also checksum */
+	__le16	length;	/* also vlan tag */
+	u8	link;
+	u8	opcode;
+} __attribute((packed));
+
+struct tx_ring_info {
+	struct sk_buff	*skb;
+	DECLARE_PCI_UNMAP_ADDR(mapaddr);
+	u16		idx;
+};
+
+struct ring_info {
+	struct sk_buff	*skb;
+	dma_addr_t	mapaddr;
+};
+
+struct sky2_port {
+	struct sky2_hw	     *hw;
+	struct net_device    *netdev;
+	unsigned	     port;
+	u32		     msg_enable;
+
+	spinlock_t	     tx_lock  ____cacheline_aligned_in_smp;
+	struct tx_ring_info  *tx_ring;
+	struct sky2_tx_le    *tx_le;
+	u16		     tx_cons;		/* next le to check */
+	u16		     tx_prod;		/* next le to use */
+	u32		     tx_addr64;
+	u16		     tx_pending;
+	u16		     tx_last_put;
+	u16		     tx_last_mss;
+
+	struct ring_info     *rx_ring ____cacheline_aligned_in_smp;
+	struct sky2_rx_le    *rx_le;
+	u32		     rx_addr64;
+	u16		     rx_next;		/* next re to check */
+	u16		     rx_put;		/* next le index to use */
+	u16		     rx_pending;
+	u16		     rx_last_put;
+	u16		     rx_bufsize;
+#ifdef SKY2_VLAN_TAG_USED
+	u16		     rx_tag;
+	struct vlan_group    *vlgrp;
+#endif
+
+	dma_addr_t	     rx_le_map;
+	dma_addr_t	     tx_le_map;
+	u32		     advertising;	/* ADVERTISED_ bits */
+	u16		     speed;	/* SPEED_1000, SPEED_100, ... */
+	u8		     autoneg;	/* AUTONEG_ENABLE, AUTONEG_DISABLE */
+	u8		     duplex;	/* DUPLEX_HALF, DUPLEX_FULL */
+	u8		     rx_pause;
+	u8		     tx_pause;
+	u8		     rx_csum;
+	u8		     wol;
+
+	struct net_device_stats net_stats;
+
+	struct work_struct   phy_task;
+	struct semaphore     phy_sema;
+};
+
+struct sky2_hw {
+	void __iomem  	     *regs;
+	struct pci_dev	     *pdev;
+	u32		     intr_mask;
+	struct net_device    *dev[2];
+
+	int		     pm_cap;
+	u8	     	     chip_id;
+	u8		     chip_rev;
+	u8		     copper;
+	u8		     ports;
+
+	struct sky2_status_le *st_le;
+	u32		     st_idx;
+	dma_addr_t   	     st_dma;
+};
+
+/* Register accessor for memory mapped device */
+static inline u32 sky2_read32(const struct sky2_hw *hw, unsigned reg)
+{
+	return readl(hw->regs + reg);
+}
+
+static inline u16 sky2_read16(const struct sky2_hw *hw, unsigned reg)
+{
+	return readw(hw->regs + reg);
+}
+
+static inline u8 sky2_read8(const struct sky2_hw *hw, unsigned reg)
+{
+	return readb(hw->regs + reg);
+}
+
+/* This should probably go away, bus based tweeks suck */
+static inline int is_pciex(const struct sky2_hw *hw)
+{
+	u32 status;
+	pci_read_config_dword(hw->pdev, PCI_DEV_STATUS, &status);
+	return (status & PCI_OS_PCI_X) == 0;
+}
+
+static inline void sky2_write32(const struct sky2_hw *hw, unsigned reg, u32 val)
+{
+	writel(val, hw->regs + reg);
+}
+
+static inline void sky2_write16(const struct sky2_hw *hw, unsigned reg, u16 val)
+{
+	writew(val, hw->regs + reg);
+}
+
+static inline void sky2_write8(const struct sky2_hw *hw, unsigned reg, u8 val)
+{
+	writeb(val, hw->regs + reg);
+}
+
+/* Yukon PHY related registers */
+#define SK_GMAC_REG(port,reg) \
+	(BASE_GMAC_1 + (port) * (BASE_GMAC_2-BASE_GMAC_1) + (reg))
+#define GM_PHY_RETRIES	100
+
+static inline u16 gma_read16(const struct sky2_hw *hw, unsigned port, unsigned reg)
+{
+	return sky2_read16(hw, SK_GMAC_REG(port,reg));
+}
+
+static inline u32 gma_read32(struct sky2_hw *hw, unsigned port, unsigned reg)
+{
+	unsigned base = SK_GMAC_REG(port, reg);
+	return (u32) sky2_read16(hw, base)
+		| (u32) sky2_read16(hw, base+4) << 16;
+}
+
+static inline void gma_write16(const struct sky2_hw *hw, unsigned port, int r, u16 v)
+{
+	sky2_write16(hw, SK_GMAC_REG(port,r), v);
+}
+
+static inline void gma_set_addr(struct sky2_hw *hw, unsigned port, unsigned reg,
+				    const u8 *addr)
+{
+	gma_write16(hw, port, reg,  (u16) addr[0] | ((u16) addr[1] << 8));
+	gma_write16(hw, port, reg+4,(u16) addr[2] | ((u16) addr[3] << 8));
+	gma_write16(hw, port, reg+8,(u16) addr[4] | ((u16) addr[5] << 8));
+}
+#endif
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 2fc9893d69e1..eb86b059809b 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -24,6 +24,7 @@
 #include <linux/compiler.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
+#include <linux/in.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/pci.h>
@@ -3650,7 +3651,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
 			       TXD_FLAG_CPU_POST_DMA);
 
 		skb->nh.iph->check = 0;
-		skb->nh.iph->tot_len = ntohs(mss + ip_tcp_len + tcp_opt_len);
+		skb->nh.iph->tot_len = htons(mss + ip_tcp_len + tcp_opt_len);
 		if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) {
 			skb->h.th->check = 0;
 			base_flags &= ~TXD_FLAG_TCPUDP_CSUM;
diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c
index 942fae0f2130..c2506b56a186 100644
--- a/drivers/net/tlan.c
+++ b/drivers/net/tlan.c
@@ -2865,11 +2865,11 @@ void TLan_PhyMonitor( struct net_device *dev )
 	 *				for this device.
 	 *		phy		The address of the PHY to be queried.
 	 *		reg		The register whose contents are to be
-	 *				retreived.
+	 *				retrieved.
 	 *		val		A pointer to a variable to store the
 	 *				retrieved value.
 	 *
-	 *	This function uses the TLAN's MII bus to retreive the contents
+	 *	This function uses the TLAN's MII bus to retrieve the contents
 	 *	of a given register on a PHY.  It sends the appropriate info
 	 *	and then reads the 16-bit register value from the MII bus via
 	 *	the TLAN SIO register.
diff --git a/drivers/net/wan/.gitignore b/drivers/net/wan/.gitignore
new file mode 100644
index 000000000000..dae3ea6bb18c
--- /dev/null
+++ b/drivers/net/wan/.gitignore
@@ -0,0 +1 @@
+wanxlfw.inc
diff --git a/drivers/net/wan/lmc/lmc_prot.h b/drivers/net/wan/lmc/lmc_prot.h
deleted file mode 100644
index f3b1df9e2cdb..000000000000
--- a/drivers/net/wan/lmc/lmc_prot.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef _LMC_PROTO_H_
-#define _LMC_PROTO_H_
-
-void lmc_proto_init(lmc_softc_t * const)
-void lmc_proto_attach(lmc_softc_t *sc const)
-void lmc_proto_detach(lmc_softc *sc const)
-void lmc_proto_reopen(lmc_softc_t *sc const)
-int lmc_proto_ioctl(lmc_softc_t *sc const, struct ifreq *ifr, int cmd)
-void lmc_proto_open(lmc_softc_t *sc const)
-void lmc_proto_close(lmc_softc_t *sc const)
-unsigned short lmc_proto_type(lmc_softc_t *sc const, struct skbuff *skb)
-
-
-#endif
-
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 00e55165b760..24f7967aab67 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -173,7 +173,7 @@ config IPW2100_MONITOR
 	  promiscuous mode via the Wireless Tool's Monitor mode.  While in this
 	  mode, no packets can be sent.
 
-config IPW_DEBUG
+config IPW2100_DEBUG
 	bool "Enable full debugging output in IPW2100 module."
 	depends on IPW2100
 	---help---
@@ -192,7 +192,7 @@ config IPW_DEBUG
 
 config IPW2200
 	tristate "Intel PRO/Wireless 2200BG and 2915ABG Network Connection"
-	depends on IEEE80211 && PCI
+	depends on NET_RADIO && IEEE80211 && PCI
 	select FW_LOADER
 	---help---
           A driver for the Intel PRO/Wireless 2200BG and 2915ABG Network
@@ -217,7 +217,7 @@ config IPW2200
           say M here and read <file:Documentation/modules.txt>.  The module
           will be called ipw2200.ko.
 
-config IPW_DEBUG
+config IPW2200_DEBUG
 	bool "Enable full debugging output in IPW2200 module."
 	depends on IPW2200
 	---help---
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 7a92b1cbd6aa..ee866fd6957d 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -4037,7 +4037,7 @@ static int PC4500_writerid(struct airo_info *ai, u16 rid,
 		Cmd cmd;
 		Resp rsp;
 
-		if (test_bit(FLAG_ENABLED, &ai->flags))
+		if (test_bit(FLAG_ENABLED, &ai->flags) && (RID_WEP_TEMP != rid))
 			printk(KERN_ERR
 				"%s: MAC should be disabled (rid=%04x)\n",
 				__FUNCTION__, rid);
@@ -5093,9 +5093,9 @@ static int set_wep_key(struct airo_info *ai, u16 index,
 		printk(KERN_INFO "Setting key %d\n", index);
 	}
 
-	disable_MAC(ai, lock);
+	if (perm) disable_MAC(ai, lock);
 	writeWepKeyRid(ai, &wkr, perm, lock);
-	enable_MAC(ai, &rsp, lock);
+	if (perm) enable_MAC(ai, &rsp, lock);
 	return 0;
 }
 
@@ -6170,6 +6170,8 @@ static int airo_set_encode(struct net_device *dev,
 {
 	struct airo_info *local = dev->priv;
 	CapabilityRid cap_rid;		/* Card capability info */
+	int perm = ( dwrq->flags & IW_ENCODE_TEMP ? 0 : 1 );
+	u16 currentAuthType = local->config.authType;
 
 	/* Is WEP supported ? */
 	readCapabilityRid(local, &cap_rid, 1);
@@ -6212,7 +6214,7 @@ static int airo_set_encode(struct net_device *dev,
 			/* Copy the key in the driver */
 			memcpy(key.key, extra, dwrq->length);
 			/* Send the key to the card */
-			set_wep_key(local, index, key.key, key.len, 1, 1);
+			set_wep_key(local, index, key.key, key.len, perm, 1);
 		}
 		/* WE specify that if a valid key is set, encryption
 		 * should be enabled (user may turn it off later)
@@ -6220,13 +6222,12 @@ static int airo_set_encode(struct net_device *dev,
 		if((index == current_index) && (key.len > 0) &&
 		   (local->config.authType == AUTH_OPEN)) {
 			local->config.authType = AUTH_ENCRYPT;
-			set_bit (FLAG_COMMIT, &local->flags);
 		}
 	} else {
 		/* Do we want to just set the transmit key index ? */
 		int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
 		if ((index >= 0) && (index < ((cap_rid.softCap & 0x80)?4:1))) {
-			set_wep_key(local, index, NULL, 0, 1, 1);
+			set_wep_key(local, index, NULL, 0, perm, 1);
 		} else
 			/* Don't complain if only change the mode */
 			if(!dwrq->flags & IW_ENCODE_MODE) {
@@ -6241,7 +6242,7 @@ static int airo_set_encode(struct net_device *dev,
 	if(dwrq->flags & IW_ENCODE_OPEN)
 		local->config.authType = AUTH_ENCRYPT;	// Only Wep
 	/* Commit the changes to flags if needed */
-	if(dwrq->flags & IW_ENCODE_MODE)
+	if (local->config.authType != currentAuthType)
 		set_bit (FLAG_COMMIT, &local->flags);
 	return -EINPROGRESS;		/* Call commit handler */
 }
diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c
index e328547599dc..a496460ce224 100644
--- a/drivers/net/wireless/airo_cs.c
+++ b/drivers/net/wireless/airo_cs.c
@@ -82,8 +82,6 @@ MODULE_SUPPORTED_DEVICE("Aironet 4500, 4800 and Cisco 340 PCMCIA cards");
 
 static void airo_config(dev_link_t *link);
 static void airo_release(dev_link_t *link);
-static int airo_event(event_t event, int priority,
-		       event_callback_args_t *args);
 
 /*
    The attach() and detach() entry points are used to create and destroy
@@ -91,8 +89,7 @@ static int airo_event(event_t event, int priority,
    needed to manage one actual PCMCIA card.
 */
 
-static dev_link_t *airo_attach(void);
-static void airo_detach(dev_link_t *);
+static void airo_detach(struct pcmcia_device *p_dev);
 
 /*
    You'll also need to prototype all the functions that will actually
@@ -102,14 +99,6 @@ static void airo_detach(dev_link_t *);
 */
 
 /*
-   The dev_info variable is the "key" that is used to match up this
-   device driver with appropriate cards, through the card configuration
-   database.
-*/
-
-static dev_info_t dev_info = "airo_cs";
-
-/*
    A linked list of "instances" of the  aironet device.  Each actual
    PCMCIA card corresponds to one device instance, and is described
    by one dev_link_t structure (defined in ds.h).
@@ -119,15 +108,7 @@ static dev_info_t dev_info = "airo_cs";
    device numbers are used to derive the corresponding array index.
 */
 
-static dev_link_t *dev_list = NULL;
-
 /*
-   A dev_link_t structure has fields for most things that are needed
-   to keep track of a socket, but there will usually be some device
-   specific information that also needs to be kept track of.  The
-   'priv' pointer in a dev_link_t structure can be used to point to
-   a device-specific private data structure, like this.
-
    A driver needs to provide a dev_node_t structure for each device
    on a card.  In some cases, there is only one device per card (for
    example, ethernet cards, modems).  In other cases, there may be
@@ -160,20 +141,18 @@ typedef struct local_info_t {
   
   ======================================================================*/
 
-static dev_link_t *airo_attach(void)
+static int airo_attach(struct pcmcia_device *p_dev)
 {
-	client_reg_t client_reg;
 	dev_link_t *link;
 	local_info_t *local;
-	int ret;
-	
+
 	DEBUG(0, "airo_attach()\n");
 
 	/* Initialize the dev_link_t structure */
 	link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL);
 	if (!link) {
 		printk(KERN_ERR "airo_cs: no memory for new device\n");
-		return NULL;
+		return -ENOMEM;
 	}
 	
 	/* Interrupt setup */
@@ -197,24 +176,17 @@ static dev_link_t *airo_attach(void)
 	if (!local) {
 		printk(KERN_ERR "airo_cs: no memory for new device\n");
 		kfree (link);
-		return NULL;
+		return -ENOMEM;
 	}
 	link->priv = local;
-	
-	/* Register with Card Services */
-	link->next = dev_list;
-	dev_list = link;
-	client_reg.dev_info = &dev_info;
-	client_reg.Version = 0x0210;
-	client_reg.event_callback_args.client_data = link;
-	ret = pcmcia_register_client(&link->handle, &client_reg);
-	if (ret != 0) {
-		cs_error(link->handle, RegisterClient, ret);
-		airo_detach(link);
-		return NULL;
-	}
-	
-	return link;
+
+	link->handle = p_dev;
+	p_dev->instance = link;
+
+	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+	airo_config(link);
+
+	return 0;
 } /* airo_attach */
 
 /*======================================================================
@@ -226,37 +198,22 @@ static dev_link_t *airo_attach(void)
   
   ======================================================================*/
 
-static void airo_detach(dev_link_t *link)
+static void airo_detach(struct pcmcia_device *p_dev)
 {
-	dev_link_t **linkp;
-	
+	dev_link_t *link = dev_to_instance(p_dev);
+
 	DEBUG(0, "airo_detach(0x%p)\n", link);
-	
-	/* Locate device structure */
-	for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
-		if (*linkp == link) break;
-	if (*linkp == NULL)
-		return;
-	
+
 	if (link->state & DEV_CONFIG)
 		airo_release(link);
-	
+
 	if ( ((local_info_t*)link->priv)->eth_dev ) {
 		stop_airo_card( ((local_info_t*)link->priv)->eth_dev, 0 );
 	}
-	((local_info_t*)link->priv)->eth_dev = NULL;   
-	
-	/* Break the link with Card Services */
-	if (link->handle)
-		pcmcia_deregister_client(link->handle);
-	
-	
-	
-	/* Unlink device structure, free pieces */
-	*linkp = link->next;
+	((local_info_t*)link->priv)->eth_dev = NULL;
+
 	kfree(link->priv);
 	kfree(link);
-	
 } /* airo_detach */
 
 /*======================================================================
@@ -492,60 +449,34 @@ static void airo_release(dev_link_t *link)
 	link->state &= ~DEV_CONFIG;
 }
 
-/*======================================================================
-  
-  The card status event handler.  Mostly, this schedules other
-  stuff to run after an event is received.
+static int airo_suspend(struct pcmcia_device *p_dev)
+{
+	dev_link_t *link = dev_to_instance(p_dev);
+	local_info_t *local = link->priv;
 
-  When a CARD_REMOVAL event is received, we immediately set a
-  private flag to block future accesses to this device.  All the
-  functions that actually access the device should check this flag
-  to make sure the card is still present.
-  
-  ======================================================================*/
+	link->state |= DEV_SUSPEND;
+	if (link->state & DEV_CONFIG) {
+		netif_device_detach(local->eth_dev);
+		pcmcia_release_configuration(link->handle);
+	}
+
+	return 0;
+}
 
-static int airo_event(event_t event, int priority,
-		      event_callback_args_t *args)
+static int airo_resume(struct pcmcia_device *p_dev)
 {
-	dev_link_t *link = args->client_data;
+	dev_link_t *link = dev_to_instance(p_dev);
 	local_info_t *local = link->priv;
-	
-	DEBUG(1, "airo_event(0x%06x)\n", event);
-	
-	switch (event) {
-	case CS_EVENT_CARD_REMOVAL:
-		link->state &= ~DEV_PRESENT;
-		if (link->state & DEV_CONFIG) {
-			netif_device_detach(local->eth_dev);
-			airo_release(link);
-		}
-		break;
-	case CS_EVENT_CARD_INSERTION:
-		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-		airo_config(link);
-		break;
-	case CS_EVENT_PM_SUSPEND:
-		link->state |= DEV_SUSPEND;
-		/* Fall through... */
-	case CS_EVENT_RESET_PHYSICAL:
-		if (link->state & DEV_CONFIG) {
-			netif_device_detach(local->eth_dev);
-			pcmcia_release_configuration(link->handle);
-		}
-		break;
-	case CS_EVENT_PM_RESUME:
-		link->state &= ~DEV_SUSPEND;
-		/* Fall through... */
-	case CS_EVENT_CARD_RESET:
-		if (link->state & DEV_CONFIG) {
-			pcmcia_request_configuration(link->handle, &link->conf);
-			reset_airo_card(local->eth_dev);
-			netif_device_attach(local->eth_dev);
-		}
-		break;
+
+	link->state &= ~DEV_SUSPEND;
+	if (link->state & DEV_CONFIG) {
+		pcmcia_request_configuration(link->handle, &link->conf);
+		reset_airo_card(local->eth_dev);
+		netif_device_attach(local->eth_dev);
 	}
+
 	return 0;
-} /* airo_event */
+}
 
 static struct pcmcia_device_id airo_ids[] = {
 	PCMCIA_DEVICE_MANF_CARD(0x015f, 0x000a),
@@ -561,10 +492,11 @@ static struct pcmcia_driver airo_driver = {
 	.drv		= {
 		.name	= "airo_cs",
 	},
-	.attach		= airo_attach,
-	.event		= airo_event,
-	.detach		= airo_detach,
+	.probe		= airo_attach,
+	.remove		= airo_detach,
 	.id_table       = airo_ids,
+	.suspend	= airo_suspend,
+	.resume		= airo_resume,
 };
 
 static int airo_cs_init(void)
@@ -575,7 +507,6 @@ static int airo_cs_init(void)
 static void airo_cs_cleanup(void)
 {
 	pcmcia_unregister_driver(&airo_driver);
-	BUG_ON(dev_list != NULL);
 }
 
 /*
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c
index 5e53c5258a33..e4729ddf29fd 100644
--- a/drivers/net/wireless/atmel.c
+++ b/drivers/net/wireless/atmel.c
@@ -5,9 +5,9 @@
         Copyright 2000-2001 ATMEL Corporation.
         Copyright 2003-2004 Simon Kelley.
 
-    This code was developed from version 2.1.1 of the Atmel drivers, 
-    released by Atmel corp. under the GPL in December 2002. It also 
-    includes code from the Linux aironet drivers (C) Benjamin Reed, 
+    This code was developed from version 2.1.1 of the Atmel drivers,
+    released by Atmel corp. under the GPL in December 2002. It also
+    includes code from the Linux aironet drivers (C) Benjamin Reed,
     and the Linux PCMCIA package, (C) David Hinds and the Linux wireless
     extensions, (C) Jean Tourrilhes.
 
@@ -31,7 +31,7 @@
     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
 
-    For all queries about this code, please contact the current author, 
+    For all queries about this code, please contact the current author,
     Simon Kelley <simon@thekelleys.org.uk> and not Atmel Corporation.
 
     Credit is due to HP UK and Cambridge Online Systems Ltd for supplying
@@ -79,13 +79,13 @@ MODULE_DESCRIPTION("Support for Atmel at76c50x 802.11 wireless ethernet cards.")
 MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("Atmel at76c50x wireless cards");
 
-/* The name of the firmware file to be loaded 
+/* The name of the firmware file to be loaded
    over-rides any automatic selection */
 static char *firmware = NULL;
 module_param(firmware, charp, 0);
 
 /* table of firmware file names */
-static struct { 
+static struct {
 	AtmelFWType fw_type;
 	const char *fw_file;
 	const char *fw_file_ext;
@@ -104,17 +104,17 @@ static struct {
 #define MAX_SSID_LENGTH 32
 #define MGMT_JIFFIES (256 * HZ / 100)
 
-#define MAX_BSS_ENTRIES	64	
+#define MAX_BSS_ENTRIES	64
 
 /* registers */
-#define GCR  0x00    //      (SIR0)  General Configuration Register        
-#define BSR  0x02    //      (SIR1)  Bank Switching Select Register 
+#define GCR  0x00    //      (SIR0)  General Configuration Register
+#define BSR  0x02    //      (SIR1)  Bank Switching Select Register
 #define AR   0x04
 #define DR   0x08
-#define MR1  0x12    //      Mirror Register 1                  
-#define MR2  0x14    //      Mirror Register 2  
-#define MR3  0x16    //      Mirror Register 3  
-#define MR4  0x18    //      Mirror Register 4   
+#define MR1  0x12    //      Mirror Register 1
+#define MR2  0x14    //      Mirror Register 2
+#define MR3  0x16    //      Mirror Register 3
+#define MR4  0x18    //      Mirror Register 4
 
 #define GPR1                            0x0c
 #define GPR2                            0x0e
@@ -123,9 +123,9 @@ static struct {
 // Constants for the GCR register.
 //
 #define GCR_REMAP     0x0400          // Remap internal SRAM to 0
-#define GCR_SWRES     0x0080          // BIU reset (ARM and PAI are NOT reset) 
+#define GCR_SWRES     0x0080          // BIU reset (ARM and PAI are NOT reset)
 #define GCR_CORES     0x0060          // Core Reset (ARM and PAI are reset)
-#define GCR_ENINT     0x0002          // Enable Interrupts    
+#define GCR_ENINT     0x0002          // Enable Interrupts
 #define GCR_ACKINT    0x0008          // Acknowledge Interrupts
 
 #define BSS_SRAM      0x0200          // AMBA module selection --> SRAM
@@ -190,7 +190,7 @@ struct rx_desc {
         u32          Next;
         u16          MsduPos;
         u16          MsduSize;
-	
+
         u8           State;
         u8           Status;
         u8           Rate;
@@ -199,7 +199,6 @@ struct rx_desc {
         u8           PreambleType;
         u16          Duration;
         u32          RxTime;
-
 };
 
 #define RX_DESC_FLAG_VALID       0x80
@@ -218,16 +217,15 @@ struct rx_desc {
 #define RX_DESC_DURATION_OFFSET      14
 #define RX_DESC_RX_TIME_OFFSET       16
 
-
 struct tx_desc {
 	u32       NextDescriptor;
 	u16       TxStartOfFrame;
 	u16       TxLength;
-	
+
 	u8        TxState;
 	u8        TxStatus;
 	u8        RetryCount;
-	
+
 	u8        TxRate;
 
 	u8        KeyIndex;
@@ -238,10 +236,8 @@ struct tx_desc {
 	u8        Reserved;
 	u8        PacketType;
 	u16       HostTxLength;
-	
 };
 
-
 #define TX_DESC_NEXT_OFFSET          0
 #define TX_DESC_POS_OFFSET           4
 #define TX_DESC_SIZE_OFFSET          6
@@ -255,8 +251,6 @@ struct tx_desc {
 #define TX_DESC_PACKET_TYPE_OFFSET   17
 #define TX_DESC_HOST_LENGTH_OFFSET   18
 
-
-
 ///////////////////////////////////////////////////////
 // Host-MAC interface
 ///////////////////////////////////////////////////////
@@ -266,7 +260,6 @@ struct tx_desc {
 #define TX_FIRM_OWN             0x80
 #define TX_DONE                 0x40
 
-
 #define TX_ERROR                0x01
 
 #define TX_PACKET_TYPE_DATA     0x01
@@ -280,8 +273,7 @@ struct tx_desc {
 #define ISR_COMMAND_COMPLETE    0x10        // command completed
 #define ISR_OUT_OF_RANGE        0x20        // command completed
 #define ISR_IBSS_MERGE          0x40        // (4.1.2.30): IBSS merge
-#define ISR_GENERIC_IRQ         0x80                
-
+#define ISR_GENERIC_IRQ         0x80
 
 #define Local_Mib_Type          0x01
 #define Mac_Address_Mib_Type    0x02
@@ -317,7 +309,6 @@ struct tx_desc {
 #define LOCAL_MIB_PREAMBLE_TYPE               9
 #define MAC_ADDR_MIB_MAC_ADDR_POS             0
 
-
 #define         CMD_Set_MIB_Vars              0x01
 #define         CMD_Get_MIB_Vars              0x02
 #define         CMD_Scan                      0x03
@@ -338,7 +329,6 @@ struct tx_desc {
 #define         CMD_STATUS_HOST_ERROR             0xFF
 #define         CMD_STATUS_BUSY                   0xFE
 
-
 #define CMD_BLOCK_COMMAND_OFFSET        0
 #define CMD_BLOCK_STATUS_OFFSET         1
 #define CMD_BLOCK_PARAMETERS_OFFSET     4
@@ -347,15 +337,15 @@ struct tx_desc {
 
 #define MGMT_FRAME_BODY_OFFSET		24
 #define MAX_AUTHENTICATION_RETRIES	3
-#define MAX_ASSOCIATION_RETRIES 	3
+#define MAX_ASSOCIATION_RETRIES		3
 
 #define AUTHENTICATION_RESPONSE_TIME_OUT  1000
 
 #define MAX_WIRELESS_BODY  2316 /* mtu is 2312, CRC is 4 */
 #define LOOP_RETRY_LIMIT   500000
 
-#define ACTIVE_MODE 	1
-#define PS_MODE 	2
+#define ACTIVE_MODE	1
+#define PS_MODE		2
 
 #define MAX_ENCRYPTION_KEYS 4
 #define MAX_ENCRYPTION_KEY_SIZE 40
@@ -377,7 +367,7 @@ struct tx_desc {
 #define REG_DOMAIN_MKK1		0x41	//Channel	1-14	Japan(MKK1)
 #define REG_DOMAIN_ISRAEL	0x50	//Channel	3-9	ISRAEL
 
-#define BSS_TYPE_AD_HOC 	1
+#define BSS_TYPE_AD_HOC		1
 #define BSS_TYPE_INFRASTRUCTURE 2
 
 #define SCAN_TYPE_ACTIVE	0
@@ -389,7 +379,7 @@ struct tx_desc {
 
 #define DATA_FRAME_WS_HEADER_SIZE   30
 
-/* promiscuous mode control */ 
+/* promiscuous mode control */
 #define PROM_MODE_OFF			0x0
 #define PROM_MODE_UNKNOWN		0x1
 #define PROM_MODE_CRC_FAILED		0x2
@@ -398,8 +388,7 @@ struct tx_desc {
 #define PROM_MODE_CTRL			0x10
 #define PROM_MODE_BAD_PROTOCOL		0x20
 
-
-#define IFACE_INT_STATUS_OFFSET 	0
+#define IFACE_INT_STATUS_OFFSET		0
 #define IFACE_INT_MASK_OFFSET		1
 #define IFACE_LOCKOUT_HOST_OFFSET	2
 #define IFACE_LOCKOUT_MAC_OFFSET	3
@@ -407,7 +396,7 @@ struct tx_desc {
 #define IFACE_MAC_STAT_OFFSET		30
 #define IFACE_GENERIC_INT_TYPE_OFFSET	32
 
-#define CIPHER_SUITE_NONE     0 
+#define CIPHER_SUITE_NONE     0
 #define CIPHER_SUITE_WEP_64   1
 #define CIPHER_SUITE_TKIP     2
 #define CIPHER_SUITE_AES      3
@@ -419,11 +408,11 @@ struct tx_desc {
 //
 //
 
-// FuncCtrl field: 
+// FuncCtrl field:
 //
 #define FUNC_CTRL_TxENABLE		0x10
 #define FUNC_CTRL_RxENABLE		0x20
-#define FUNC_CTRL_INIT_COMPLETE 	0x01
+#define FUNC_CTRL_INIT_COMPLETE		0x01
 
 /* A stub firmware image which reads the MAC address from NVRAM on the card.
    For copyright information and source see the end of this file. */
@@ -486,10 +475,10 @@ struct atmel_private {
 	struct net_device_stats	stats;	// device stats
 	spinlock_t irqlock, timerlock;	// spinlocks
 	enum { BUS_TYPE_PCCARD, BUS_TYPE_PCI } bus_type;
-	enum { 
-		CARD_TYPE_PARALLEL_FLASH, 
+	enum {
+		CARD_TYPE_PARALLEL_FLASH,
 		CARD_TYPE_SPI_FLASH,
-		CARD_TYPE_EEPROM 
+		CARD_TYPE_EEPROM
 	} card_type;
 	int do_rx_crc; /* If we need to CRC incoming packets */
 	int probe_crc; /* set if we don't yet know */
@@ -497,18 +486,18 @@ struct atmel_private {
 	u16 rx_desc_head;
 	u16 tx_desc_free, tx_desc_head, tx_desc_tail, tx_desc_previous;
 	u16 tx_free_mem, tx_buff_head, tx_buff_tail;
-	
+
 	u16 frag_seq, frag_len, frag_no;
-	u8 frag_source[6]; 
-	
+	u8 frag_source[6];
+
 	u8 wep_is_on, default_key, exclude_unencrypted, encryption_level;
 	u8 group_cipher_suite, pairwise_cipher_suite;
 	u8 wep_keys[MAX_ENCRYPTION_KEYS][MAX_ENCRYPTION_KEY_SIZE];
-	int wep_key_len[MAX_ENCRYPTION_KEYS]; 
+	int wep_key_len[MAX_ENCRYPTION_KEYS];
 	int use_wpa, radio_on_broken; /* firmware dependent stuff. */
 
 	u16 host_info_base;
-	struct host_info_struct { 
+	struct host_info_struct {
 		/* NB this is matched to the hardware, don't change. */
 		u8 volatile int_status;
 		u8 volatile int_mask;
@@ -524,20 +513,20 @@ struct atmel_private {
 		u16 rx_buff_size;
 		u16 rx_desc_pos;
 		u16 rx_desc_count;
-		
+
 		u16 build_version;
-		u16 command_pos; 	
-		
+		u16 command_pos;
+
 		u16 major_version;
 		u16 minor_version;
-		
+
 		u16 func_ctrl;
 		u16 mac_status;
 		u16 generic_IRQ_type;
 		u8  reserved[2];
 	} host_info;
 
-	enum { 
+	enum {
 		STATION_STATE_SCANNING,
 		STATION_STATE_JOINNING,
 		STATION_STATE_AUTHENTICATING,
@@ -547,7 +536,7 @@ struct atmel_private {
 		STATION_STATE_DOWN,
 		STATION_STATE_MGMT_ERROR
 	} station_state;
-	
+
 	int operating_mode, power_mode;
 	time_t last_qual;
 	int beacons_this_sec;
@@ -560,18 +549,18 @@ struct atmel_private {
 	int long_retry, short_retry;
 	int preamble;
 	int default_beacon_period, beacon_period, listen_interval;
-	int CurrentAuthentTransactionSeqNum, ExpectedAuthentTransactionSeqNum;	
+	int CurrentAuthentTransactionSeqNum, ExpectedAuthentTransactionSeqNum;
 	int AuthenticationRequestRetryCnt, AssociationRequestRetryCnt, ReAssociationRequestRetryCnt;
 	enum {
 		SITE_SURVEY_IDLE,
 		SITE_SURVEY_IN_PROGRESS,
-		SITE_SURVEY_COMPLETED 
+		SITE_SURVEY_COMPLETED
 	} site_survey_state;
 	time_t last_survey;
 
 	int station_was_associated, station_is_associated;
 	int fast_scan;
-				
+
 	struct bss_info {
 		int channel;
 		int SSIDsize;
@@ -584,13 +573,12 @@ struct atmel_private {
 		u8 SSID[MAX_SSID_LENGTH];
 	} BSSinfo[MAX_BSS_ENTRIES];
 	int BSS_list_entries, current_BSS;
-	int connect_to_any_BSS; 
+	int connect_to_any_BSS;
 	int SSID_size, new_SSID_size;
 	u8 CurrentBSSID[6], BSSID[6];
 	u8 SSID[MAX_SSID_LENGTH], new_SSID[MAX_SSID_LENGTH];
 	u64 last_beacon_timestamp;
 	u8 rx_buf[MAX_WIRELESS_BODY];
-	
 };
 
 static u8 atmel_basic_rates[4] = {0x82,0x84,0x0b,0x16};
@@ -598,39 +586,49 @@ static u8 atmel_basic_rates[4] = {0x82,0x84,0x0b,0x16};
 static const struct {
 	int reg_domain;
 	int min, max;
-	char *name; 
+	char *name;
 } channel_table[] = { { REG_DOMAIN_FCC, 1, 11, "USA" },
 		      { REG_DOMAIN_DOC, 1, 11, "Canada" },
 		      { REG_DOMAIN_ETSI, 1, 13, "Europe" },
 		      { REG_DOMAIN_SPAIN, 10, 11, "Spain" },
-		      { REG_DOMAIN_FRANCE, 10, 13, "France" }, 
+		      { REG_DOMAIN_FRANCE, 10, 13, "France" },
 		      { REG_DOMAIN_MKK, 14, 14, "MKK" },
 		      { REG_DOMAIN_MKK1, 1, 14, "MKK1" },
 		      { REG_DOMAIN_ISRAEL, 3, 9, "Israel"} };
 
 static void build_wpa_mib(struct atmel_private *priv);
 static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-static void atmel_copy_to_card(struct net_device *dev, u16 dest, unsigned char *src, u16 len);
-static void atmel_copy_to_host(struct net_device *dev, unsigned char *dest, u16 src, u16 len);
+static void atmel_copy_to_card(struct net_device *dev, u16 dest,
+			       unsigned char *src, u16 len);
+static void atmel_copy_to_host(struct net_device *dev, unsigned char *dest,
+			       u16 src, u16 len);
 static void atmel_set_gcr(struct net_device *dev, u16 mask);
 static void atmel_clear_gcr(struct net_device *dev, u16 mask);
 static int atmel_lock_mac(struct atmel_private *priv);
 static void atmel_wmem32(struct atmel_private *priv, u16 pos, u32 data);
 static void atmel_command_irq(struct atmel_private *priv);
 static int atmel_validate_channel(struct atmel_private *priv, int channel);
-static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_hdr_4addr *header, 
+static void atmel_management_frame(struct atmel_private *priv,
+				   struct ieee80211_hdr_4addr *header,
 				   u16 frame_len, u8 rssi);
 static void atmel_management_timer(u_long a);
-static void atmel_send_command(struct atmel_private *priv, int command, void *cmd, int cmd_size);
-static int atmel_send_command_wait(struct atmel_private *priv, int command, void *cmd, int cmd_size);
-static void atmel_transmit_management_frame(struct atmel_private *priv, struct ieee80211_hdr_4addr *header,
+static void atmel_send_command(struct atmel_private *priv, int command,
+			       void *cmd, int cmd_size);
+static int atmel_send_command_wait(struct atmel_private *priv, int command,
+				   void *cmd, int cmd_size);
+static void atmel_transmit_management_frame(struct atmel_private *priv,
+					    struct ieee80211_hdr_4addr *header,
 					    u8 *body, int body_len);
 
 static u8 atmel_get_mib8(struct atmel_private *priv, u8 type, u8 index);
-static void atmel_set_mib8(struct atmel_private *priv, u8 type, u8 index, u8 data);
-static void atmel_set_mib16(struct atmel_private *priv, u8 type, u8 index, u16 data);
-static void atmel_set_mib(struct atmel_private *priv, u8 type, u8 index, u8 *data, int data_len);
-static void atmel_get_mib(struct atmel_private *priv, u8 type, u8 index, u8 *data, int data_len);
+static void atmel_set_mib8(struct atmel_private *priv, u8 type, u8 index,
+			   u8 data);
+static void atmel_set_mib16(struct atmel_private *priv, u8 type, u8 index,
+			    u16 data);
+static void atmel_set_mib(struct atmel_private *priv, u8 type, u8 index,
+			  u8 *data, int data_len);
+static void atmel_get_mib(struct atmel_private *priv, u8 type, u8 index,
+			  u8 *data, int data_len);
 static void atmel_scan(struct atmel_private *priv, int specific_ssid);
 static void atmel_join_bss(struct atmel_private *priv, int bss_index);
 static void atmel_smooth_qual(struct atmel_private *priv);
@@ -650,12 +648,12 @@ static inline u16 atmel_co(struct atmel_private *priv, u16 offset)
 	return priv->host_info.command_pos + offset;
 }
 
-static inline u16 atmel_rx(struct atmel_private *priv, u16 offset, u16  desc)
+static inline u16 atmel_rx(struct atmel_private *priv, u16 offset, u16 desc)
 {
 	return priv->host_info.rx_desc_pos + (sizeof(struct rx_desc) * desc) + offset;
 }
 
-static inline u16 atmel_tx(struct atmel_private *priv, u16 offset, u16  desc)
+static inline u16 atmel_tx(struct atmel_private *priv, u16 offset, u16 desc)
 {
 	return priv->host_info.tx_desc_pos + (sizeof(struct tx_desc) * desc) + offset;
 }
@@ -682,25 +680,25 @@ static inline void atmel_write16(struct net_device *dev, u16 offset, u16 data)
 
 static inline u8 atmel_rmem8(struct atmel_private *priv, u16 pos)
 {
-	atmel_writeAR(priv->dev, pos);	
+	atmel_writeAR(priv->dev, pos);
 	return atmel_read8(priv->dev, DR);
 }
 
 static inline void atmel_wmem8(struct atmel_private *priv, u16 pos, u16 data)
 {
-	atmel_writeAR(priv->dev, pos);	
+	atmel_writeAR(priv->dev, pos);
 	atmel_write8(priv->dev, DR, data);
 }
 
 static inline u16 atmel_rmem16(struct atmel_private *priv, u16 pos)
 {
-       	atmel_writeAR(priv->dev, pos);	
+	atmel_writeAR(priv->dev, pos);
 	return atmel_read16(priv->dev, DR);
 }
 
 static inline void atmel_wmem16(struct atmel_private *priv, u16 pos, u16 data)
 {
-       	atmel_writeAR(priv->dev, pos);	
+	atmel_writeAR(priv->dev, pos);
 	atmel_write16(priv->dev, DR, data);
 }
 
@@ -710,11 +708,10 @@ static void tx_done_irq(struct atmel_private *priv)
 {
 	int i;
 
-	for (i = 0; 
+	for (i = 0;
 	     atmel_rmem8(priv, atmel_tx(priv, TX_DESC_FLAGS_OFFSET, priv->tx_desc_head)) == TX_DONE &&
 		     i < priv->host_info.tx_desc_count;
 	     i++) {
-		
 		u8 status = atmel_rmem8(priv, atmel_tx(priv, TX_DESC_STATUS_OFFSET, priv->tx_desc_head));
 		u16 msdu_size = atmel_rmem16(priv, atmel_tx(priv, TX_DESC_SIZE_OFFSET, priv->tx_desc_head));
 		u8 type = atmel_rmem8(priv, atmel_tx(priv, TX_DESC_PACKET_TYPE_OFFSET, priv->tx_desc_head));
@@ -728,16 +725,16 @@ static void tx_done_irq(struct atmel_private *priv)
 			priv->tx_buff_head = 0;
 		else
 			priv->tx_buff_head += msdu_size;
-			
+
 		if (priv->tx_desc_head < (priv->host_info.tx_desc_count - 1))
-			priv->tx_desc_head++ ;					
+			priv->tx_desc_head++ ;
 		else
 			priv->tx_desc_head = 0;
-		
+
 		if (type == TX_PACKET_TYPE_DATA) {
 			if (status == TX_STATUS_SUCCESS)
 				priv->stats.tx_packets++;
-			else 
+			else
 				priv->stats.tx_errors++;
 			netif_wake_queue(priv->dev);
 		}
@@ -748,21 +745,22 @@ static u16 find_tx_buff(struct atmel_private *priv, u16 len)
 {
 	u16 bottom_free = priv->host_info.tx_buff_size - priv->tx_buff_tail;
 
-	if (priv->tx_desc_free == 3 || priv->tx_free_mem < len) 
+	if (priv->tx_desc_free == 3 || priv->tx_free_mem < len)
 		return 0;
-	
+
 	if (bottom_free >= len)
 		return priv->host_info.tx_buff_pos + priv->tx_buff_tail;
-	
+
 	if (priv->tx_free_mem - bottom_free >= len) {
 		priv->tx_buff_tail = 0;
 		return priv->host_info.tx_buff_pos;
 	}
-	
+
 	return 0;
 }
 
-static void tx_update_descriptor(struct atmel_private *priv, int is_bcast, u16 len, u16 buff, u8 type)
+static void tx_update_descriptor(struct atmel_private *priv, int is_bcast,
+				 u16 len, u16 buff, u8 type)
 {
 	atmel_wmem16(priv, atmel_tx(priv, TX_DESC_POS_OFFSET, priv->tx_desc_tail), buff);
 	atmel_wmem16(priv, atmel_tx(priv, TX_DESC_SIZE_OFFSET, priv->tx_desc_tail), len);
@@ -775,8 +773,8 @@ static void tx_update_descriptor(struct atmel_private *priv, int is_bcast, u16 l
 		int cipher_type, cipher_length;
 		if (is_bcast) {
 			cipher_type = priv->group_cipher_suite;
-			if (cipher_type == CIPHER_SUITE_WEP_64 || 
-			    cipher_type == CIPHER_SUITE_WEP_128 )
+			if (cipher_type == CIPHER_SUITE_WEP_64 ||
+			    cipher_type == CIPHER_SUITE_WEP_128)
 				cipher_length = 8;
 			else if (cipher_type == CIPHER_SUITE_TKIP)
 				cipher_length = 12;
@@ -790,8 +788,8 @@ static void tx_update_descriptor(struct atmel_private *priv, int is_bcast, u16 l
 			}
 		} else {
 			cipher_type = priv->pairwise_cipher_suite;
-			if (cipher_type == CIPHER_SUITE_WEP_64 || 
-			    cipher_type == CIPHER_SUITE_WEP_128 )
+			if (cipher_type == CIPHER_SUITE_WEP_64 ||
+			    cipher_type == CIPHER_SUITE_WEP_128)
 				cipher_length = 8;
 			else if (cipher_type == CIPHER_SUITE_TKIP)
 				cipher_length = 12;
@@ -804,9 +802,9 @@ static void tx_update_descriptor(struct atmel_private *priv, int is_bcast, u16 l
 				cipher_length = 0;
 			}
 		}
-		
+
 		atmel_wmem8(priv, atmel_tx(priv, TX_DESC_CIPHER_TYPE_OFFSET, priv->tx_desc_tail),
-			    cipher_type);	
+			    cipher_type);
 		atmel_wmem8(priv, atmel_tx(priv, TX_DESC_CIPHER_LENGTH_OFFSET, priv->tx_desc_tail),
 			    cipher_length);
 	}
@@ -815,46 +813,46 @@ static void tx_update_descriptor(struct atmel_private *priv, int is_bcast, u16 l
 	if (priv->tx_desc_previous != priv->tx_desc_tail)
 		atmel_wmem32(priv, atmel_tx(priv, TX_DESC_NEXT_OFFSET, priv->tx_desc_previous), 0);
 	priv->tx_desc_previous = priv->tx_desc_tail;
-	if (priv->tx_desc_tail < (priv->host_info.tx_desc_count -1 ))
+	if (priv->tx_desc_tail < (priv->host_info.tx_desc_count - 1))
 		priv->tx_desc_tail++;
 	else
 		priv->tx_desc_tail = 0;
 	priv->tx_desc_free--;
 	priv->tx_free_mem -= len;
-
 }
 
-static int start_tx (struct sk_buff *skb, struct net_device *dev)
+static int start_tx(struct sk_buff *skb, struct net_device *dev)
 {
 	struct atmel_private *priv = netdev_priv(dev);
 	struct ieee80211_hdr_4addr header;
 	unsigned long flags;
 	u16 buff, frame_ctl, len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
 	u8 SNAP_RFC1024[6] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
- 
-	if (priv->card && priv->present_callback && 
+
+	if (priv->card && priv->present_callback &&
 	    !(*priv->present_callback)(priv->card)) {
 		priv->stats.tx_errors++;
 		dev_kfree_skb(skb);
 		return 0;
 	}
-	
+
 	if (priv->station_state != STATION_STATE_READY) {
 		priv->stats.tx_errors++;
 		dev_kfree_skb(skb);
 		return 0;
 	}
-	
+
 	/* first ensure the timer func cannot run */
-	spin_lock_bh(&priv->timerlock); 
+	spin_lock_bh(&priv->timerlock);
 	/* then stop the hardware ISR */
-	spin_lock_irqsave(&priv->irqlock, flags); 
+	spin_lock_irqsave(&priv->irqlock, flags);
 	/* nb doing the above in the opposite order will deadlock */
-	
+
 	/* The Wireless Header is 30 bytes. In the Ethernet packet we "cut" the
-	   12 first bytes (containing DA/SA) and put them in the appropriate fields of
-	   the Wireless Header. Thus the packet length is then the initial + 18 (+30-12) */
-	
+	   12 first bytes (containing DA/SA) and put them in the appropriate
+	   fields of the Wireless Header. Thus the packet length is then the
+	   initial + 18 (+30-12) */
+
 	if (!(buff = find_tx_buff(priv, len + 18))) {
 		priv->stats.tx_dropped++;
 		spin_unlock_irqrestore(&priv->irqlock, flags);
@@ -862,7 +860,7 @@ static int start_tx (struct sk_buff *skb, struct net_device *dev)
 		netif_stop_queue(dev);
 		return 1;
 	}
-	
+
 	frame_ctl = IEEE80211_FTYPE_DATA;
 	header.duration_id = 0;
 	header.seq_ctl = 0;
@@ -878,7 +876,7 @@ static int start_tx (struct sk_buff *skb, struct net_device *dev)
 		memcpy(&header.addr2, dev->dev_addr, 6);
 		memcpy(&header.addr3, skb->data, 6);
 	}
-	
+
 	if (priv->use_wpa)
 		memcpy(&header.addr4, SNAP_RFC1024, 6);
 
@@ -888,27 +886,27 @@ static int start_tx (struct sk_buff *skb, struct net_device *dev)
 	/* Copy the packet sans its 802.3 header addresses which have been replaced */
 	atmel_copy_to_card(dev, buff + DATA_FRAME_WS_HEADER_SIZE, skb->data + 12, len - 12);
 	priv->tx_buff_tail += len - 12 + DATA_FRAME_WS_HEADER_SIZE;
-	
+
 	/* low bit of first byte of destination tells us if broadcast */
 	tx_update_descriptor(priv, *(skb->data) & 0x01, len + 18, buff, TX_PACKET_TYPE_DATA);
 	dev->trans_start = jiffies;
 	priv->stats.tx_bytes += len;
-	
+
 	spin_unlock_irqrestore(&priv->irqlock, flags);
 	spin_unlock_bh(&priv->timerlock);
 	dev_kfree_skb(skb);
-	
-	return 0;	
+
+	return 0;
 }
 
-static void atmel_transmit_management_frame(struct atmel_private *priv, 
+static void atmel_transmit_management_frame(struct atmel_private *priv,
 					    struct ieee80211_hdr_4addr *header,
 					    u8 *body, int body_len)
 {
 	u16 buff;
-	int len =  MGMT_FRAME_BODY_OFFSET + body_len;
-	
-	if (!(buff = find_tx_buff(priv, len))) 
+	int len = MGMT_FRAME_BODY_OFFSET + body_len;
+
+	if (!(buff = find_tx_buff(priv, len)))
 		return;
 
 	atmel_copy_to_card(priv->dev, buff, (u8 *)header, MGMT_FRAME_BODY_OFFSET);
@@ -916,24 +914,25 @@ static void atmel_transmit_management_frame(struct atmel_private *priv,
 	priv->tx_buff_tail += len;
 	tx_update_descriptor(priv, header->addr1[0] & 0x01, len, buff, TX_PACKET_TYPE_MGMT);
 }
-	
-static void fast_rx_path(struct atmel_private *priv, struct ieee80211_hdr_4addr *header, 
+
+static void fast_rx_path(struct atmel_private *priv,
+			 struct ieee80211_hdr_4addr *header,
 			 u16 msdu_size, u16 rx_packet_loc, u32 crc)
 {
 	/* fast path: unfragmented packet copy directly into skbuf */
-	u8 mac4[6]; 
-	struct sk_buff 	*skb;
+	u8 mac4[6];
+	struct sk_buff	*skb;
 	unsigned char *skbp;
-	
+
 	/* get the final, mac 4 header field, this tells us encapsulation */
 	atmel_copy_to_host(priv->dev, mac4, rx_packet_loc + 24, 6);
 	msdu_size -= 6;
-	
+
 	if (priv->do_rx_crc) {
 		crc = crc32_le(crc, mac4, 6);
 		msdu_size -= 4;
 	}
-	
+
 	if (!(skb = dev_alloc_skb(msdu_size + 14))) {
 		priv->stats.rx_dropped++;
 		return;
@@ -942,7 +941,7 @@ static void fast_rx_path(struct atmel_private *priv, struct ieee80211_hdr_4addr
 	skb_reserve(skb, 2);
 	skbp = skb_put(skb, msdu_size + 12);
 	atmel_copy_to_host(priv->dev, skbp + 12, rx_packet_loc + 30, msdu_size);
-	
+
 	if (priv->do_rx_crc) {
 		u32 netcrc;
 		crc = crc32_le(crc, skbp + 12, msdu_size);
@@ -953,24 +952,25 @@ static void fast_rx_path(struct atmel_private *priv, struct ieee80211_hdr_4addr
 			return;
 		}
 	}
-	
+
 	memcpy(skbp, header->addr1, 6); /* destination address */
-	if (le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_FROMDS) 
+	if (le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_FROMDS)
 		memcpy(&skbp[6], header->addr3, 6);
 	else
 		memcpy(&skbp[6], header->addr2, 6); /* source address */
-	
-	priv->dev->last_rx=jiffies;
+
+	priv->dev->last_rx = jiffies;
 	skb->dev = priv->dev;
 	skb->protocol = eth_type_trans(skb, priv->dev);
-	skb->ip_summed = CHECKSUM_NONE;	
+	skb->ip_summed = CHECKSUM_NONE;
 	netif_rx(skb);
 	priv->stats.rx_bytes += 12 + msdu_size;
 	priv->stats.rx_packets++;
 }
 
 /* Test to see if the packet in card memory at packet_loc has a valid CRC
-   It doesn't matter that this is slow: it is only used to proble the first few packets. */
+   It doesn't matter that this is slow: it is only used to proble the first few
+   packets. */
 static int probe_crc(struct atmel_private *priv, u16 packet_loc, u16 msdu_size)
 {
 	int i = msdu_size - 4;
@@ -980,7 +980,7 @@ static int probe_crc(struct atmel_private *priv, u16 packet_loc, u16 msdu_size)
 		return 0;
 
 	atmel_copy_to_host(priv->dev, (void *)&netcrc, packet_loc + i, 4);
-	
+
 	atmel_writeAR(priv->dev, packet_loc);
 	while (i--) {
 		u8 octet = atmel_read8(priv->dev, DR);
@@ -990,20 +990,22 @@ static int probe_crc(struct atmel_private *priv, u16 packet_loc, u16 msdu_size)
 	return (crc ^ 0xffffffff) == netcrc;
 }
 
-static void frag_rx_path(struct atmel_private *priv, struct ieee80211_hdr_4addr *header, 
-			 u16 msdu_size, u16 rx_packet_loc, u32 crc, u16 seq_no, u8 frag_no, int more_frags)
+static void frag_rx_path(struct atmel_private *priv,
+			 struct ieee80211_hdr_4addr *header,
+			 u16 msdu_size, u16 rx_packet_loc, u32 crc, u16 seq_no,
+			 u8 frag_no, int more_frags)
 {
-	u8 mac4[6]; 
+	u8 mac4[6];
 	u8 source[6];
 	struct sk_buff *skb;
 
-	if (le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_FROMDS) 
+	if (le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_FROMDS)
 		memcpy(source, header->addr3, 6);
 	else
-		memcpy(source, header->addr2, 6); 
-	
+		memcpy(source, header->addr2, 6);
+
 	rx_packet_loc += 24; /* skip header */
-	
+
 	if (priv->do_rx_crc)
 		msdu_size -= 4;
 
@@ -1012,16 +1014,16 @@ static void frag_rx_path(struct atmel_private *priv, struct ieee80211_hdr_4addr
 		msdu_size -= 6;
 		rx_packet_loc += 6;
 
-		if (priv->do_rx_crc) 
+		if (priv->do_rx_crc)
 			crc = crc32_le(crc, mac4, 6);
-	       
+
 		priv->frag_seq = seq_no;
 		priv->frag_no = 1;
 		priv->frag_len = msdu_size;
-		memcpy(priv->frag_source, source, 6); 
+		memcpy(priv->frag_source, source, 6);
 		memcpy(&priv->rx_buf[6], source, 6);
 		memcpy(priv->rx_buf, header->addr1, 6);
-				
+
 		atmel_copy_to_host(priv->dev, &priv->rx_buf[12], rx_packet_loc, msdu_size);
 
 		if (priv->do_rx_crc) {
@@ -1033,17 +1035,17 @@ static void frag_rx_path(struct atmel_private *priv, struct ieee80211_hdr_4addr
 				memset(priv->frag_source, 0xff, 6);
 			}
 		}
-		
+
 	} else if (priv->frag_no == frag_no &&
 		   priv->frag_seq == seq_no &&
 		   memcmp(priv->frag_source, source, 6) == 0) {
-		
-		atmel_copy_to_host(priv->dev, &priv->rx_buf[12 + priv->frag_len], 
+
+		atmel_copy_to_host(priv->dev, &priv->rx_buf[12 + priv->frag_len],
 				   rx_packet_loc, msdu_size);
 		if (priv->do_rx_crc) {
 			u32 netcrc;
-			crc = crc32_le(crc, 
-				       &priv->rx_buf[12 + priv->frag_len], 
+			crc = crc32_le(crc,
+				       &priv->rx_buf[12 + priv->frag_len],
 				       msdu_size);
 			atmel_copy_to_host(priv->dev, (void *)&netcrc, rx_packet_loc + msdu_size, 4);
 			if ((crc ^ 0xffffffff) != netcrc) {
@@ -1052,7 +1054,7 @@ static void frag_rx_path(struct atmel_private *priv, struct ieee80211_hdr_4addr
 				more_frags = 1; /* don't send broken assembly */
 			}
 		}
-		
+
 		priv->frag_len += msdu_size;
 		priv->frag_no++;
 
@@ -1062,60 +1064,60 @@ static void frag_rx_path(struct atmel_private *priv, struct ieee80211_hdr_4addr
 				priv->stats.rx_dropped++;
 			} else {
 				skb_reserve(skb, 2);
-				memcpy(skb_put(skb, priv->frag_len + 12), 
+				memcpy(skb_put(skb, priv->frag_len + 12),
 				       priv->rx_buf,
 				       priv->frag_len + 12);
 				priv->dev->last_rx = jiffies;
 				skb->dev = priv->dev;
 				skb->protocol = eth_type_trans(skb, priv->dev);
-				skb->ip_summed = CHECKSUM_NONE;	
+				skb->ip_summed = CHECKSUM_NONE;
 				netif_rx(skb);
 				priv->stats.rx_bytes += priv->frag_len + 12;
 				priv->stats.rx_packets++;
 			}
 		}
-		
 	} else
 		priv->wstats.discard.fragment++;
 }
-		
+
 static void rx_done_irq(struct atmel_private *priv)
 {
 	int i;
 	struct ieee80211_hdr_4addr header;
-	
-	for (i = 0; 
+
+	for (i = 0;
 	     atmel_rmem8(priv, atmel_rx(priv, RX_DESC_FLAGS_OFFSET, priv->rx_desc_head)) == RX_DESC_FLAG_VALID &&
 		     i < priv->host_info.rx_desc_count;
 	     i++) {
-				
+
 		u16 msdu_size, rx_packet_loc, frame_ctl, seq_control;
 		u8 status = atmel_rmem8(priv, atmel_rx(priv, RX_DESC_STATUS_OFFSET, priv->rx_desc_head));
 		u32 crc = 0xffffffff;
-		
+
 		if (status != RX_STATUS_SUCCESS) {
 			if (status == 0xc1) /* determined by experiment */
 				priv->wstats.discard.nwid++;
 			else
-				priv->stats.rx_errors++; 
+				priv->stats.rx_errors++;
 			goto next;
 		}
 
 		msdu_size = atmel_rmem16(priv, atmel_rx(priv, RX_DESC_MSDU_SIZE_OFFSET, priv->rx_desc_head));
 		rx_packet_loc = atmel_rmem16(priv, atmel_rx(priv, RX_DESC_MSDU_POS_OFFSET, priv->rx_desc_head));
-		
+
 		if (msdu_size < 30) {
-			priv->stats.rx_errors++; 
+			priv->stats.rx_errors++;
 			goto next;
 		}
-		
+
 		/* Get header as far as end of seq_ctl */
 		atmel_copy_to_host(priv->dev, (char *)&header, rx_packet_loc, 24);
 		frame_ctl = le16_to_cpu(header.frame_ctl);
 		seq_control = le16_to_cpu(header.seq_ctl);
 
-		/* probe for CRC use here if needed  once five packets have arrived with
-		   the same crc status, we assume we know what's happening and stop probing */
+		/* probe for CRC use here if needed  once five packets have
+		   arrived with the same crc status, we assume we know what's
+		   happening and stop probing */
 		if (priv->probe_crc) {
 			if (!priv->wep_is_on || !(frame_ctl & IEEE80211_FCTL_PROTECTED)) {
 				priv->do_rx_crc = probe_crc(priv, rx_packet_loc, msdu_size);
@@ -1130,34 +1132,33 @@ static void rx_done_irq(struct atmel_private *priv)
 					priv->probe_crc = 0;
 			}
 		}
-		    
+
 		/* don't CRC header when WEP in use */
 		if (priv->do_rx_crc && (!priv->wep_is_on || !(frame_ctl & IEEE80211_FCTL_PROTECTED))) {
 			crc = crc32_le(0xffffffff, (unsigned char *)&header, 24);
 		}
 		msdu_size -= 24; /* header */
 
-		if ((frame_ctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) { 
-			
+		if ((frame_ctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) {
 			int more_fragments = frame_ctl & IEEE80211_FCTL_MOREFRAGS;
 			u8 packet_fragment_no = seq_control & IEEE80211_SCTL_FRAG;
 			u16 packet_sequence_no = (seq_control & IEEE80211_SCTL_SEQ) >> 4;
-			
-			if (!more_fragments && packet_fragment_no == 0 ) {
+
+			if (!more_fragments && packet_fragment_no == 0) {
 				fast_rx_path(priv, &header, msdu_size, rx_packet_loc, crc);
 			} else {
 				frag_rx_path(priv, &header, msdu_size, rx_packet_loc, crc,
 					     packet_sequence_no, packet_fragment_no, more_fragments);
 			}
 		}
-		
+
 		if ((frame_ctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) {
 			/* copy rest of packet into buffer */
 			atmel_copy_to_host(priv->dev, (unsigned char *)&priv->rx_buf, rx_packet_loc + 24, msdu_size);
-			
+
 			/* we use the same buffer for frag reassembly and control packets */
 			memset(priv->frag_source, 0xff, 6);
-			
+
 			if (priv->do_rx_crc) {
 				/* last 4 octets is crc */
 				msdu_size -= 4;
@@ -1170,18 +1171,18 @@ static void rx_done_irq(struct atmel_private *priv)
 
 			atmel_management_frame(priv, &header, msdu_size,
 					       atmel_rmem8(priv, atmel_rx(priv, RX_DESC_RSSI_OFFSET, priv->rx_desc_head)));
-		} 
+		}
 
-	next:
+next:
 		/* release descriptor */
-		atmel_wmem8(priv, atmel_rx(priv, RX_DESC_FLAGS_OFFSET, priv->rx_desc_head), RX_DESC_FLAG_CONSUMED);  
-		
+		atmel_wmem8(priv, atmel_rx(priv, RX_DESC_FLAGS_OFFSET, priv->rx_desc_head), RX_DESC_FLAG_CONSUMED);
+
 		if (priv->rx_desc_head < (priv->host_info.rx_desc_count - 1))
-			priv->rx_desc_head++;					
+			priv->rx_desc_head++;
 		else
 			priv->rx_desc_head = 0;
 	}
-}	
+}
 
 static irqreturn_t service_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
@@ -1189,7 +1190,7 @@ static irqreturn_t service_interrupt(int irq, void *dev_id, struct pt_regs *regs
 	struct atmel_private *priv = netdev_priv(dev);
 	u8 isr;
 	int i = -1;
-	static u8 irq_order[] = { 
+	static u8 irq_order[] = {
 		ISR_OUT_OF_RANGE,
 		ISR_RxCOMPLETE,
 		ISR_TxCOMPLETE,
@@ -1199,20 +1200,19 @@ static irqreturn_t service_interrupt(int irq, void *dev_id, struct pt_regs *regs
 		ISR_IBSS_MERGE,
 		ISR_GENERIC_IRQ
 	};
-		
 
-	if (priv->card && priv->present_callback && 
+	if (priv->card && priv->present_callback &&
 	    !(*priv->present_callback)(priv->card))
 		return IRQ_HANDLED;
 
 	/* In this state upper-level code assumes it can mess with
 	   the card unhampered by interrupts which may change register state.
 	   Note that even though the card shouldn't generate interrupts
-	   the inturrupt line may be shared. This allows card setup 
+	   the inturrupt line may be shared. This allows card setup
 	   to go on without disabling interrupts for a long time. */
 	if (priv->station_state == STATION_STATE_DOWN)
 		return IRQ_NONE;
-     	
+
 	atmel_clear_gcr(dev, GCR_ENINT); /* disable interrupts */
 
 	while (1) {
@@ -1221,36 +1221,36 @@ static irqreturn_t service_interrupt(int irq, void *dev_id, struct pt_regs *regs
 			printk(KERN_ALERT "%s: failed to contact MAC.\n", dev->name);
 			return IRQ_HANDLED;
 		}
-		
+
 		isr = atmel_rmem8(priv, atmel_hi(priv, IFACE_INT_STATUS_OFFSET));
 		atmel_wmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_MAC_OFFSET), 0);
-		
+
 		if (!isr) {
 			atmel_set_gcr(dev, GCR_ENINT); /* enable interrupts */
 			return i == -1 ? IRQ_NONE : IRQ_HANDLED;
 		}
-		
+
 		atmel_set_gcr(dev, GCR_ACKINT); /* acknowledge interrupt */
-		
+
 		for (i = 0; i < sizeof(irq_order)/sizeof(u8); i++)
 			if (isr & irq_order[i])
 				break;
-		
+
 		if (!atmel_lock_mac(priv)) {
 			/* failed to contact card */
 			printk(KERN_ALERT "%s: failed to contact MAC.\n", dev->name);
 			return IRQ_HANDLED;
 		}
-		
+
 		isr = atmel_rmem8(priv, atmel_hi(priv, IFACE_INT_STATUS_OFFSET));
 		isr ^= irq_order[i];
 		atmel_wmem8(priv, atmel_hi(priv, IFACE_INT_STATUS_OFFSET), isr);
 		atmel_wmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_MAC_OFFSET), 0);
-		
+
 		switch (irq_order[i]) {
-			
-		case ISR_OUT_OF_RANGE: 
-			if (priv->operating_mode == IW_MODE_INFRA && 
+
+		case ISR_OUT_OF_RANGE:
+			if (priv->operating_mode == IW_MODE_INFRA &&
 			    priv->station_state == STATION_STATE_READY) {
 				priv->station_is_associated = 0;
 				atmel_scan(priv, 1);
@@ -1261,24 +1261,24 @@ static irqreturn_t service_interrupt(int irq, void *dev_id, struct pt_regs *regs
 			priv->wstats.discard.misc++;
 			/* fall through */
 		case ISR_RxCOMPLETE:
-			rx_done_irq(priv); 
+			rx_done_irq(priv);
 			break;
-			
+
 		case ISR_TxCOMPLETE:
-			tx_done_irq(priv); 
+			tx_done_irq(priv);
 			break;
-			
+
 		case ISR_FATAL_ERROR:
 			printk(KERN_ALERT "%s: *** FATAL error interrupt ***\n", dev->name);
 			atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
 			break;
-			
-		case ISR_COMMAND_COMPLETE: 
+
+		case ISR_COMMAND_COMPLETE:
 			atmel_command_irq(priv);
 			break;
 
 		case ISR_IBSS_MERGE:
-			atmel_get_mib(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_CUR_BSSID_POS, 
+			atmel_get_mib(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_CUR_BSSID_POS,
 				      priv->CurrentBSSID, 6);
 			/* The WPA stuff cares about the current AP address */
 			if (priv->use_wpa)
@@ -1288,24 +1288,23 @@ static irqreturn_t service_interrupt(int irq, void *dev_id, struct pt_regs *regs
 			printk(KERN_INFO "%s: Generic_irq received.\n", dev->name);
 			break;
 		}
-	}	
+	}
 }
 
-
-static struct net_device_stats *atmel_get_stats (struct net_device *dev)
+static struct net_device_stats *atmel_get_stats(struct net_device *dev)
 {
 	struct atmel_private *priv = netdev_priv(dev);
 	return &priv->stats;
 }
 
-static struct iw_statistics *atmel_get_wireless_stats (struct net_device *dev)
+static struct iw_statistics *atmel_get_wireless_stats(struct net_device *dev)
 {
 	struct atmel_private *priv = netdev_priv(dev);
 
-	/* update the link quality here in case we are seeing no beacons 
+	/* update the link quality here in case we are seeing no beacons
 	   at all to drive the process */
 	atmel_smooth_qual(priv);
-	
+
 	priv->wstats.status = priv->station_state;
 
 	if (priv->operating_mode == IW_MODE_INFRA) {
@@ -1328,8 +1327,8 @@ static struct iw_statistics *atmel_get_wireless_stats (struct net_device *dev)
 					| IW_QUAL_NOISE_INVALID;
 		priv->wstats.miss.beacon = 0;
 	}
-	
-	return (&priv->wstats);
+
+	return &priv->wstats;
 }
 
 static int atmel_change_mtu(struct net_device *dev, int new_mtu)
@@ -1343,21 +1342,21 @@ static int atmel_change_mtu(struct net_device *dev, int new_mtu)
 static int atmel_set_mac_address(struct net_device *dev, void *p)
 {
 	struct sockaddr *addr = p;
-        
+
         memcpy (dev->dev_addr, addr->sa_data, dev->addr_len);
 	return atmel_open(dev);
 }
 
 EXPORT_SYMBOL(atmel_open);
 
-int atmel_open (struct net_device *dev)
+int atmel_open(struct net_device *dev)
 {
 	struct atmel_private *priv = netdev_priv(dev);
 	int i, channel;
 
 	/* any scheduled timer is no longer needed and might screw things up.. */
 	del_timer_sync(&priv->management_timer);
-	
+
 	/* Interrupts will not touch the card once in this state... */
 	priv->station_state = STATION_STATE_DOWN;
 
@@ -1377,7 +1376,7 @@ int atmel_open (struct net_device *dev)
 	priv->site_survey_state = SITE_SURVEY_IDLE;
 	priv->station_is_associated = 0;
 
-	if (!reset_atmel_card(dev)) 
+	if (!reset_atmel_card(dev))
 		return -EAGAIN;
 
 	if (priv->config_reg_domain) {
@@ -1391,26 +1390,26 @@ int atmel_open (struct net_device *dev)
 		if (i == sizeof(channel_table)/sizeof(channel_table[0])) {
 			priv->reg_domain = REG_DOMAIN_MKK1;
 			printk(KERN_ALERT "%s: failed to get regulatory domain: assuming MKK1.\n", dev->name);
-		} 
+		}
 	}
-	
+
 	if ((channel = atmel_validate_channel(priv, priv->channel)))
 		priv->channel = channel;
 
-	/* this moves station_state on.... */ 
-	atmel_scan(priv, 1);	
+	/* this moves station_state on.... */
+	atmel_scan(priv, 1);
 
 	atmel_set_gcr(priv->dev, GCR_ENINT); /* enable interrupts */
 	return 0;
 }
 
-static int atmel_close (struct net_device *dev)
+static int atmel_close(struct net_device *dev)
 {
 	struct atmel_private *priv = netdev_priv(dev);
-		
+
 	atmel_enter_state(priv, STATION_STATE_DOWN);
-	
-	if (priv->bus_type == BUS_TYPE_PCCARD) 
+
+	if (priv->bus_type == BUS_TYPE_PCCARD)
 		atmel_write16(dev, GCR, 0x0060);
 	atmel_write16(dev, GCR, 0x0040);
 	return 0;
@@ -1438,43 +1437,46 @@ static int atmel_proc_output (char *buf, struct atmel_private *priv)
 	int i;
 	char *p = buf;
 	char *s, *r, *c;
-	
-	p += sprintf(p, "Driver version:\t\t%d.%d\n", DRIVER_MAJOR, DRIVER_MINOR);
-	
+
+	p += sprintf(p, "Driver version:\t\t%d.%d\n",
+		     DRIVER_MAJOR, DRIVER_MINOR);
+
 	if (priv->station_state != STATION_STATE_DOWN) {
-		p += sprintf(p, "Firmware version:\t%d.%d build %d\nFirmware location:\t", 
+		p += sprintf(p, "Firmware version:\t%d.%d build %d\n"
+				"Firmware location:\t",
 			     priv->host_info.major_version,
 			     priv->host_info.minor_version,
 			     priv->host_info.build_version);
-		
-		if (priv->card_type != CARD_TYPE_EEPROM) 
+
+		if (priv->card_type != CARD_TYPE_EEPROM)
 			p += sprintf(p, "on card\n");
-		else if (priv->firmware) 
-			p += sprintf(p, "%s loaded by host\n", priv->firmware_id);
+		else if (priv->firmware)
+			p += sprintf(p, "%s loaded by host\n",
+				     priv->firmware_id);
 		else
-			p += sprintf(p, "%s loaded by hotplug\n", priv->firmware_id);
-		
-		switch(priv->card_type) {
+			p += sprintf(p, "%s loaded by hotplug\n",
+				     priv->firmware_id);
+
+		switch (priv->card_type) {
 		case CARD_TYPE_PARALLEL_FLASH: c = "Parallel flash"; break;
 		case CARD_TYPE_SPI_FLASH: c = "SPI flash\n"; break;
 		case CARD_TYPE_EEPROM: c = "EEPROM"; break;
 		default: c = "<unknown>";
 		}
 
-		
 		r = "<unknown>";
 		for (i = 0; i < sizeof(channel_table)/sizeof(channel_table[0]); i++)
 			if (priv->reg_domain == channel_table[i].reg_domain)
 				r = channel_table[i].name;
-		
+
 		p += sprintf(p, "MAC memory type:\t%s\n", c);
 		p += sprintf(p, "Regulatory domain:\t%s\n", r);
-		p += sprintf(p, "Host CRC checking:\t%s\n", 
+		p += sprintf(p, "Host CRC checking:\t%s\n",
 			     priv->do_rx_crc ? "On" : "Off");
 		p += sprintf(p, "WPA-capable firmware:\t%s\n",
 			     priv->use_wpa ? "Yes" : "No");
 	}
-	
+
 	switch(priv->station_state) {
 	case STATION_STATE_SCANNING: s = "Scanning"; break;
 	case STATION_STATE_JOINNING: s = "Joining"; break;
@@ -1486,9 +1488,9 @@ static int atmel_proc_output (char *buf, struct atmel_private *priv)
 	case STATION_STATE_DOWN: s = "Down"; break;
 	default: s = "<unknown>";
 	}
-      
+
 	p += sprintf(p, "Current state:\t\t%s\n", s);
-	return  p - buf;
+	return p - buf;
 }
 
 static int atmel_read_proc(char *page, char **start, off_t off,
@@ -1504,9 +1506,12 @@ static int atmel_read_proc(char *page, char **start, off_t off,
         return len;
 }
 
-struct net_device *init_atmel_card( unsigned short irq, unsigned long port, const AtmelFWType fw_type,  
-				    struct device *sys_dev, int (*card_present)(void *), void *card)
+struct net_device *init_atmel_card(unsigned short irq, unsigned long port,
+				   const AtmelFWType fw_type,
+				   struct device *sys_dev,
+				   int (*card_present)(void *), void *card)
 {
+	struct proc_dir_entry *ent;
 	struct net_device *dev;
 	struct atmel_private *priv;
 	int rc;
@@ -1514,11 +1519,11 @@ struct net_device *init_atmel_card( unsigned short irq, unsigned long port, cons
 	/* Create the network device object. */
         dev = alloc_etherdev(sizeof(*priv));
         if (!dev) {
-		printk(KERN_ERR "atmel:  Couldn't alloc_etherdev\n");
+		printk(KERN_ERR "atmel: Couldn't alloc_etherdev\n");
 		return NULL;
         }
 	if (dev_alloc_name(dev, dev->name) < 0) {
-		printk(KERN_ERR "atmel:  Couldn't get name!\n");
+		printk(KERN_ERR "atmel: Couldn't get name!\n");
 		goto err_out_free;
 	}
 
@@ -1550,7 +1555,7 @@ struct net_device *init_atmel_card( unsigned short irq, unsigned long port, cons
 	memset(priv->BSSID, 0, 6);
 	priv->CurrentBSSID[0] = 0xFF; /* Initialize to something invalid.... */
 	priv->station_was_associated = 0;
-	
+
 	priv->last_survey = jiffies;
 	priv->preamble = LONG_PREAMBLE;
 	priv->operating_mode = IW_MODE_INFRA;
@@ -1586,7 +1591,7 @@ struct net_device *init_atmel_card( unsigned short irq, unsigned long port, cons
 	spin_lock_init(&priv->timerlock);
 	priv->management_timer.function = atmel_management_timer;
 	priv->management_timer.data = (unsigned long) dev;
-	
+
 	dev->open = atmel_open;
 	dev->stop = atmel_close;
 	dev->change_mtu = atmel_change_mtu;
@@ -1597,44 +1602,46 @@ struct net_device *init_atmel_card( unsigned short irq, unsigned long port, cons
 	dev->do_ioctl = atmel_ioctl;
 	dev->irq = irq;
 	dev->base_addr = port;
-	
+
 	SET_NETDEV_DEV(dev, sys_dev);
-	
+
 	if ((rc = request_irq(dev->irq, service_interrupt, SA_SHIRQ, dev->name, dev))) {
-		printk(KERN_ERR "%s: register interrupt %d failed, rc %d\n", dev->name, irq, rc );
+		printk(KERN_ERR "%s: register interrupt %d failed, rc %d\n", dev->name, irq, rc);
 		goto err_out_free;
 	}
 
-	if (!request_region(dev->base_addr, 32, 
+	if (!request_region(dev->base_addr, 32,
 			    priv->bus_type == BUS_TYPE_PCCARD ?  "atmel_cs" : "atmel_pci")) {
 		goto err_out_irq;
 	}
-	
+
 	if (register_netdev(dev))
 		goto err_out_res;
-	
+
 	if (!probe_atmel_card(dev)){
 		unregister_netdev(dev);
 		goto err_out_res;
 	}
-	
+
 	netif_carrier_off(dev);
-	
-	create_proc_read_entry ("driver/atmel", 0, NULL, atmel_read_proc, priv);	
-	
+
+	ent = create_proc_read_entry ("driver/atmel", 0, NULL, atmel_read_proc, priv);
+	if (!ent)
+		printk(KERN_WARNING "atmel: unable to create /proc entry.\n");
+
 	printk(KERN_INFO "%s: Atmel at76c50x. Version %d.%d. MAC %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
 	       dev->name, DRIVER_MAJOR, DRIVER_MINOR,
 	       dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
 	       dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5] );
-	
+
 	SET_MODULE_OWNER(dev);
 	return dev;
-	
- err_out_res:
+
+err_out_res:
 	release_region( dev->base_addr, 32);
- err_out_irq:
+err_out_irq:
 	free_irq(dev->irq, dev);
- err_out_free:
+err_out_free:
 	free_netdev(dev);
 	return NULL;
 }
@@ -1644,12 +1651,12 @@ EXPORT_SYMBOL(init_atmel_card);
 void stop_atmel_card(struct net_device *dev)
 {
 	struct atmel_private *priv = netdev_priv(dev);
-		
+
 	/* put a brick on it... */
-	if (priv->bus_type == BUS_TYPE_PCCARD) 
+	if (priv->bus_type == BUS_TYPE_PCCARD)
 		atmel_write16(dev, GCR, 0x0060);
 	atmel_write16(dev, GCR, 0x0040);
-	
+
 	del_timer_sync(&priv->management_timer);
 	unregister_netdev(dev);
 	remove_proc_entry("driver/atmel", NULL);
@@ -1675,13 +1682,13 @@ static int atmel_set_essid(struct net_device *dev,
 		int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
 
 		priv->connect_to_any_BSS = 0;
-		
+
 		/* Check the size of the string */
 		if (dwrq->length > MAX_SSID_LENGTH + 1)
-			 return -E2BIG ;
+			 return -E2BIG;
 		if (index != 0)
 			return -EINVAL;
-		
+
 		memcpy(priv->new_SSID, extra, dwrq->length - 1);
 		priv->new_SSID_size = dwrq->length - 1;
 	}
@@ -1706,7 +1713,7 @@ static int atmel_get_essid(struct net_device *dev,
 		extra[priv->SSID_size] = '\0';
 		dwrq->length = priv->SSID_size + 1;
 	}
-	
+
 	dwrq->flags = !priv->connect_to_any_BSS; /* active */
 
 	return 0;
@@ -1768,7 +1775,7 @@ static int atmel_set_encode(struct net_device *dev,
 		/* WE specify that if a valid key is set, encryption
 		 * should be enabled (user may turn it off later)
 		 * This is also how "iwconfig ethX key on" works */
-		if (index == current_index && 
+		if (index == current_index &&
 		    priv->wep_key_len[index] > 0) {
 			priv->wep_is_on = 1;
 			priv->exclude_unencrypted = 1;
@@ -1783,18 +1790,18 @@ static int atmel_set_encode(struct net_device *dev,
 	} else {
 		/* Do we want to just set the transmit key index ? */
 		int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
-		if ( index>=0 && index < 4 ) {
+		if (index >= 0 && index < 4) {
 			priv->default_key = index;
 		} else
 			/* Don't complain if only change the mode */
-			if(!dwrq->flags & IW_ENCODE_MODE) {
+			if (!dwrq->flags & IW_ENCODE_MODE) {
 				return -EINVAL;
 			}
 	}
 	/* Read the flags */
-	if(dwrq->flags & IW_ENCODE_DISABLED) {
+	if (dwrq->flags & IW_ENCODE_DISABLED) {
 		priv->wep_is_on = 0;
-		priv->encryption_level = 0; 	
+		priv->encryption_level = 0;
 		priv->pairwise_cipher_suite = CIPHER_SUITE_NONE;
 	} else {
 		priv->wep_is_on = 1;
@@ -1806,15 +1813,14 @@ static int atmel_set_encode(struct net_device *dev,
 			priv->encryption_level = 1;
 		}
 	}
-	if(dwrq->flags & IW_ENCODE_RESTRICTED)
+	if (dwrq->flags & IW_ENCODE_RESTRICTED)
 		priv->exclude_unencrypted = 1;
-       	if(dwrq->flags & IW_ENCODE_OPEN) 
+	if(dwrq->flags & IW_ENCODE_OPEN)
 		priv->exclude_unencrypted = 0;
-       
+
 	return -EINPROGRESS;		/* Call commit handler */
 }
 
-
 static int atmel_get_encode(struct net_device *dev,
 			    struct iw_request_info *info,
 			    struct iw_point *dwrq,
@@ -1822,7 +1828,7 @@ static int atmel_get_encode(struct net_device *dev,
 {
 	struct atmel_private *priv = netdev_priv(dev);
 	int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
-	
+
 	if (!priv->wep_is_on)
 		dwrq->flags = IW_ENCODE_DISABLED;
 	else {
@@ -1843,7 +1849,7 @@ static int atmel_get_encode(struct net_device *dev,
 		memset(extra, 0, 16);
 		memcpy(extra, priv->wep_keys[index], dwrq->length);
 	}
-	
+
 	return 0;
 }
 
@@ -1862,17 +1868,17 @@ static int atmel_set_rate(struct net_device *dev,
 			  char *extra)
 {
 	struct atmel_private *priv = netdev_priv(dev);
-	
+
 	if (vwrq->fixed == 0) {
 		priv->tx_rate = 3;
 		priv->auto_tx_rate = 1;
 	} else {
 		priv->auto_tx_rate = 0;
-		
+
 		/* Which type of value ? */
-		if((vwrq->value < 4) && (vwrq->value >= 0)) {
+		if ((vwrq->value < 4) && (vwrq->value >= 0)) {
 			/* Setting by rate index */
-		priv->tx_rate = vwrq->value;
+			priv->tx_rate = vwrq->value;
 		} else {
 		/* Setting by frequency value */
 			switch (vwrq->value) {
@@ -1899,7 +1905,7 @@ static int atmel_set_mode(struct net_device *dev,
 		return -EINVAL;
 
 	priv->operating_mode = *uwrq;
-	return -EINPROGRESS;  
+	return -EINPROGRESS;
 }
 
 static int atmel_get_mode(struct net_device *dev,
@@ -1908,7 +1914,7 @@ static int atmel_get_mode(struct net_device *dev,
 			  char *extra)
 {
 	struct atmel_private *priv = netdev_priv(dev);
-	
+
 	*uwrq = priv->operating_mode;
 	return 0;
 }
@@ -1962,9 +1968,9 @@ static int atmel_set_retry(struct net_device *dev,
 			   char *extra)
 {
 	struct atmel_private *priv = netdev_priv(dev);
-	
-	if(!vwrq->disabled && (vwrq->flags & IW_RETRY_LIMIT)) {
-		if(vwrq->flags & IW_RETRY_MAX)
+
+	if (!vwrq->disabled && (vwrq->flags & IW_RETRY_LIMIT)) {
+		if (vwrq->flags & IW_RETRY_MAX)
 			priv->long_retry = vwrq->value;
 		else if (vwrq->flags & IW_RETRY_MIN)
 			priv->short_retry = vwrq->value;
@@ -1973,9 +1979,9 @@ static int atmel_set_retry(struct net_device *dev,
 			priv->long_retry = vwrq->value;
 			priv->short_retry = vwrq->value;
 		}
-		return -EINPROGRESS;		
+		return -EINPROGRESS;
 	}
-	   
+
 	return -EINVAL;
 }
 
@@ -1989,13 +1995,13 @@ static int atmel_get_retry(struct net_device *dev,
 	vwrq->disabled = 0;      /* Can't be disabled */
 
 	/* Note : by default, display the min retry number */
-	if((vwrq->flags & IW_RETRY_MAX)) {
+	if (vwrq->flags & IW_RETRY_MAX) {
 		vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
 		vwrq->value = priv->long_retry;
 	} else {
 		vwrq->flags = IW_RETRY_LIMIT;
 		vwrq->value = priv->short_retry;
-		if(priv->long_retry != priv->short_retry)
+		if (priv->long_retry != priv->short_retry)
 			vwrq->flags |= IW_RETRY_MIN;
 	}
 
@@ -2010,13 +2016,13 @@ static int atmel_set_rts(struct net_device *dev,
 	struct atmel_private *priv = netdev_priv(dev);
 	int rthr = vwrq->value;
 
-	if(vwrq->disabled)
+	if (vwrq->disabled)
 		rthr = 2347;
-	if((rthr < 0) || (rthr > 2347)) {
+	if ((rthr < 0) || (rthr > 2347)) {
 		return -EINVAL;
 	}
 	priv->rts_threshold = rthr;
-	
+
 	return -EINPROGRESS;		/* Call commit handler */
 }
 
@@ -2026,7 +2032,7 @@ static int atmel_get_rts(struct net_device *dev,
 			 char *extra)
 {
 	struct atmel_private *priv = netdev_priv(dev);
-	
+
 	vwrq->value = priv->rts_threshold;
 	vwrq->disabled = (vwrq->value >= 2347);
 	vwrq->fixed = 1;
@@ -2042,14 +2048,14 @@ static int atmel_set_frag(struct net_device *dev,
 	struct atmel_private *priv = netdev_priv(dev);
 	int fthr = vwrq->value;
 
-	if(vwrq->disabled)
+	if (vwrq->disabled)
 		fthr = 2346;
-	if((fthr < 256) || (fthr > 2346)) {
+	if ((fthr < 256) || (fthr > 2346)) {
 		return -EINVAL;
 	}
 	fthr &= ~0x1;	/* Get an even value - is it really needed ??? */
 	priv->frag_threshold = fthr;
-	
+
 	return -EINPROGRESS;		/* Call commit handler */
 }
 
@@ -2077,21 +2083,21 @@ static int atmel_set_freq(struct net_device *dev,
 {
 	struct atmel_private *priv = netdev_priv(dev);
 	int rc = -EINPROGRESS;		/* Call commit handler */
-	
+
 	/* If setting by frequency, convert to a channel */
-	if((fwrq->e == 1) &&
-	   (fwrq->m >= (int) 241200000) &&
-	   (fwrq->m <= (int) 248700000)) {
+	if ((fwrq->e == 1) &&
+	    (fwrq->m >= (int) 241200000) &&
+	    (fwrq->m <= (int) 248700000)) {
 		int f = fwrq->m / 100000;
 		int c = 0;
-		while((c < 14) && (f != frequency_list[c]))
+		while ((c < 14) && (f != frequency_list[c]))
 			c++;
 		/* Hack to fall through... */
 		fwrq->e = 0;
 		fwrq->m = c + 1;
 	}
 	/* Setting by channel number */
-	if((fwrq->m > 1000) || (fwrq->e > 0))
+	if ((fwrq->m > 1000) || (fwrq->e > 0))
 		rc = -EOPNOTSUPP;
 	else {
 		int channel = fwrq->m;
@@ -2099,7 +2105,7 @@ static int atmel_set_freq(struct net_device *dev,
 			priv->channel = channel;
 		} else {
 			rc = -EINVAL;
-		} 
+		}
 	}
 	return rc;
 }
@@ -2130,7 +2136,7 @@ static int atmel_set_scan(struct net_device *dev,
 	 * This is not an error, while the device perform scanning,
 	 * traffic doesn't flow, so it's a perfect DoS...
 	 * Jean II */
-	
+
 	if (priv->station_state == STATION_STATE_DOWN)
 		return -EAGAIN;
 
@@ -2142,15 +2148,15 @@ static int atmel_set_scan(struct net_device *dev,
 	/* Initiate a scan command */
 	if (priv->site_survey_state == SITE_SURVEY_IN_PROGRESS)
 		return -EBUSY;
-		
+
 	del_timer_sync(&priv->management_timer);
 	spin_lock_irqsave(&priv->irqlock, flags);
-	
+
 	priv->site_survey_state = SITE_SURVEY_IN_PROGRESS;
 	priv->fast_scan = 0;
 	atmel_scan(priv, 0);
 	spin_unlock_irqrestore(&priv->irqlock, flags);
-	
+
 	return 0;
 }
 
@@ -2163,11 +2169,11 @@ static int atmel_get_scan(struct net_device *dev,
 	int i;
 	char *current_ev = extra;
 	struct iw_event	iwe;
-	
+
 	if (priv->site_survey_state != SITE_SURVEY_COMPLETED)
 		return -EAGAIN;
-	
-	for(i=0; i<priv->BSS_list_entries; i++) { 
+
+	for (i = 0; i < priv->BSS_list_entries; i++) {
 		iwe.cmd = SIOCGIWAP;
 		iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
 		memcpy(iwe.u.ap_addr.sa_data, priv->BSSinfo[i].BSSID, 6);
@@ -2179,16 +2185,16 @@ static int atmel_get_scan(struct net_device *dev,
 		iwe.cmd = SIOCGIWESSID;
 		iwe.u.data.flags = 1;
 		current_ev = iwe_stream_add_point(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, priv->BSSinfo[i].SSID);
-		
+
 		iwe.cmd = SIOCGIWMODE;
 		iwe.u.mode = priv->BSSinfo[i].BSStype;
 		current_ev = iwe_stream_add_event(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, IW_EV_UINT_LEN);
-	
+
 		iwe.cmd = SIOCGIWFREQ;
 		iwe.u.freq.m = priv->BSSinfo[i].channel;
 		iwe.u.freq.e = 0;
 		current_ev = iwe_stream_add_event(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, IW_EV_FREQ_LEN);
-		
+
 		iwe.cmd = SIOCGIWENCODE;
 		if (priv->BSSinfo[i].UsingWEP)
 			iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
@@ -2196,13 +2202,12 @@ static int atmel_get_scan(struct net_device *dev,
 			iwe.u.data.flags = IW_ENCODE_DISABLED;
 		iwe.u.data.length = 0;
 		current_ev = iwe_stream_add_point(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, NULL);
-		
 	}
 
 	/* Length of data */
 	dwrq->length = (current_ev - extra);
-	dwrq->flags = 0;   
-	
+	dwrq->flags = 0;
+
 	return 0;
 }
 
@@ -2213,7 +2218,7 @@ static int atmel_get_range(struct net_device *dev,
 {
 	struct atmel_private *priv = netdev_priv(dev);
 	struct iw_range *range = (struct iw_range *) extra;
-	int k,i,j;
+	int k, i, j;
 
 	dwrq->length = sizeof(struct iw_range);
 	memset(range, 0, sizeof(struct iw_range));
@@ -2226,14 +2231,14 @@ static int atmel_get_range(struct net_device *dev,
 			break;
 		}
 	if (range->num_channels != 0) {
-		for(k = 0, i = channel_table[j].min; i <= channel_table[j].max; i++) {
+		for (k = 0, i = channel_table[j].min; i <= channel_table[j].max; i++) {
 			range->freq[k].i = i; /* List index */
-			range->freq[k].m = frequency_list[i-1] * 100000;
+			range->freq[k].m = frequency_list[i - 1] * 100000;
 			range->freq[k++].e = 1;	/* Values in table in MHz -> * 10^5 * 10 */
 		}
 		range->num_frequency = k;
 	}
-	
+
 	range->max_qual.qual = 100;
 	range->max_qual.level = 100;
 	range->max_qual.noise = 0;
@@ -2261,11 +2266,11 @@ static int atmel_get_range(struct net_device *dev,
 	range->encoding_size[1] = 13;
 	range->num_encoding_sizes = 2;
 	range->max_encoding_tokens = 4;
-	
+
 	range->pmp_flags = IW_POWER_ON;
 	range->pmt_flags = IW_POWER_ON;
 	range->pm_capa = 0;
-	
+
 	range->we_version_source = WIRELESS_EXT;
 	range->we_version_compiled = WIRELESS_EXT;
 	range->retry_capa = IW_RETRY_LIMIT ;
@@ -2289,7 +2294,7 @@ static int atmel_set_wap(struct net_device *dev,
 
 	if (awrq->sa_family != ARPHRD_ETHER)
 		return -EINVAL;
-	
+
 	if (memcmp(bcast, awrq->sa_data, 6) == 0) {
 		del_timer_sync(&priv->management_timer);
 		spin_lock_irqsave(&priv->irqlock, flags);
@@ -2297,8 +2302,8 @@ static int atmel_set_wap(struct net_device *dev,
 		spin_unlock_irqrestore(&priv->irqlock, flags);
 		return 0;
 	}
-	
-	for(i=0; i<priv->BSS_list_entries; i++) {
+
+	for (i = 0; i < priv->BSS_list_entries; i++) {
 		if (memcmp(priv->BSSinfo[i].BSSID, awrq->sa_data, 6) == 0) {
 			if (!priv->wep_is_on && priv->BSSinfo[i].UsingWEP) {
 				return -EINVAL;
@@ -2313,10 +2318,10 @@ static int atmel_set_wap(struct net_device *dev,
 			}
 		}
 	}
-		
+
 	return -EINVAL;
 }
-	
+
 static int atmel_config_commit(struct net_device *dev,
 			       struct iw_request_info *info,	/* NULL */
 			       void *zwrq,			/* NULL */
@@ -2325,18 +2330,18 @@ static int atmel_config_commit(struct net_device *dev,
 	return atmel_open(dev);
 }
 
-static const iw_handler		atmel_handler[] =
+static const iw_handler atmel_handler[] =
 {
 	(iw_handler) atmel_config_commit,	/* SIOCSIWCOMMIT */
-	(iw_handler) atmel_get_name,    	/* SIOCGIWNAME */
+	(iw_handler) atmel_get_name,		/* SIOCGIWNAME */
 	(iw_handler) NULL,			/* SIOCSIWNWID */
 	(iw_handler) NULL,			/* SIOCGIWNWID */
 	(iw_handler) atmel_set_freq,		/* SIOCSIWFREQ */
 	(iw_handler) atmel_get_freq,		/* SIOCGIWFREQ */
 	(iw_handler) atmel_set_mode,		/* SIOCSIWMODE */
 	(iw_handler) atmel_get_mode,		/* SIOCGIWMODE */
-	(iw_handler) NULL,                  	/* SIOCSIWSENS */
-	(iw_handler) NULL,           		/* SIOCGIWSENS */
+	(iw_handler) NULL,			/* SIOCSIWSENS */
+	(iw_handler) NULL,			/* SIOCGIWSENS */
 	(iw_handler) NULL,			/* SIOCSIWRANGE */
 	(iw_handler) atmel_get_range,           /* SIOCGIWRANGE */
 	(iw_handler) NULL,			/* SIOCSIWPRIV */
@@ -2350,13 +2355,13 @@ static const iw_handler		atmel_handler[] =
 	(iw_handler) atmel_set_wap,		/* SIOCSIWAP */
 	(iw_handler) atmel_get_wap,		/* SIOCGIWAP */
 	(iw_handler) NULL,			/* -- hole -- */
-	(iw_handler) NULL,       		/* SIOCGIWAPLIST */
+	(iw_handler) NULL,			/* SIOCGIWAPLIST */
 	(iw_handler) atmel_set_scan,		/* SIOCSIWSCAN */
 	(iw_handler) atmel_get_scan,		/* SIOCGIWSCAN */
 	(iw_handler) atmel_set_essid,		/* SIOCSIWESSID */
 	(iw_handler) atmel_get_essid,		/* SIOCGIWESSID */
-	(iw_handler) NULL,         		/* SIOCSIWNICKN */
-	(iw_handler) NULL,          		/* SIOCGIWNICKN */
+	(iw_handler) NULL,			/* SIOCSIWNICKN */
+	(iw_handler) NULL,			/* SIOCGIWNICKN */
 	(iw_handler) NULL,			/* -- hole -- */
 	(iw_handler) NULL,			/* -- hole -- */
 	(iw_handler) atmel_set_rate,		/* SIOCSIWRATE */
@@ -2365,8 +2370,8 @@ static const iw_handler		atmel_handler[] =
 	(iw_handler) atmel_get_rts,		/* SIOCGIWRTS */
 	(iw_handler) atmel_set_frag,		/* SIOCSIWFRAG */
 	(iw_handler) atmel_get_frag,		/* SIOCGIWFRAG */
-	(iw_handler) NULL,         		/* SIOCSIWTXPOW */
-	(iw_handler) NULL,          		/* SIOCGIWTXPOW */
+	(iw_handler) NULL,			/* SIOCSIWTXPOW */
+	(iw_handler) NULL,			/* SIOCGIWTXPOW */
 	(iw_handler) atmel_set_retry,		/* SIOCSIWRETRY */
 	(iw_handler) atmel_get_retry,		/* SIOCGIWRETRY */
 	(iw_handler) atmel_set_encode,		/* SIOCSIWENCODE */
@@ -2375,39 +2380,51 @@ static const iw_handler		atmel_handler[] =
 	(iw_handler) atmel_get_power,		/* SIOCGIWPOWER */
 };
 
-
-static const iw_handler		atmel_private_handler[] =
+static const iw_handler atmel_private_handler[] =
 {
 	NULL,				/* SIOCIWFIRSTPRIV */
 };
 
 typedef struct atmel_priv_ioctl {
 	char id[32];
-	unsigned char __user *data;		
-	unsigned short len;		
+	unsigned char __user *data;
+	unsigned short len;
 } atmel_priv_ioctl;
 
-	
-#define ATMELFWL SIOCIWFIRSTPRIV
-#define ATMELIDIFC ATMELFWL + 1
-#define ATMELRD ATMELFWL + 2
-#define ATMELMAGIC 0x51807 
+#define ATMELFWL	SIOCIWFIRSTPRIV
+#define ATMELIDIFC	ATMELFWL + 1
+#define ATMELRD		ATMELFWL + 2
+#define ATMELMAGIC 0x51807
 #define REGDOMAINSZ 20
 
 static const struct iw_priv_args atmel_private_args[] = {
-/*{ cmd,         set_args,                            get_args, name } */
-  { ATMELFWL, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | sizeof (atmel_priv_ioctl), IW_PRIV_TYPE_NONE, "atmelfwl" },
-  { ATMELIDIFC, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "atmelidifc" },
-  { ATMELRD, IW_PRIV_TYPE_CHAR | REGDOMAINSZ, IW_PRIV_TYPE_NONE, "regdomain" },
+	{
+		.cmd = ATMELFWL,
+		.set_args = IW_PRIV_TYPE_BYTE
+				| IW_PRIV_SIZE_FIXED
+				| sizeof (atmel_priv_ioctl),
+		.get_args = IW_PRIV_TYPE_NONE,
+		.name = "atmelfwl"
+	}, {
+		.cmd = ATMELIDIFC,
+		.set_args = IW_PRIV_TYPE_NONE,
+		.get_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+		.name = "atmelidifc"
+	}, {
+		.cmd = ATMELRD,
+		.set_args = IW_PRIV_TYPE_CHAR | REGDOMAINSZ,
+		.get_args = IW_PRIV_TYPE_NONE,
+		.name = "regdomain"
+	},
 };
 
-static const struct iw_handler_def	atmel_handler_def =
+static const struct iw_handler_def atmel_handler_def =
 {
 	.num_standard	= sizeof(atmel_handler)/sizeof(iw_handler),
-	.num_private	= sizeof(atmel_private_handler)/sizeof(iw_handler), 
-	.num_private_args = sizeof(atmel_private_args)/sizeof(struct iw_priv_args), 
+	.num_private	= sizeof(atmel_private_handler)/sizeof(iw_handler),
+	.num_private_args = sizeof(atmel_private_args)/sizeof(struct iw_priv_args),
 	.standard	= (iw_handler *) atmel_handler,
-	.private	= (iw_handler *) atmel_private_handler, 
+	.private	= (iw_handler *) atmel_private_handler,
 	.private_args	= (struct iw_priv_args *) atmel_private_args,
 	.get_wireless_stats = atmel_get_wireless_stats
 };
@@ -2419,13 +2436,13 @@ static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 	atmel_priv_ioctl com;
 	struct iwreq *wrq = (struct iwreq *) rq;
 	unsigned char *new_firmware;
-	char domain[REGDOMAINSZ+1];
+	char domain[REGDOMAINSZ + 1];
 
 	switch (cmd) {
 	case ATMELIDIFC:
-		wrq->u.param.value = ATMELMAGIC;		
+		wrq->u.param.value = ATMELMAGIC;
 		break;
-	
+
 	case ATMELFWL:
 		if (copy_from_user(&com, rq->ifr_data, sizeof(com))) {
 			rc = -EFAULT;
@@ -2449,7 +2466,7 @@ static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 		}
 
 		kfree(priv->firmware);
-		
+
 		priv->firmware = new_firmware;
 		priv->firmware_length = com.len;
 		strncpy(priv->firmware_id, com.id, 31);
@@ -2461,7 +2478,7 @@ static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 			rc = -EFAULT;
 			break;
 		}
-		
+
 		if (!capable(CAP_NET_ADMIN)) {
 			rc = -EPERM;
 			break;
@@ -2484,15 +2501,15 @@ static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 				rc = 0;
 			}
 		}
-		
+
 		if (rc == 0 &&  priv->station_state != STATION_STATE_DOWN)
 			rc = atmel_open(dev);
 		break;
-		
+
 	default:
 		rc = -EOPNOTSUPP;
 	}
-	
+
 	return rc;
 }
 
@@ -2503,17 +2520,17 @@ struct auth_body {
 	u8 el_id;
 	u8 chall_text_len;
 	u8 chall_text[253];
-}; 
+};
 
 static void atmel_enter_state(struct atmel_private *priv, int new_state)
 {
 	int old_state = priv->station_state;
-		
+
 	if (new_state == old_state)
 		return;
-	
+
 	priv->station_state = new_state;
-		
+
 	if (new_state == STATION_STATE_READY) {
 		netif_start_queue(priv->dev);
 		netif_carrier_on(priv->dev);
@@ -2540,7 +2557,7 @@ static void atmel_scan(struct atmel_private *priv, int specific_ssid)
 		u8 options;
 		u8 SSID_size;
 	} cmd;
-	
+
 	memset(cmd.BSSID, 0xff, 6);
 
 	if (priv->fast_scan) {
@@ -2554,17 +2571,17 @@ static void atmel_scan(struct atmel_private *priv, int specific_ssid)
 		cmd.min_channel_time = cpu_to_le16(10);
 		cmd.max_channel_time = cpu_to_le16(120);
 	}
-	
+
 	cmd.options = 0;
-	
+
 	if (!specific_ssid)
 		cmd.options |= SCAN_OPTIONS_SITE_SURVEY;
-	
-	cmd.channel = (priv->channel & 0x7f); 
+
+	cmd.channel = (priv->channel & 0x7f);
 	cmd.scan_type = SCAN_TYPE_ACTIVE;
-	cmd.BSS_type = cpu_to_le16(priv->operating_mode == IW_MODE_ADHOC ? 
+	cmd.BSS_type = cpu_to_le16(priv->operating_mode == IW_MODE_ADHOC ?
 		BSS_TYPE_AD_HOC : BSS_TYPE_INFRASTRUCTURE);
-	
+
 	atmel_send_command(priv, CMD_Scan, &cmd, sizeof(cmd));
 
 	/* This must come after all hardware access to avoid being messed up
@@ -2591,16 +2608,15 @@ static void join(struct atmel_private *priv, int type)
 	cmd.BSS_type = type;
 	cmd.timeout = cpu_to_le16(2000);
 
- 	atmel_send_command(priv, CMD_Join, &cmd, sizeof(cmd));
+	atmel_send_command(priv, CMD_Join, &cmd, sizeof(cmd));
 }
 
-
 static void start(struct atmel_private *priv, int type)
 {
 	struct {
 		u8 BSSID[6];
 		u8 SSID[MAX_SSID_LENGTH];
-		u8 BSS_type;                                
+		u8 BSS_type;
 		u8 channel;
 		u8 SSID_size;
 		u8 reserved[3];
@@ -2612,13 +2628,14 @@ static void start(struct atmel_private *priv, int type)
 	cmd.BSS_type = type;
 	cmd.channel = (priv->channel & 0x7f);
 
-	atmel_send_command(priv, CMD_Start, &cmd, sizeof(cmd)); 
+	atmel_send_command(priv, CMD_Start, &cmd, sizeof(cmd));
 }
 
-static void handle_beacon_probe(struct atmel_private *priv, u16 capability, u8 channel)
+static void handle_beacon_probe(struct atmel_private *priv, u16 capability,
+				u8 channel)
 {
 	int rejoin = 0;
-	int new = capability  & C80211_MGMT_CAPABILITY_ShortPreamble ? 
+	int new = capability  & C80211_MGMT_CAPABILITY_ShortPreamble ?
 		SHORT_PREAMBLE : LONG_PREAMBLE;
 
 	if (priv->preamble != new) {
@@ -2626,48 +2643,48 @@ static void handle_beacon_probe(struct atmel_private *priv, u16 capability, u8 c
 		rejoin = 1;
 		atmel_set_mib8(priv, Local_Mib_Type, LOCAL_MIB_PREAMBLE_TYPE, new);
 	}
-		
+
 	if (priv->channel != channel) {
 		priv->channel = channel;
 		rejoin = 1;
 		atmel_set_mib8(priv, Phy_Mib_Type, PHY_MIB_CHANNEL_POS, channel);
 	}
-	
+
 	if (rejoin) {
 		priv->station_is_associated = 0;
 		atmel_enter_state(priv, STATION_STATE_JOINNING);
-		
+
 		if (priv->operating_mode == IW_MODE_INFRA)
 			join(priv, BSS_TYPE_INFRASTRUCTURE);
-		else 
+		else
 			join(priv, BSS_TYPE_AD_HOC);
-	} 
+	}
 }
 
-
-static void send_authentication_request(struct atmel_private *priv, u16 system, u8 *challenge, int challenge_len)
+static void send_authentication_request(struct atmel_private *priv, u16 system,
+					u8 *challenge, int challenge_len)
 {
 	struct ieee80211_hdr_4addr header;
 	struct auth_body auth;
-	
-	header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH); 
-	header.duration_id	= cpu_to_le16(0x8000);	
+
+	header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH);
+	header.duration_id = cpu_to_le16(0x8000);
 	header.seq_ctl = 0;
 	memcpy(header.addr1, priv->CurrentBSSID, 6);
 	memcpy(header.addr2, priv->dev->dev_addr, 6);
 	memcpy(header.addr3, priv->CurrentBSSID, 6);
-	
-	if (priv->wep_is_on && priv->CurrentAuthentTransactionSeqNum != 1) 
+
+	if (priv->wep_is_on && priv->CurrentAuthentTransactionSeqNum != 1)
 		/* no WEP for authentication frames with TrSeqNo 1 */
                 header.frame_ctl |=  cpu_to_le16(IEEE80211_FCTL_PROTECTED);
-	
-	auth.alg = cpu_to_le16(system); 
+
+	auth.alg = cpu_to_le16(system);
 
 	auth.status = 0;
 	auth.trans_seq = cpu_to_le16(priv->CurrentAuthentTransactionSeqNum);
-	priv->ExpectedAuthentTransactionSeqNum = priv->CurrentAuthentTransactionSeqNum+1; 
+	priv->ExpectedAuthentTransactionSeqNum = priv->CurrentAuthentTransactionSeqNum+1;
 	priv->CurrentAuthentTransactionSeqNum += 2;
-	
+
 	if (challenge_len != 0)	{
 		auth.el_id = 16; /* challenge_text */
 		auth.chall_text_len = challenge_len;
@@ -2685,7 +2702,7 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc)
 	struct ieee80211_hdr_4addr header;
 	struct ass_req_format {
 		u16 capability;
-		u16 listen_interval; 
+		u16 listen_interval;
 		u8 ap[6]; /* nothing after here directly accessible */
 		u8 ssid_el_id;
 		u8 ssid_len;
@@ -2694,15 +2711,15 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc)
 		u8 sup_rates_len;
 		u8 rates[4];
 	} body;
-		
-	header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT | 
+
+	header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT |
 		(is_reassoc ? IEEE80211_STYPE_REASSOC_REQ : IEEE80211_STYPE_ASSOC_REQ));
 	header.duration_id = cpu_to_le16(0x8000);
 	header.seq_ctl = 0;
 
-	memcpy(header.addr1, priv->CurrentBSSID, 6); 
+	memcpy(header.addr1, priv->CurrentBSSID, 6);
 	memcpy(header.addr2, priv->dev->dev_addr, 6);
-	memcpy(header.addr3, priv->CurrentBSSID, 6); 
+	memcpy(header.addr3, priv->CurrentBSSID, 6);
 
 	body.capability = cpu_to_le16(C80211_MGMT_CAPABILITY_ESS);
 	if (priv->wep_is_on)
@@ -2711,18 +2728,18 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc)
 		body.capability |= cpu_to_le16(C80211_MGMT_CAPABILITY_ShortPreamble);
 
 	body.listen_interval = cpu_to_le16(priv->listen_interval * priv->beacon_period);
-	
+
 	/* current AP address - only in reassoc frame */
 	if (is_reassoc) {
-		memcpy(body.ap,  priv->CurrentBSSID, 6);
+		memcpy(body.ap, priv->CurrentBSSID, 6);
 		ssid_el_p = (u8 *)&body.ssid_el_id;
 		bodysize = 18 + priv->SSID_size;
 	} else {
 		ssid_el_p = (u8 *)&body.ap[0];
 		bodysize = 12 + priv->SSID_size;
 	}
-		
-	ssid_el_p[0]= C80211_MGMT_ElementID_SSID;
+
+	ssid_el_p[0] = C80211_MGMT_ElementID_SSID;
 	ssid_el_p[1] = priv->SSID_size;
 	memcpy(ssid_el_p + 2, priv->SSID, priv->SSID_size);
 	ssid_el_p[2 + priv->SSID_size] = C80211_MGMT_ElementID_SupportedRates;
@@ -2732,7 +2749,8 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc)
 	atmel_transmit_management_frame(priv, &header, (void *)&body, bodysize);
 }
 
-static int is_frame_from_current_bss(struct atmel_private *priv, struct ieee80211_hdr_4addr *header)
+static int is_frame_from_current_bss(struct atmel_private *priv,
+				     struct ieee80211_hdr_4addr *header)
 {
 	if (le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_FROMDS)
 		return memcmp(header->addr3, priv->CurrentBSSID, 6) == 0;
@@ -2745,29 +2763,29 @@ static int retrieve_bss(struct atmel_private *priv)
 	int i;
 	int max_rssi = -128;
 	int max_index = -1;
-	
+
 	if (priv->BSS_list_entries == 0)
 		return -1;
-			
+
 	if (priv->connect_to_any_BSS) {
-		/* Select a BSS with the max-RSSI but of the same type and of the same WEP mode
-		   and that it is not marked as 'bad' (i.e. we had previously failed to connect to
-		   this BSS with the settings that we currently use) */
+		/* Select a BSS with the max-RSSI but of the same type and of
+		   the same WEP mode and that it is not marked as 'bad' (i.e.
+		   we had previously failed to connect to this BSS with the
+		   settings that we currently use) */
 		priv->current_BSS = 0;
-		for(i=0; i<priv->BSS_list_entries; i++) { 
+		for (i = 0; i < priv->BSS_list_entries; i++) {
 			if (priv->operating_mode == priv->BSSinfo[i].BSStype &&
-			    ((!priv->wep_is_on && !priv->BSSinfo[i].UsingWEP) || 
+			    ((!priv->wep_is_on && !priv->BSSinfo[i].UsingWEP) ||
 			     (priv->wep_is_on && priv->BSSinfo[i].UsingWEP)) &&
 			    !(priv->BSSinfo[i].channel & 0x80)) {
 				max_rssi = priv->BSSinfo[i].RSSI;
 				priv->current_BSS = max_index = i;
 			}
-			
 		}
 		return max_index;
 	}
-		
-	for(i=0; i<priv->BSS_list_entries; i++) {
+
+	for (i = 0; i < priv->BSS_list_entries; i++) {
 		if (priv->SSID_size == priv->BSSinfo[i].SSIDsize &&
 		    memcmp(priv->SSID, priv->BSSinfo[i].SSID, priv->SSID_size) == 0 &&
 		    priv->operating_mode == priv->BSSinfo[i].BSStype &&
@@ -2781,19 +2799,19 @@ static int retrieve_bss(struct atmel_private *priv)
 	return max_index;
 }
 
-
-static void store_bss_info(struct atmel_private *priv, struct ieee80211_hdr_4addr *header,
-			   u16 capability, u16 beacon_period, u8 channel, u8 rssi, 
-			   u8 ssid_len, u8 *ssid, int is_beacon)
+static void store_bss_info(struct atmel_private *priv,
+			   struct ieee80211_hdr_4addr *header, u16 capability,
+			   u16 beacon_period, u8 channel, u8 rssi, u8 ssid_len,
+			   u8 *ssid, int is_beacon)
 {
 	u8 *bss = capability & C80211_MGMT_CAPABILITY_ESS ? header->addr2 : header->addr3;
 	int i, index;
-		
-	for (index = -1, i = 0; i < priv->BSS_list_entries; i++) 
-		if (memcmp(bss, priv->BSSinfo[i].BSSID, 6) == 0) 
+
+	for (index = -1, i = 0; i < priv->BSS_list_entries; i++)
+		if (memcmp(bss, priv->BSSinfo[i].BSSID, 6) == 0)
 			index = i;
 
-        /* If we process a probe and an entry from this BSS exists 
+        /* If we process a probe and an entry from this BSS exists
 	   we will update the BSS entry with the info from this BSS.
 	   If we process a beacon we will only update RSSI */
 
@@ -2820,8 +2838,8 @@ static void store_bss_info(struct atmel_private *priv, struct ieee80211_hdr_4add
 		priv->BSSinfo[index].BSStype = IW_MODE_ADHOC;
 	else if (capability & C80211_MGMT_CAPABILITY_ESS)
 		priv->BSSinfo[index].BSStype =IW_MODE_INFRA;
-	
-	priv->BSSinfo[index].preamble = capability  & C80211_MGMT_CAPABILITY_ShortPreamble ? 
+
+	priv->BSSinfo[index].preamble = capability & C80211_MGMT_CAPABILITY_ShortPreamble ?
 		SHORT_PREAMBLE : LONG_PREAMBLE;
 }
 
@@ -2831,8 +2849,8 @@ static void authenticate(struct atmel_private *priv, u16 frame_len)
 	u16 status = le16_to_cpu(auth->status);
 	u16 trans_seq_no = le16_to_cpu(auth->trans_seq);
 	u16 system = le16_to_cpu(auth->alg);
-	
-	if (status == C80211_MGMT_SC_Success && !priv->wep_is_on) { 
+
+	if (status == C80211_MGMT_SC_Success && !priv->wep_is_on) {
 		/* no WEP */
 		if (priv->station_was_associated) {
 			atmel_enter_state(priv, STATION_STATE_REASSOCIATING);
@@ -2842,20 +2860,20 @@ static void authenticate(struct atmel_private *priv, u16 frame_len)
 			atmel_enter_state(priv, STATION_STATE_ASSOCIATING);
 			send_association_request(priv, 0);
 			return;
-		} 
+		}
 	}
-		
-	if (status == C80211_MGMT_SC_Success && priv->wep_is_on) { 
+
+	if (status == C80211_MGMT_SC_Success && priv->wep_is_on) {
 		/* WEP */
 		if (trans_seq_no != priv->ExpectedAuthentTransactionSeqNum)
 			return;
-				
+
 		if (trans_seq_no == 0x0002 &&
 		    auth->el_id == C80211_MGMT_ElementID_ChallengeText) {
 			send_authentication_request(priv, system, auth->chall_text, auth->chall_text_len);
 			return;
 		}
-		
+
 		if (trans_seq_no == 0x0004) {
 			if(priv->station_was_associated) {
 				atmel_enter_state(priv, STATION_STATE_REASSOCIATING);
@@ -2865,10 +2883,10 @@ static void authenticate(struct atmel_private *priv, u16 frame_len)
 				atmel_enter_state(priv, STATION_STATE_ASSOCIATING);
 				send_association_request(priv, 0);
 				return;
-			} 
+			}
 		}
-	}			
-	
+	}
+
 	if (status == C80211_MGMT_SC_AuthAlgNotSupported) {
 		/* Do opensystem first, then try sharedkey */
 		if (system ==  C80211_MGMT_AAN_OPENSYSTEM) {
@@ -2876,17 +2894,16 @@ static void authenticate(struct atmel_private *priv, u16 frame_len)
 			send_authentication_request(priv, C80211_MGMT_AAN_SHAREDKEY, NULL, 0);
 		} else if (priv->connect_to_any_BSS) {
 			int bss_index;
-			
+
 			priv->BSSinfo[(int)(priv->current_BSS)].channel |= 0x80;
-			
+
 			if ((bss_index  = retrieve_bss(priv)) != -1) {
 				atmel_join_bss(priv, bss_index);
 				return;
 			}
 		}
 	}
-	
-	
+
 	priv->AuthenticationRequestRetryCnt = 0;
 	atmel_enter_state(priv,  STATION_STATE_MGMT_ERROR);
 	priv->station_is_associated = 0;
@@ -2902,38 +2919,44 @@ static void associate(struct atmel_private *priv, u16 frame_len, u16 subtype)
 		u8 length;
 		u8 rates[4];
 	} *ass_resp = (struct ass_resp_format *)priv->rx_buf;
-	
-       	u16 status = le16_to_cpu(ass_resp->status);
+
+	u16 status = le16_to_cpu(ass_resp->status);
 	u16 ass_id = le16_to_cpu(ass_resp->ass_id);
-   	u16 rates_len = ass_resp->length > 4 ? 4 : ass_resp->length;
-	
+	u16 rates_len = ass_resp->length > 4 ? 4 : ass_resp->length;
+
 	if (frame_len < 8 + rates_len)
 		return;
-	
+
 	if (status == C80211_MGMT_SC_Success) {
 		if (subtype == C80211_SUBTYPE_MGMT_ASS_RESPONSE)
 			priv->AssociationRequestRetryCnt = 0;
 		else
 			priv->ReAssociationRequestRetryCnt = 0;
-		
-		atmel_set_mib16(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_STATION_ID_POS, ass_id & 0x3fff);
-		atmel_set_mib(priv, Phy_Mib_Type, PHY_MIB_RATE_SET_POS, ass_resp->rates, rates_len);
+
+		atmel_set_mib16(priv, Mac_Mgmt_Mib_Type,
+				MAC_MGMT_MIB_STATION_ID_POS, ass_id & 0x3fff);
+		atmel_set_mib(priv, Phy_Mib_Type,
+			      PHY_MIB_RATE_SET_POS, ass_resp->rates, rates_len);
 		if (priv->power_mode == 0) {
 			priv->listen_interval = 1;
-			atmel_set_mib8(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_PS_MODE_POS,  ACTIVE_MODE);
-			atmel_set_mib16(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_LISTEN_INTERVAL_POS, 1);
+			atmel_set_mib8(priv, Mac_Mgmt_Mib_Type,
+				       MAC_MGMT_MIB_PS_MODE_POS, ACTIVE_MODE);
+			atmel_set_mib16(priv, Mac_Mgmt_Mib_Type,
+					MAC_MGMT_MIB_LISTEN_INTERVAL_POS, 1);
 		} else {
 			priv->listen_interval = 2;
-			atmel_set_mib8(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_PS_MODE_POS,  PS_MODE);
-			atmel_set_mib16(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_LISTEN_INTERVAL_POS, 2);
+			atmel_set_mib8(priv, Mac_Mgmt_Mib_Type,
+				       MAC_MGMT_MIB_PS_MODE_POS,  PS_MODE);
+			atmel_set_mib16(priv, Mac_Mgmt_Mib_Type,
+					MAC_MGMT_MIB_LISTEN_INTERVAL_POS, 2);
 		}
-		
+
 		priv->station_is_associated = 1;
 		priv->station_was_associated = 1;
 		atmel_enter_state(priv, STATION_STATE_READY);
 		return;
 	}
-	
+
 	if (subtype == C80211_SUBTYPE_MGMT_ASS_RESPONSE &&
 	    status != C80211_MGMT_SC_AssDeniedBSSRate &&
 	    status != C80211_MGMT_SC_SupportCapabilities &&
@@ -2943,7 +2966,7 @@ static void associate(struct atmel_private *priv, u16 frame_len, u16 subtype)
 		send_association_request(priv, 0);
 		return;
 	}
-		
+
 	if (subtype == C80211_SUBTYPE_MGMT_REASS_RESPONSE &&
 	    status != C80211_MGMT_SC_AssDeniedBSSRate &&
 	    status != C80211_MGMT_SC_SupportCapabilities &&
@@ -2953,17 +2976,16 @@ static void associate(struct atmel_private *priv, u16 frame_len, u16 subtype)
 		send_association_request(priv, 1);
 		return;
 	}
-	
+
 	atmel_enter_state(priv,  STATION_STATE_MGMT_ERROR);
 	priv->station_is_associated = 0;
-	
-	if(priv->connect_to_any_BSS) {
+
+	if (priv->connect_to_any_BSS) {
 		int bss_index;
 		priv->BSSinfo[(int)(priv->current_BSS)].channel |= 0x80;
-		
-		if ((bss_index = retrieve_bss(priv)) != -1) 
+
+		if ((bss_index = retrieve_bss(priv)) != -1)
 			atmel_join_bss(priv, bss_index);
-		
 	}
 }
 
@@ -2977,7 +2999,7 @@ void atmel_join_bss(struct atmel_private *priv, int bss_index)
 	/* The WPA stuff cares about the current AP address */
 	if (priv->use_wpa)
 		build_wpa_mib(priv);
-	
+
 	/* When switching to AdHoc turn OFF Power Save if needed */
 
 	if (bss->BSStype == IW_MODE_ADHOC &&
@@ -2985,25 +3007,28 @@ void atmel_join_bss(struct atmel_private *priv, int bss_index)
 	    priv->power_mode) {
 		priv->power_mode = 0;
 		priv->listen_interval = 1;
-		atmel_set_mib8(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_PS_MODE_POS,  ACTIVE_MODE);
-		atmel_set_mib16(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_LISTEN_INTERVAL_POS, 1);
+		atmel_set_mib8(priv, Mac_Mgmt_Mib_Type,
+			       MAC_MGMT_MIB_PS_MODE_POS,  ACTIVE_MODE);
+		atmel_set_mib16(priv, Mac_Mgmt_Mib_Type,
+				MAC_MGMT_MIB_LISTEN_INTERVAL_POS, 1);
 	}
-		
+
 	priv->operating_mode = bss->BSStype;
-	priv->channel = bss->channel & 0x7f; 	
+	priv->channel = bss->channel & 0x7f;
 	priv->beacon_period = bss->beacon_period;
-	
+
 	if (priv->preamble != bss->preamble) {
 		priv->preamble = bss->preamble;
-		atmel_set_mib8(priv, Local_Mib_Type, LOCAL_MIB_PREAMBLE_TYPE, bss->preamble);
+		atmel_set_mib8(priv, Local_Mib_Type,
+			       LOCAL_MIB_PREAMBLE_TYPE, bss->preamble);
 	}
-	
+
 	if (!priv->wep_is_on && bss->UsingWEP) {
 		atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
 		priv->station_is_associated = 0;
 		return;
 	}
-		
+
 	if (priv->wep_is_on && !bss->UsingWEP) {
 		atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
 		priv->station_is_associated = 0;
@@ -3011,30 +3036,28 @@ void atmel_join_bss(struct atmel_private *priv, int bss_index)
 	}
 
 	atmel_enter_state(priv, STATION_STATE_JOINNING);
-	
+
 	if (priv->operating_mode == IW_MODE_INFRA)
 		join(priv, BSS_TYPE_INFRASTRUCTURE);
-	else 
+	else
 		join(priv, BSS_TYPE_AD_HOC);
 }
 
-
 static void restart_search(struct atmel_private *priv)
 {
 	int bss_index;
-	
+
 	if (!priv->connect_to_any_BSS) {
 		atmel_scan(priv, 1);
 	} else {
 		priv->BSSinfo[(int)(priv->current_BSS)].channel |= 0x80;
-		
-		if ((bss_index = retrieve_bss(priv)) != -1) 
+
+		if ((bss_index = retrieve_bss(priv)) != -1)
 			atmel_join_bss(priv, bss_index);
 		else
 			atmel_scan(priv, 0);
-		
-	} 
-}	
+	}
+}
 
 static void smooth_rssi(struct atmel_private *priv, u8 rssi)
 {
@@ -3050,21 +3073,21 @@ static void smooth_rssi(struct atmel_private *priv, u8 rssi)
 	}
 
 	rssi = rssi * 100 / max_rssi;
-	if((rssi + old) % 2)
-		priv->wstats.qual.level =  ((rssi + old)/2) + 1;
+	if ((rssi + old) % 2)
+		priv->wstats.qual.level = (rssi + old) / 2 + 1;
 	else
-		priv->wstats.qual.level =  ((rssi + old)/2);		
+		priv->wstats.qual.level = (rssi + old) / 2;
 	priv->wstats.qual.updated |= IW_QUAL_LEVEL_UPDATED;
 	priv->wstats.qual.updated &= ~IW_QUAL_LEVEL_INVALID;
 }
 
 static void atmel_smooth_qual(struct atmel_private *priv)
 {
-	unsigned long time_diff = (jiffies - priv->last_qual)/HZ;
+	unsigned long time_diff = (jiffies - priv->last_qual) / HZ;
 	while (time_diff--) {
 		priv->last_qual += HZ;
-		priv->wstats.qual.qual = priv->wstats.qual.qual/2;
-		priv->wstats.qual.qual += 
+		priv->wstats.qual.qual = priv->wstats.qual.qual / 2;
+		priv->wstats.qual.qual +=
 			priv->beacons_this_sec * priv->beacon_period * (priv->wstats.qual.level + 100) / 4000;
 		priv->beacons_this_sec = 0;
 	}
@@ -3073,15 +3096,17 @@ static void atmel_smooth_qual(struct atmel_private *priv)
 }
 
 /* deals with incoming managment frames. */
-static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_hdr_4addr *header, 
-		      u16 frame_len, u8 rssi)
+static void atmel_management_frame(struct atmel_private *priv,
+				   struct ieee80211_hdr_4addr *header,
+				   u16 frame_len, u8 rssi)
 {
 	u16 subtype;
-	
-	switch (subtype = le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_STYPE) {
-	case C80211_SUBTYPE_MGMT_BEACON :
+
+	subtype = le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_STYPE;
+	switch (subtype) {
+	case C80211_SUBTYPE_MGMT_BEACON:
 	case C80211_SUBTYPE_MGMT_ProbeResponse:
-		
+
 		/* beacon frame has multiple variable-length fields -
 		   never let an engineer loose with a data structure design. */
 		{
@@ -3099,7 +3124,7 @@ static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_
 				u8 ds_length;
 				/* ds here */
 			} *beacon = (struct beacon_format *)priv->rx_buf;
-			
+
 			u8 channel, rates_length, ssid_length;
 			u64 timestamp = le64_to_cpu(beacon->timestamp);
 			u16 beacon_interval = le16_to_cpu(beacon->interval);
@@ -3107,7 +3132,7 @@ static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_
 			u8 *beaconp = priv->rx_buf;
 			ssid_length = beacon->ssid_length;
 			/* this blows chunks. */
-			if (frame_len < 14 || frame_len < ssid_length + 15) 
+			if (frame_len < 14 || frame_len < ssid_length + 15)
 				return;
 			rates_length = beaconp[beacon->ssid_length + 15];
 			if (frame_len < ssid_length + rates_length + 18)
@@ -3115,10 +3140,10 @@ static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_
 			if (ssid_length >  MAX_SSID_LENGTH)
 				return;
 			channel = beaconp[ssid_length + rates_length + 18];
-		       
+
 			if (priv->station_state == STATION_STATE_READY) {
 				smooth_rssi(priv, rssi);
-				if (is_frame_from_current_bss(priv, header)) { 
+				if (is_frame_from_current_bss(priv, header)) {
 					priv->beacons_this_sec++;
 					atmel_smooth_qual(priv);
 					if (priv->last_beacon_timestamp) {
@@ -3132,41 +3157,43 @@ static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_
 					handle_beacon_probe(priv, capability, channel);
 				}
 			}
-			
-			if (priv->station_state == STATION_STATE_SCANNING ) 
-				store_bss_info(priv, header, capability, beacon_interval, channel,
-					       rssi, ssid_length, &beacon->rates_el_id,
-					       subtype == C80211_SUBTYPE_MGMT_BEACON) ;
+
+			if (priv->station_state == STATION_STATE_SCANNING)
+				store_bss_info(priv, header, capability,
+					       beacon_interval, channel, rssi,
+					       ssid_length,
+					       &beacon->rates_el_id,
+					       subtype == C80211_SUBTYPE_MGMT_BEACON);
 		}
 		break;
-		
+
 	case C80211_SUBTYPE_MGMT_Authentication:
 
 		if (priv->station_state == STATION_STATE_AUTHENTICATING)
 			authenticate(priv, frame_len);
-	
+
 		break;
-		
+
 	case C80211_SUBTYPE_MGMT_ASS_RESPONSE:
 	case C80211_SUBTYPE_MGMT_REASS_RESPONSE:
-		
-		if (priv->station_state == STATION_STATE_ASSOCIATING || 
+
+		if (priv->station_state == STATION_STATE_ASSOCIATING ||
 		    priv->station_state == STATION_STATE_REASSOCIATING)
 			associate(priv, frame_len, subtype);
-		
+
 		break;
 
 	case C80211_SUBTYPE_MGMT_DISASSOSIATION:
-		if (priv->station_is_associated && 
-		    priv->operating_mode == IW_MODE_INFRA && 
+		if (priv->station_is_associated &&
+		    priv->operating_mode == IW_MODE_INFRA &&
 		    is_frame_from_current_bss(priv, header)) {
 			priv->station_was_associated = 0;
 			priv->station_is_associated = 0;
-			
+
 			atmel_enter_state(priv, STATION_STATE_JOINNING);
 			join(priv, BSS_TYPE_INFRASTRUCTURE);
 		}
-		
+
 		break;
 
 	case C80211_SUBTYPE_MGMT_Deauthentication:
@@ -3177,7 +3204,7 @@ static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_
 			atmel_enter_state(priv, STATION_STATE_JOINNING);
 			join(priv, BSS_TYPE_INFRASTRUCTURE);
 		}
-		
+
 		break;
 	}
 }
@@ -3185,76 +3212,73 @@ static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_
 /* run when timer expires */
 static void atmel_management_timer(u_long a)
 {
-  struct net_device *dev = (struct net_device *) a;
-  struct atmel_private *priv = netdev_priv(dev);
-  unsigned long flags;
-  
-  /* Check if the card has been yanked. */
-  if (priv->card && priv->present_callback && 
-      !(*priv->present_callback)(priv->card))
-	  return;
-  
-  spin_lock_irqsave(&priv->irqlock, flags);
-
-  switch (priv->station_state) {
-	  
-  case STATION_STATE_AUTHENTICATING:
-	  if (priv->AuthenticationRequestRetryCnt >= MAX_AUTHENTICATION_RETRIES) {
-		  atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
-		  priv->station_is_associated = 0;
-		  priv->AuthenticationRequestRetryCnt = 0;
-		  restart_search(priv);
-	  } else {
-		  priv->AuthenticationRequestRetryCnt++;
-		  priv->CurrentAuthentTransactionSeqNum = 0x0001;
-		  mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
-		  send_authentication_request(priv, C80211_MGMT_AAN_OPENSYSTEM, NULL, 0);
-	  }
-	  
-	  break;
+	struct net_device *dev = (struct net_device *) a;
+	struct atmel_private *priv = netdev_priv(dev);
+	unsigned long flags;
 
-  case STATION_STATE_ASSOCIATING:
-	  if (priv->AssociationRequestRetryCnt == MAX_ASSOCIATION_RETRIES) {
-		  atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
-		  priv->station_is_associated = 0;
-		  priv->AssociationRequestRetryCnt = 0;
-		  restart_search(priv);
-	  } else {
-		  priv->AssociationRequestRetryCnt++;
-		  mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
-		  send_association_request(priv, 0);
-	  }
+	/* Check if the card has been yanked. */
+	if (priv->card && priv->present_callback &&
+		!(*priv->present_callback)(priv->card))
+		return;
 
-	  break;
-		  
-  case STATION_STATE_REASSOCIATING:	
-	  if (priv->ReAssociationRequestRetryCnt == MAX_ASSOCIATION_RETRIES) {
-		  atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
-		  priv->station_is_associated = 0;
-		  priv->ReAssociationRequestRetryCnt = 0;
-		  restart_search(priv);
-	  } else {
-		  priv->ReAssociationRequestRetryCnt++;
-		  mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
-		  send_association_request(priv, 1);
-	  }
+	spin_lock_irqsave(&priv->irqlock, flags);
+
+	switch (priv->station_state) {
 
+	case STATION_STATE_AUTHENTICATING:
+		if (priv->AuthenticationRequestRetryCnt >= MAX_AUTHENTICATION_RETRIES) {
+			atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
+			priv->station_is_associated = 0;
+			priv->AuthenticationRequestRetryCnt = 0;
+			restart_search(priv);
+		} else {
+			priv->AuthenticationRequestRetryCnt++;
+			priv->CurrentAuthentTransactionSeqNum = 0x0001;
+			mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
+			send_authentication_request(priv, C80211_MGMT_AAN_OPENSYSTEM, NULL, 0);
+	  }
 	  break;
-  
-  default:
+
+	case STATION_STATE_ASSOCIATING:
+		if (priv->AssociationRequestRetryCnt == MAX_ASSOCIATION_RETRIES) {
+			atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
+			priv->station_is_associated = 0;
+			priv->AssociationRequestRetryCnt = 0;
+			restart_search(priv);
+		} else {
+			priv->AssociationRequestRetryCnt++;
+			mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
+			send_association_request(priv, 0);
+		}
 	  break;
-  }
-  
-  spin_unlock_irqrestore(&priv->irqlock, flags);
+
+	case STATION_STATE_REASSOCIATING:
+		if (priv->ReAssociationRequestRetryCnt == MAX_ASSOCIATION_RETRIES) {
+			atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
+			priv->station_is_associated = 0;
+			priv->ReAssociationRequestRetryCnt = 0;
+			restart_search(priv);
+		} else {
+			priv->ReAssociationRequestRetryCnt++;
+			mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
+			send_association_request(priv, 1);
+		}
+		break;
+
+	default:
+		break;
+	}
+
+	spin_unlock_irqrestore(&priv->irqlock, flags);
 }
-  
+
 static void atmel_command_irq(struct atmel_private *priv)
 {
 	u8 status = atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_STATUS_OFFSET));
 	u8 command = atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_COMMAND_OFFSET));
 	int fast_scan;
-	
-	if (status == CMD_STATUS_IDLE || 
+
+	if (status == CMD_STATUS_IDLE ||
 	    status == CMD_STATUS_IN_PROGRESS)
 		return;
 
@@ -3266,20 +3290,20 @@ static void atmel_command_irq(struct atmel_private *priv)
 			atmel_get_mib(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_CUR_BSSID_POS,
 				      (u8 *)priv->CurrentBSSID, 6);
 			atmel_enter_state(priv, STATION_STATE_READY);
-		}			
+		}
 		break;
-		
+
 	case CMD_Scan:
 		fast_scan = priv->fast_scan;
 		priv->fast_scan = 0;
-		
+
 		if (status != CMD_STATUS_COMPLETE) {
 			atmel_scan(priv, 1);
 		} else {
 			int bss_index = retrieve_bss(priv);
 			if (bss_index != -1) {
 				atmel_join_bss(priv, bss_index);
-			} else if (priv->operating_mode == IW_MODE_ADHOC && 
+			} else if (priv->operating_mode == IW_MODE_ADHOC &&
 				   priv->SSID_size != 0) {
 				start(priv, BSS_TYPE_AD_HOC);
 			} else {
@@ -3289,16 +3313,16 @@ static void atmel_command_irq(struct atmel_private *priv)
 			priv->site_survey_state = SITE_SURVEY_COMPLETED;
 		}
 		break;
-		
+
 	case CMD_SiteSurvey:
 		priv->fast_scan = 0;
-		
+
 		if (status != CMD_STATUS_COMPLETE)
 			return;
-		
+
 		priv->site_survey_state = SITE_SURVEY_COMPLETED;
 		if (priv->station_is_associated) {
-			atmel_enter_state(priv, STATION_STATE_READY);				
+			atmel_enter_state(priv, STATION_STATE_READY);
 		} else {
 			atmel_scan(priv, 1);
 		}
@@ -3312,16 +3336,15 @@ static void atmel_command_irq(struct atmel_private *priv)
 			} else {
 				priv->AuthenticationRequestRetryCnt = 0;
 				atmel_enter_state(priv, STATION_STATE_AUTHENTICATING);
-				
+
 				mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
 				priv->CurrentAuthentTransactionSeqNum = 0x0001;
 				send_authentication_request(priv, C80211_MGMT_AAN_SHAREDKEY, NULL, 0);
 			}
 			return;
 		}
-		
+
 		atmel_scan(priv, 1);
-		
 	}
 }
 
@@ -3333,20 +3356,20 @@ static int atmel_wakeup_firmware(struct atmel_private *priv)
 
 	if (priv->card_type == CARD_TYPE_SPI_FLASH)
 		atmel_set_gcr(priv->dev, GCR_REMAP);
-	
+
 	/* wake up on-board processor */
 	atmel_clear_gcr(priv->dev, 0x0040);
 	atmel_write16(priv->dev, BSR, BSS_SRAM);
-	
+
 	if (priv->card_type == CARD_TYPE_SPI_FLASH)
 		mdelay(100);
 
 	/* and wait for it */
-	for (i =  LOOP_RETRY_LIMIT; i; i--) {
+	for (i = LOOP_RETRY_LIMIT; i; i--) {
 		mr1 = atmel_read16(priv->dev, MR1);
 		mr3 = atmel_read16(priv->dev, MR3);
-		
-		if (mr3 & MAC_BOOT_COMPLETE) 
+
+		if (mr3 & MAC_BOOT_COMPLETE)
 			break;
 		if (mr1 & MAC_BOOT_COMPLETE &&
 		    priv->bus_type == BUS_TYPE_PCCARD)
@@ -3357,35 +3380,36 @@ static int atmel_wakeup_firmware(struct atmel_private *priv)
 		printk(KERN_ALERT "%s: MAC failed to boot.\n", priv->dev->name);
 		return 0;
 	}
-		
+
 	if ((priv->host_info_base = atmel_read16(priv->dev, MR2)) == 0xffff) {
 		printk(KERN_ALERT "%s: card missing.\n", priv->dev->name);
 		return 0;
 	}
-	
-	/* now check for completion of MAC initialization through  
-	   the FunCtrl field of the IFACE, poll MR1 to detect completion of	  
-	   MAC initialization, check completion status, set interrupt mask,  
-	   enables interrupts and calls Tx and Rx initialization functions */  
-	
+
+	/* now check for completion of MAC initialization through
+	   the FunCtrl field of the IFACE, poll MR1 to detect completion of
+	   MAC initialization, check completion status, set interrupt mask,
+	   enables interrupts and calls Tx and Rx initialization functions */
+
 	atmel_wmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET), FUNC_CTRL_INIT_COMPLETE);
-	
-	for (i =  LOOP_RETRY_LIMIT; i; i--) {
+
+	for (i = LOOP_RETRY_LIMIT; i; i--) {
 		mr1 = atmel_read16(priv->dev, MR1);
 		mr3 = atmel_read16(priv->dev, MR3);
-		
-		if (mr3 & MAC_INIT_COMPLETE) 
+
+		if (mr3 & MAC_INIT_COMPLETE)
 			break;
 		if (mr1 & MAC_INIT_COMPLETE &&
 		    priv->bus_type == BUS_TYPE_PCCARD)
 			break;
 	}
-	
+
 	if (i == 0) {
-		printk(KERN_ALERT "%s: MAC failed to initialise.\n", priv->dev->name);
+		printk(KERN_ALERT "%s: MAC failed to initialise.\n",
+				priv->dev->name);
 		return 0;
 	}
-	
+
 	/* Check for MAC_INIT_OK only on the register that the MAC_INIT_OK was set */
 	if ((mr3 & MAC_INIT_COMPLETE) &&
 	    !(atmel_read16(priv->dev, MR3) & MAC_INIT_OK)) {
@@ -3398,9 +3422,9 @@ static int atmel_wakeup_firmware(struct atmel_private *priv)
 		return 0;
 	}
 
-	atmel_copy_to_host(priv->dev, (unsigned char *)iface, 
+	atmel_copy_to_host(priv->dev, (unsigned char *)iface,
 			   priv->host_info_base, sizeof(*iface));
-        
+
 	iface->tx_buff_pos = le16_to_cpu(iface->tx_buff_pos);
 	iface->tx_buff_size = le16_to_cpu(iface->tx_buff_size);
 	iface->tx_desc_pos = le16_to_cpu(iface->tx_desc_pos);
@@ -3424,16 +3448,16 @@ static int probe_atmel_card(struct net_device *dev)
 {
 	int rc = 0;
 	struct atmel_private *priv = netdev_priv(dev);
-	 
+
 	/* reset pccard */
-	if (priv->bus_type == BUS_TYPE_PCCARD) 
+	if (priv->bus_type == BUS_TYPE_PCCARD)
 		atmel_write16(dev, GCR, 0x0060);
-	
+
 	atmel_write16(dev, GCR, 0x0040);
 	mdelay(500);
-	
+
 	if (atmel_read16(dev, MR2) == 0) {
-		/* No stored firmware so load a small stub which just 
+		/* No stored firmware so load a small stub which just
 		   tells us the MAC address */
 		int i;
 		priv->card_type = CARD_TYPE_EEPROM;
@@ -3442,7 +3466,7 @@ static int probe_atmel_card(struct net_device *dev)
 		atmel_set_gcr(dev, GCR_REMAP);
 		atmel_clear_gcr(priv->dev, 0x0040);
 		atmel_write16(dev, BSR, BSS_SRAM);
-		for (i =  LOOP_RETRY_LIMIT; i; i--) 
+		for (i = LOOP_RETRY_LIMIT; i; i--)
 			if (atmel_read16(dev, MR3) & MAC_BOOT_COMPLETE)
 				break;
 		if (i == 0) {
@@ -3451,7 +3475,7 @@ static int probe_atmel_card(struct net_device *dev)
 			atmel_copy_to_host(dev, dev->dev_addr, atmel_read16(dev, MR2), 6);
 			/* got address, now squash it again until the network
 			   interface is opened */
-			if (priv->bus_type == BUS_TYPE_PCCARD) 
+			if (priv->bus_type == BUS_TYPE_PCCARD)
 				atmel_write16(dev, GCR, 0x0060);
 			atmel_write16(dev, GCR, 0x0040);
 			rc = 1;
@@ -3459,7 +3483,7 @@ static int probe_atmel_card(struct net_device *dev)
 	} else if (atmel_read16(dev, MR4) == 0) {
 		/* Mac address easy in this case. */
 		priv->card_type = CARD_TYPE_PARALLEL_FLASH;
-		atmel_write16(dev,  BSR, 1);	
+		atmel_write16(dev,  BSR, 1);
 		atmel_copy_to_host(dev, dev->dev_addr, 0xc000, 6);
 		atmel_write16(dev,  BSR, 0x200);
 		rc = 1;
@@ -3469,16 +3493,16 @@ static int probe_atmel_card(struct net_device *dev)
 		priv->card_type = CARD_TYPE_SPI_FLASH;
 		if (atmel_wakeup_firmware(priv)) {
 			atmel_get_mib(priv, Mac_Address_Mib_Type, 0, dev->dev_addr, 6);
-			
+
 			/* got address, now squash it again until the network
 			   interface is opened */
-			if (priv->bus_type == BUS_TYPE_PCCARD) 
+			if (priv->bus_type == BUS_TYPE_PCCARD)
 				atmel_write16(dev, GCR, 0x0060);
 			atmel_write16(dev, GCR, 0x0040);
 			rc = 1;
 		}
 	}
-	
+
 	if (rc) {
 		if (dev->dev_addr[0] == 0xFF) {
 			u8 default_mac[] = {0x00,0x04, 0x25, 0x00, 0x00, 0x00};
@@ -3486,27 +3510,27 @@ static int probe_atmel_card(struct net_device *dev)
 			memcpy(dev->dev_addr, default_mac, 6);
 		}
 	}
-	
+
 	return rc;
 }
 
-static void build_wep_mib(struct atmel_private *priv)
 /* Move the encyption information on the MIB structure.
    This routine is for the pre-WPA firmware: later firmware has
    a different format MIB and a different routine. */
+static void build_wep_mib(struct atmel_private *priv)
 {
 	struct { /* NB this is matched to the hardware, don't change. */
-		u8 wep_is_on;                 
+		u8 wep_is_on;
 		u8 default_key; /* 0..3 */
 		u8 reserved;
 		u8 exclude_unencrypted;
-		
+
 		u32 WEPICV_error_count;
 		u32 WEP_excluded_count;
-		
+
 		u8 wep_keys[MAX_ENCRYPTION_KEYS][13];
- 		u8 encryption_level; /* 0, 1, 2 */
-		u8 reserved2[3]; 
+		u8 encryption_level; /* 0, 1, 2 */
+		u8 reserved2[3];
 	} mib;
 	int i;
 
@@ -3515,54 +3539,55 @@ static void build_wep_mib(struct atmel_private *priv)
 		if (priv->wep_key_len[priv->default_key] > 5)
 			mib.encryption_level = 2;
 		else
-			mib.encryption_level = 1;	
+			mib.encryption_level = 1;
 	} else {
 		mib.encryption_level = 0;
 	}
 
 	mib.default_key = priv->default_key;
 	mib.exclude_unencrypted = priv->exclude_unencrypted;
-	
-	for(i = 0; i < MAX_ENCRYPTION_KEYS;  i++)
+
+	for (i = 0; i < MAX_ENCRYPTION_KEYS; i++)
 		memcpy(mib.wep_keys[i], priv->wep_keys[i], 13);
-		
+
 	atmel_set_mib(priv, Mac_Wep_Mib_Type, 0, (u8 *)&mib, sizeof(mib));
 }
 
 static void build_wpa_mib(struct atmel_private *priv)
 {
-	/* This is for the later (WPA enabled) firmware. */	   
+	/* This is for the later (WPA enabled) firmware. */
 
 	struct { /* NB this is matched to the hardware, don't change. */
 		u8 cipher_default_key_value[MAX_ENCRYPTION_KEYS][MAX_ENCRYPTION_KEY_SIZE];
 		u8 receiver_address[6];
-		u8 wep_is_on;                 
+		u8 wep_is_on;
 		u8 default_key; /* 0..3 */
 		u8 group_key;
 		u8 exclude_unencrypted;
 		u8 encryption_type;
 		u8 reserved;
-		
+
 		u32 WEPICV_error_count;
 		u32 WEP_excluded_count;
-		
+
 		u8 key_RSC[4][8];
 	} mib;
-	
+
 	int i;
 
 	mib.wep_is_on = priv->wep_is_on;
 	mib.exclude_unencrypted = priv->exclude_unencrypted;
 	memcpy(mib.receiver_address, priv->CurrentBSSID, 6);
-	
+
 	/* zero all the keys before adding in valid ones. */
 	memset(mib.cipher_default_key_value, 0, sizeof(mib.cipher_default_key_value));
-	
+
 	if (priv->wep_is_on) {
-		/* There's a comment in the Atmel code to the effect that this is only valid
-		   when still using WEP, it may need to be set to something to use WPA */
+		/* There's a comment in the Atmel code to the effect that this
+		   is only valid when still using WEP, it may need to be set to
+		   something to use WPA */
 		memset(mib.key_RSC, 0, sizeof(mib.key_RSC));
-		
+
 		mib.default_key = mib.group_key = 255;
 		for (i = 0; i < MAX_ENCRYPTION_KEYS; i++) {
 			if (priv->wep_key_len[i] > 0) {
@@ -3570,12 +3595,12 @@ static void build_wpa_mib(struct atmel_private *priv)
 				if (i == priv->default_key) {
 					mib.default_key = i;
 					mib.cipher_default_key_value[i][MAX_ENCRYPTION_KEY_SIZE-1] = 7;
-					mib.cipher_default_key_value[i][MAX_ENCRYPTION_KEY_SIZE-2] = priv->pairwise_cipher_suite; 
+					mib.cipher_default_key_value[i][MAX_ENCRYPTION_KEY_SIZE-2] = priv->pairwise_cipher_suite;
 				} else {
 					mib.group_key = i;
 					priv->group_cipher_suite = priv->pairwise_cipher_suite;
 				        mib.cipher_default_key_value[i][MAX_ENCRYPTION_KEY_SIZE-1] = 1;
-					mib.cipher_default_key_value[i][MAX_ENCRYPTION_KEY_SIZE-2] = priv->group_cipher_suite;	
+					mib.cipher_default_key_value[i][MAX_ENCRYPTION_KEY_SIZE-2] = priv->group_cipher_suite;
 				}
 			}
 		}
@@ -3583,47 +3608,47 @@ static void build_wpa_mib(struct atmel_private *priv)
 			mib.default_key = mib.group_key != 255 ? mib.group_key : 0;
 		if (mib.group_key == 255)
 			mib.group_key = mib.default_key;
-		
+
 	}
-	
+
 	atmel_set_mib(priv, Mac_Wep_Mib_Type, 0, (u8 *)&mib, sizeof(mib));
 }
-					
-static int reset_atmel_card(struct net_device *dev) 
+
+static int reset_atmel_card(struct net_device *dev)
 {
 	/* do everything necessary to wake up the hardware, including
 	   waiting for the lightning strike and throwing the knife switch....
 
-	   set all the Mib values which matter in the card to match 
+	   set all the Mib values which matter in the card to match
 	   their settings in the atmel_private structure. Some of these
 	   can be altered on the fly, but many (WEP, infrastucture or ad-hoc)
 	   can only be changed by tearing down the world and coming back through
 	   here.
 
-	   This routine is also responsible for initialising some 
-	   hardware-specific fields in the atmel_private structure, 
+	   This routine is also responsible for initialising some
+	   hardware-specific fields in the atmel_private structure,
 	   including a copy of the firmware's hostinfo stucture
 	   which is the route into the rest of the firmare datastructures. */
 
 	struct atmel_private *priv = netdev_priv(dev);
 	u8 configuration;
-	
+
 	/* data to add to the firmware names, in priority order
 	   this implemenents firmware versioning */
-	
+
 	static char *firmware_modifier[] = {
 		"-wpa",
 		"",
 		NULL
 	};
-		
+
 	/* reset pccard */
-	if (priv->bus_type == BUS_TYPE_PCCARD) 
+	if (priv->bus_type == BUS_TYPE_PCCARD)
 		atmel_write16(priv->dev, GCR, 0x0060);
-		
+
 	/* stop card , disable interrupts */
 	atmel_write16(priv->dev, GCR, 0x0040);
-		
+
 	if (priv->card_type == CARD_TYPE_EEPROM) {
 		/* copy in firmware if needed */
 		const struct firmware *fw_entry = NULL;
@@ -3636,13 +3661,13 @@ static int reset_atmel_card(struct net_device *dev)
 					       "%s: card type is unknown: assuming at76c502 firmware is OK.\n",
 					       dev->name);
 					printk(KERN_INFO
-					       "%s: if not, use the firmware= module parameter.\n", 
+					       "%s: if not, use the firmware= module parameter.\n",
 					       dev->name);
 					strcpy(priv->firmware_id, "atmel_at76c502.bin");
 				}
 				if (request_firmware(&fw_entry, priv->firmware_id, priv->sys_dev) != 0) {
-					printk(KERN_ALERT 
-					       "%s: firmware %s is missing, cannot continue.\n", 
+					printk(KERN_ALERT
+					       "%s: firmware %s is missing, cannot continue.\n",
 					       dev->name, priv->firmware_id);
 					return 0;
 				}
@@ -3654,7 +3679,7 @@ static int reset_atmel_card(struct net_device *dev)
 				while (fw_table[fw_index].fw_type != priv->firmware_type
 						&& fw_table[fw_index].fw_type != ATMEL_FW_TYPE_NONE)
 					fw_index++;
-				
+
 				/* construct the actual firmware file name */
 				if (fw_table[fw_index].fw_type != ATMEL_FW_TYPE_NONE) {
 					int i;
@@ -3669,24 +3694,24 @@ static int reset_atmel_card(struct net_device *dev)
 					}
 				}
 				if (!success) {
-					printk(KERN_ALERT 
-					       "%s: firmware %s is missing, cannot start.\n", 
+					printk(KERN_ALERT
+					       "%s: firmware %s is missing, cannot start.\n",
 					       dev->name, priv->firmware_id);
 					priv->firmware_id[0] = '\0';
-					return 0;	
+					return 0;
 				}
 			}
-			
+
 			fw = fw_entry->data;
 			len = fw_entry->size;
 		}
-		
+
 	        if (len <= 0x6000) {
 			atmel_write16(priv->dev, BSR, BSS_IRAM);
 			atmel_copy_to_card(priv->dev, 0, fw, len);
 			atmel_set_gcr(priv->dev, GCR_REMAP);
 		} else {
-			/* Remap */ 
+			/* Remap */
 			atmel_set_gcr(priv->dev, GCR_REMAP);
 			atmel_write16(priv->dev, BSR, BSS_IRAM);
 			atmel_copy_to_card(priv->dev, 0, fw, 0x6000);
@@ -3708,45 +3733,45 @@ static int reset_atmel_card(struct net_device *dev)
 	   the 3com broken-ness filter. */
 	priv->use_wpa = (priv->host_info.major_version == 4);
 	priv->radio_on_broken = (priv->host_info.major_version == 5);
-	
+
         /* unmask all irq sources */
 	atmel_wmem8(priv, atmel_hi(priv, IFACE_INT_MASK_OFFSET), 0xff);
-	
+
 	/* int Tx system and enable Tx */
 	atmel_wmem8(priv, atmel_tx(priv, TX_DESC_FLAGS_OFFSET, 0), 0);
 	atmel_wmem32(priv, atmel_tx(priv, TX_DESC_NEXT_OFFSET, 0), 0x80000000L);
 	atmel_wmem16(priv, atmel_tx(priv, TX_DESC_POS_OFFSET, 0), 0);
 	atmel_wmem16(priv, atmel_tx(priv, TX_DESC_SIZE_OFFSET, 0), 0);
 
-	priv->tx_desc_free = priv->host_info.tx_desc_count;		
-	priv->tx_desc_head = 0;									
-	priv->tx_desc_tail = 0;									
+	priv->tx_desc_free = priv->host_info.tx_desc_count;
+	priv->tx_desc_head = 0;
+	priv->tx_desc_tail = 0;
 	priv->tx_desc_previous = 0;
 	priv->tx_free_mem = priv->host_info.tx_buff_size;
-	priv->tx_buff_head = 0;	
-	priv->tx_buff_tail = 0;	
-		
-	configuration = atmel_rmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET)); 
-	atmel_wmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET), 
+	priv->tx_buff_head = 0;
+	priv->tx_buff_tail = 0;
+
+	configuration = atmel_rmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET));
+	atmel_wmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET),
 				   configuration | FUNC_CTRL_TxENABLE);
 
 	/* init Rx system and enable */
 	priv->rx_desc_head = 0;
-	
-	configuration = atmel_rmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET)); 
-	atmel_wmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET), 
+
+	configuration = atmel_rmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET));
+	atmel_wmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET),
 				   configuration | FUNC_CTRL_RxENABLE);
-			
+
 	if (!priv->radio_on_broken) {
-		if (atmel_send_command_wait(priv, CMD_EnableRadio, NULL, 0) == 
+		if (atmel_send_command_wait(priv, CMD_EnableRadio, NULL, 0) ==
 		    CMD_STATUS_REJECTED_RADIO_OFF) {
-			printk(KERN_INFO 
+			printk(KERN_INFO
 			       "%s: cannot turn the radio on. (Hey radio, you're beautiful!)\n",
 			       dev->name);
                         return 0;
 		}
 	}
-	
+
 	/* set up enough MIB values to run. */
 	atmel_set_mib8(priv, Local_Mib_Type, LOCAL_MIB_AUTO_TX_RATE_POS, priv->auto_tx_rate);
 	atmel_set_mib8(priv, Local_Mib_Type,  LOCAL_MIB_TX_PROMISCUOUS_POS,  PROM_MODE_OFF);
@@ -3755,7 +3780,7 @@ static int reset_atmel_card(struct net_device *dev)
 	atmel_set_mib8(priv, Mac_Mib_Type, MAC_MIB_SHORT_RETRY_POS, priv->short_retry);
 	atmel_set_mib8(priv, Mac_Mib_Type, MAC_MIB_LONG_RETRY_POS, priv->long_retry);
 	atmel_set_mib8(priv, Local_Mib_Type, LOCAL_MIB_PREAMBLE_TYPE, priv->preamble);
-	atmel_set_mib(priv, Mac_Address_Mib_Type, MAC_ADDR_MIB_MAC_ADDR_POS, 
+	atmel_set_mib(priv, Mac_Address_Mib_Type, MAC_ADDR_MIB_MAC_ADDR_POS,
 		      priv->dev->dev_addr, 6);
 	atmel_set_mib8(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_PS_MODE_POS, ACTIVE_MODE);
 	atmel_set_mib16(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_LISTEN_INTERVAL_POS, 1);
@@ -3766,42 +3791,44 @@ static int reset_atmel_card(struct net_device *dev)
 		build_wpa_mib(priv);
 	else
 		build_wep_mib(priv);
-	
+
 	return 1;
 }
 
-static void atmel_send_command(struct atmel_private *priv, int command, void *cmd, int cmd_size)
+static void atmel_send_command(struct atmel_private *priv, int command,
+			       void *cmd, int cmd_size)
 {
 	if (cmd)
-		atmel_copy_to_card(priv->dev, atmel_co(priv, CMD_BLOCK_PARAMETERS_OFFSET), 
+		atmel_copy_to_card(priv->dev, atmel_co(priv, CMD_BLOCK_PARAMETERS_OFFSET),
 				   cmd, cmd_size);
-	
+
 	atmel_wmem8(priv, atmel_co(priv, CMD_BLOCK_COMMAND_OFFSET), command);
 	atmel_wmem8(priv, atmel_co(priv, CMD_BLOCK_STATUS_OFFSET), 0);
 }
-	
-static int atmel_send_command_wait(struct atmel_private *priv, int command, void *cmd, int cmd_size)
+
+static int atmel_send_command_wait(struct atmel_private *priv, int command,
+				   void *cmd, int cmd_size)
 {
 	int i, status;
-	
+
 	atmel_send_command(priv, command, cmd, cmd_size);
-	
+
 	for (i = 5000; i; i--) {
 		status = atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_STATUS_OFFSET));
-		if (status != CMD_STATUS_IDLE && 
+		if (status != CMD_STATUS_IDLE &&
 		    status != CMD_STATUS_IN_PROGRESS)
 			break;
 		udelay(20);
 	}
-	
+
 	if (i == 0) {
 		printk(KERN_ALERT "%s: failed to contact MAC.\n", priv->dev->name);
 		status =  CMD_STATUS_HOST_ERROR;
-	} else { 
+	} else {
 		if (command != CMD_EnableRadio)
 			status = CMD_STATUS_COMPLETE;
 	}
-	
+
 	return status;
 }
 
@@ -3827,7 +3854,8 @@ static void atmel_set_mib8(struct atmel_private *priv, u8 type, u8 index, u8 dat
 	atmel_send_command_wait(priv, CMD_Set_MIB_Vars, &m, MIB_HEADER_SIZE + 1);
 }
 
-static void atmel_set_mib16(struct atmel_private *priv, u8 type, u8 index, u16 data)
+static void atmel_set_mib16(struct atmel_private *priv, u8 type, u8 index,
+			    u16 data)
 {
 	struct get_set_mib m;
 	m.type = type;
@@ -3839,7 +3867,8 @@ static void atmel_set_mib16(struct atmel_private *priv, u8 type, u8 index, u16 d
 	atmel_send_command_wait(priv, CMD_Set_MIB_Vars, &m, MIB_HEADER_SIZE + 2);
 }
 
-static void atmel_set_mib(struct atmel_private *priv, u8 type, u8 index, u8 *data, int data_len)
+static void atmel_set_mib(struct atmel_private *priv, u8 type, u8 index,
+			  u8 *data, int data_len)
 {
 	struct get_set_mib m;
 	m.type = type;
@@ -3848,23 +3877,24 @@ static void atmel_set_mib(struct atmel_private *priv, u8 type, u8 index, u8 *dat
 
 	if (data_len > MIB_MAX_DATA_BYTES)
 		printk(KERN_ALERT "%s: MIB buffer too small.\n", priv->dev->name);
-	
+
 	memcpy(m.data, data, data_len);
 	atmel_send_command_wait(priv, CMD_Set_MIB_Vars, &m, MIB_HEADER_SIZE + data_len);
 }
 
-static void atmel_get_mib(struct atmel_private *priv, u8 type, u8 index, u8 *data, int data_len)
+static void atmel_get_mib(struct atmel_private *priv, u8 type, u8 index,
+			  u8 *data, int data_len)
 {
 	struct get_set_mib m;
 	m.type = type;
 	m.size = data_len;
 	m.index = index;
-	
+
 	if (data_len > MIB_MAX_DATA_BYTES)
 		printk(KERN_ALERT "%s: MIB buffer too small.\n", priv->dev->name);
-	
+
 	atmel_send_command_wait(priv, CMD_Get_MIB_Vars, &m, MIB_HEADER_SIZE + data_len);
-	atmel_copy_to_host(priv->dev, data, 
+	atmel_copy_to_host(priv->dev, data,
 			   atmel_co(priv, CMD_BLOCK_PARAMETERS_OFFSET + MIB_HEADER_SIZE), data_len);
 }
 
@@ -3873,11 +3903,12 @@ static void atmel_writeAR(struct net_device *dev, u16 data)
 	int i;
 	outw(data, dev->base_addr + AR);
 	/* Address register appears to need some convincing..... */
-	for (i = 0; data != inw(dev->base_addr + AR) && i<10; i++)
+	for (i = 0; data != inw(dev->base_addr + AR) && i < 10; i++)
 		outw(data, dev->base_addr + AR);
 }
 
-static void atmel_copy_to_card(struct net_device *dev, u16 dest, unsigned char *src, u16 len)
+static void atmel_copy_to_card(struct net_device *dev, u16 dest,
+			       unsigned char *src, u16 len)
 {
 	int i;
 	atmel_writeAR(dev, dest);
@@ -3894,7 +3925,8 @@ static void atmel_copy_to_card(struct net_device *dev, u16 dest, unsigned char *
 		atmel_write8(dev, DR, *src);
 }
 
-static void atmel_copy_to_host(struct net_device *dev, unsigned char *dest, u16 src, u16 len)
+static void atmel_copy_to_host(struct net_device *dev, unsigned char *dest,
+			       u16 src, u16 len)
 {
 	int i;
 	atmel_writeAR(dev, src);
@@ -3930,22 +3962,24 @@ static int atmel_lock_mac(struct atmel_private *priv)
 			break;
 		udelay(20);
 	}
-	
-	if (!i) return 0; /* timed out */
-	
+
+	if (!i)
+		return 0; /* timed out */
+
 	atmel_wmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_MAC_OFFSET), 1);
 	if (atmel_rmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_HOST_OFFSET))) {
 		atmel_wmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_MAC_OFFSET), 0);
-		if (!j--) return 0; /* timed out */
+		if (!j--)
+			return 0; /* timed out */
 		goto retry;
 	}
-	
+
 	return 1;
 }
 
 static void atmel_wmem32(struct atmel_private *priv, u16 pos, u32 data)
 {
-       	atmel_writeAR(priv->dev, pos);	
+	atmel_writeAR(priv->dev, pos);
 	atmel_write16(priv->dev, DR, data); /* card is little-endian */
 	atmel_write16(priv->dev, DR, data >> 16);
 }
@@ -4017,9 +4051,9 @@ static void atmel_wmem32(struct atmel_private *priv, u16 pos, u32 data)
 				  serial output, since SO is normally high.  But it
 				  does cause 8 clock cycles and thus 8 bits to be
 				  clocked in to the chip.  See Atmel's SPI
-				  controller (e.g. AT91M55800) timing and 4K 
+				  controller (e.g. AT91M55800) timing and 4K
 				  SPI EEPROM manuals */
-				 
+
 	.set NVRAM_SCRATCH, 0x02000100  /* arbitrary area for scratchpad memory */
 	.set NVRAM_IMAGE, 0x02000200
 	.set NVRAM_LENGTH, 0x0200
@@ -4032,24 +4066,24 @@ static void atmel_wmem32(struct atmel_private *priv, u16 pos, u32 data)
 	.set MR4, 0xC
 RESET_VECTOR:
         b RESET_HANDLER
-UNDEF_VECTOR:  
+UNDEF_VECTOR:
         b HALT1
-SWI_VECTOR:            
+SWI_VECTOR:
         b HALT1
-IABORT_VECTOR: 
+IABORT_VECTOR:
         b HALT1
-DABORT_VECTOR:         
-RESERVED_VECTOR:    
+DABORT_VECTOR:
+RESERVED_VECTOR:
         b HALT1
-IRQ_VECTOR:    
+IRQ_VECTOR:
         b HALT1
-FIQ_VECTOR:    
+FIQ_VECTOR:
 	b HALT1
 HALT1:	b HALT1
 RESET_HANDLER:
 	mov     r0, #CPSR_INITIAL
 	msr	CPSR_c, r0	/* This is probably unnecessary */
-			
+
 /* I'm guessing this is initializing clock generator electronics for SPI */
 	ldr	r0, =SPI_CGEN_BASE
 	mov	r1, #0
@@ -4061,7 +4095,7 @@ RESET_HANDLER:
 	str	r1, [r0, #28]
 	mov	r1, #1
 	str	r1, [r0, #8]
-	
+
 	ldr	r0, =MRBASE
 	mov	r1, #0
 	strh	r1, [r0, #MR1]
@@ -4094,7 +4128,7 @@ GET_WHOLE_NVRAM:
 	ldmia	sp!, {lr}
 	bx	lr
 .endfunc
-	
+
 .func Get_MAC_Addr, GET_MAC_ADDR
 GET_MAC_ADDR:
 	stmdb	sp!, {lr}
@@ -4110,13 +4144,13 @@ GET_MAC_ADDR:
 .func Delay9, DELAY9
 DELAY9:
 	adds	r0, r0, r0, LSL #3   /* r0 = r0 * 9 */
-DELAYLOOP:	
+DELAYLOOP:
 	beq	DELAY9_done
 	subs	r0, r0, #1
 	b	DELAYLOOP
-DELAY9_done:	
+DELAY9_done:
 	bx	lr
-.endfunc	
+.endfunc
 
 .func SP_Init, SP_INIT
 SP_INIT:
@@ -4145,26 +4179,26 @@ SP_INIT:
 	ldr	r0, [r0, #SP_RDR]
 	bx	lr
 .endfunc
-.func NVRAM_Init, NVRAM_INIT	
+.func NVRAM_Init, NVRAM_INIT
 NVRAM_INIT:
 	ldr	r1, =SP_BASE
 	ldr	r0, [r1, #SP_RDR]
 	mov	r0, #NVRAM_CMD_RDSR
 	str	r0, [r1, #SP_TDR]
-SP_loop1:	
+SP_loop1:
 	ldr	r0, [r1, #SP_SR]
 	tst	r0, #SP_TDRE
 	beq	SP_loop1
 
 	mov	r0, #SPI_8CLOCKS
-	str	r0, [r1, #SP_TDR] 
-SP_loop2:	
+	str	r0, [r1, #SP_TDR]
+SP_loop2:
 	ldr	r0, [r1, #SP_SR]
 	tst	r0, #SP_TDRE
 	beq	SP_loop2
 
 	ldr	r0, [r1, #SP_RDR]
-SP_loop3:	
+SP_loop3:
 	ldr	r0, [r1, #SP_SR]
 	tst	r0, #SP_RDRF
 	beq	SP_loop3
@@ -4173,7 +4207,7 @@ SP_loop3:
 	and	r0, r0, #255
 	bx	lr
 .endfunc
-	
+
 .func NVRAM_Xfer, NVRAM_XFER
 	/* r0 = dest address */
 	/* r1 = not used */
@@ -4185,11 +4219,11 @@ NVRAM_XFER:
 	mov	r4, r3		/* save r3 (length) */
 	mov	r0, r2, LSR #5 /*  SPI memories put A8 in the command field */
 	and	r0, r0, #8
-	add	r0, r0, #NVRAM_CMD_READ 
+	add	r0, r0, #NVRAM_CMD_READ
 	ldr	r1, =NVRAM_SCRATCH
 	strb	r0, [r1, #0]	/* save command in NVRAM_SCRATCH[0] */
 	strb	r2, [r1, #1]    /* save low byte of source address in NVRAM_SCRATCH[1] */
-_local1:	
+_local1:
 	bl	NVRAM_INIT
 	tst	r0, #NVRAM_SR_RDY
 	bne	_local1
@@ -4211,7 +4245,7 @@ NVRAM_XFER2:
 	cmp	r0, #0
 	bls	_local2
 	ldr	r5, =NVRAM_SCRATCH
-_local4:	
+_local4:
 	ldrb	r6, [r5, r3]
 	str	r6, [r4, #SP_TDR]
 _local3:
@@ -4225,7 +4259,7 @@ _local2:
 	mov	r3, #SPI_8CLOCKS
 	str	r3, [r4, #SP_TDR]
 	ldr	r0, [r4, #SP_RDR]
-_local5:	
+_local5:
 	ldr	r0, [r4, #SP_SR]
 	tst	r0, #SP_RDRF
 	beq	_local5
@@ -4233,12 +4267,12 @@ _local5:
 	mov	r0, #0
 	cmp	r2, #0  /* r2 is # of bytes to copy in */
 	bls	_local6
-_local7:	
+_local7:
 	ldr	r5, [r4, #SP_SR]
 	tst	r5, #SP_TDRE
 	beq	_local7
 	str	r3, [r4, #SP_TDR]  /* r3 has SPI_8CLOCKS */
-_local8:	
+_local8:
 	ldr	r5, [r4, #SP_SR]
 	tst	r5, #SP_RDRF
 	beq	_local8
diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c
index 17d1fd90f832..d6f4a5a3e55a 100644
--- a/drivers/net/wireless/atmel_cs.c
+++ b/drivers/net/wireless/atmel_cs.c
@@ -93,8 +93,6 @@ MODULE_SUPPORTED_DEVICE("Atmel at76c50x PCMCIA cards");
 
 static void atmel_config(dev_link_t *link);
 static void atmel_release(dev_link_t *link);
-static int atmel_event(event_t event, int priority,
-		       event_callback_args_t *args);
 
 /*
    The attach() and detach() entry points are used to create and destroy
@@ -102,8 +100,7 @@ static int atmel_event(event_t event, int priority,
    needed to manage one actual PCMCIA card.
 */
 
-static dev_link_t *atmel_attach(void);
-static void atmel_detach(dev_link_t *);
+static void atmel_detach(struct pcmcia_device *p_dev);
 
 /*
    You'll also need to prototype all the functions that will actually
@@ -113,14 +110,6 @@ static void atmel_detach(dev_link_t *);
 */
 
 /*
-   The dev_info variable is the "key" that is used to match up this
-   device driver with appropriate cards, through the card configuration
-   database.
-*/
-
-static dev_info_t dev_info = "atmel_cs";
-
-/*
    A linked list of "instances" of the  atmelnet device.  Each actual
    PCMCIA card corresponds to one device instance, and is described
    by one dev_link_t structure (defined in ds.h).
@@ -130,15 +119,7 @@ static dev_info_t dev_info = "atmel_cs";
    device numbers are used to derive the corresponding array index.
 */
 
-static dev_link_t *dev_list = NULL;
-
 /*
-   A dev_link_t structure has fields for most things that are needed
-   to keep track of a socket, but there will usually be some device
-   specific information that also needs to be kept track of.  The
-   'priv' pointer in a dev_link_t structure can be used to point to
-   a device-specific private data structure, like this.
-
    A driver needs to provide a dev_node_t structure for each device
    on a card.  In some cases, there is only one device per card (for
    example, ethernet cards, modems).  In other cases, there may be
@@ -171,27 +152,25 @@ typedef struct local_info_t {
   
   ======================================================================*/
 
-static dev_link_t *atmel_attach(void)
+static int atmel_attach(struct pcmcia_device *p_dev)
 {
-	client_reg_t client_reg;
 	dev_link_t *link;
 	local_info_t *local;
-	int ret;
-	
+
 	DEBUG(0, "atmel_attach()\n");
 
 	/* Initialize the dev_link_t structure */
 	link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL);
 	if (!link) {
 		printk(KERN_ERR "atmel_cs: no memory for new device\n");
-		return NULL;
+		return -ENOMEM;
 	}
-	
+
 	/* Interrupt setup */
 	link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
 	link->irq.IRQInfo1 = IRQ_LEVEL_ID;
 	link->irq.Handler = NULL;
-	
+
 	/*
 	  General socket configuration defaults can go here.  In this
 	  client, we assume very little, and rely on the CIS for almost
@@ -202,30 +181,23 @@ static dev_link_t *atmel_attach(void)
 	link->conf.Attributes = 0;
 	link->conf.Vcc = 50;
 	link->conf.IntType = INT_MEMORY_AND_IO;
-	
+
 	/* Allocate space for private device-specific data */
 	local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
 	if (!local) {
 		printk(KERN_ERR "atmel_cs: no memory for new device\n");
 		kfree (link);
-		return NULL;
+		return -ENOMEM;
 	}
 	link->priv = local;
-	
-	/* Register with Card Services */
-	link->next = dev_list;
-	dev_list = link;
-	client_reg.dev_info = &dev_info;
-	client_reg.Version = 0x0210;
-	client_reg.event_callback_args.client_data = link;
-	ret = pcmcia_register_client(&link->handle, &client_reg);
-	if (ret != 0) {
-		cs_error(link->handle, RegisterClient, ret);
-		atmel_detach(link);
-		return NULL;
-	}
-	
-	return link;
+
+	link->handle = p_dev;
+	p_dev->instance = link;
+
+	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+	atmel_config(link);
+
+	return 0;
 } /* atmel_attach */
 
 /*======================================================================
@@ -237,27 +209,15 @@ static dev_link_t *atmel_attach(void)
   
   ======================================================================*/
 
-static void atmel_detach(dev_link_t *link)
+static void atmel_detach(struct pcmcia_device *p_dev)
 {
-	dev_link_t **linkp;
-	
+	dev_link_t *link = dev_to_instance(p_dev);
+
 	DEBUG(0, "atmel_detach(0x%p)\n", link);
-	
-	/* Locate device structure */
-	for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
-		if (*linkp == link) break;
-	if (*linkp == NULL)
-		return;
 
 	if (link->state & DEV_CONFIG)
 		atmel_release(link);
-		
-	/* Break the link with Card Services */
-	if (link->handle)
-		pcmcia_deregister_client(link->handle);
 
-	/* Unlink device structure, free pieces */
-	*linkp = link->next;
 	kfree(link->priv);
 	kfree(link);
 }
@@ -477,60 +437,34 @@ static void atmel_release(dev_link_t *link)
 	link->state &= ~DEV_CONFIG;
 }
 
-/*======================================================================
-  
-  The card status event handler.  Mostly, this schedules other
-  stuff to run after an event is received.
+static int atmel_suspend(struct pcmcia_device *dev)
+{
+	dev_link_t *link = dev_to_instance(dev);
+	local_info_t *local = link->priv;
 
-  When a CARD_REMOVAL event is received, we immediately set a
-  private flag to block future accesses to this device.  All the
-  functions that actually access the device should check this flag
-  to make sure the card is still present.
-  
-  ======================================================================*/
+	link->state |= DEV_SUSPEND;
+	if (link->state & DEV_CONFIG) {
+		netif_device_detach(local->eth_dev);
+		pcmcia_release_configuration(link->handle);
+	}
+
+	return 0;
+}
 
-static int atmel_event(event_t event, int priority,
-		      event_callback_args_t *args)
+static int atmel_resume(struct pcmcia_device *dev)
 {
-	dev_link_t *link = args->client_data;
+	dev_link_t *link = dev_to_instance(dev);
 	local_info_t *local = link->priv;
-	
-	DEBUG(1, "atmel_event(0x%06x)\n", event);
-	
-	switch (event) {
-	case CS_EVENT_CARD_REMOVAL:
-		link->state &= ~DEV_PRESENT;
-		if (link->state & DEV_CONFIG) {
-			netif_device_detach(local->eth_dev);
-			atmel_release(link);
-		}
-		break;
-	case CS_EVENT_CARD_INSERTION:
-		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-		atmel_config(link);
-		break;
-	case CS_EVENT_PM_SUSPEND:
-		link->state |= DEV_SUSPEND;
-		/* Fall through... */
-	case CS_EVENT_RESET_PHYSICAL:
-		if (link->state & DEV_CONFIG) {
-			netif_device_detach(local->eth_dev);
-			pcmcia_release_configuration(link->handle);
-		}
-		break;
-	case CS_EVENT_PM_RESUME:
-		link->state &= ~DEV_SUSPEND;
-		/* Fall through... */
-	case CS_EVENT_CARD_RESET:
-		if (link->state & DEV_CONFIG) {
-			pcmcia_request_configuration(link->handle, &link->conf);
-			atmel_open(local->eth_dev);
-			netif_device_attach(local->eth_dev);
-		}
-		break;
+
+	link->state &= ~DEV_SUSPEND;
+	if (link->state & DEV_CONFIG) {
+		pcmcia_request_configuration(link->handle, &link->conf);
+		atmel_open(local->eth_dev);
+		netif_device_attach(local->eth_dev);
 	}
+
 	return 0;
-} /* atmel_event */
+}
 
 /*====================================================================*/
 /* We use the driver_info field to store the correct firmware type for a card. */
@@ -581,10 +515,11 @@ static struct pcmcia_driver atmel_driver = {
 	.drv		= {
 		.name	= "atmel_cs",
         },
-	.attach         = atmel_attach,
-	.event		= atmel_event,
-	.detach		= atmel_detach,
+	.probe          = atmel_attach,
+	.remove		= atmel_detach,
 	.id_table	= atmel_ids,
+	.suspend	= atmel_suspend,
+	.resume		= atmel_resume,
 };
 
 static int atmel_cs_init(void)
@@ -595,7 +530,6 @@ static int atmel_cs_init(void)
 static void atmel_cs_cleanup(void)
 {
         pcmcia_unregister_driver(&atmel_driver);
-	BUG_ON(dev_list != NULL);
 }
 
 /*
diff --git a/drivers/net/wireless/hostap/Makefile b/drivers/net/wireless/hostap/Makefile
index fc62235bfc24..353ccb93134b 100644
--- a/drivers/net/wireless/hostap/Makefile
+++ b/drivers/net/wireless/hostap/Makefile
@@ -1,3 +1,4 @@
+hostap-y := hostap_main.o
 obj-$(CONFIG_HOSTAP) += hostap.o
 
 obj-$(CONFIG_HOSTAP_CS) += hostap_cs.o
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index 2643976a6677..8bc0b528548f 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -25,7 +25,6 @@
 
 static char *version = PRISM2_VERSION " (Jouni Malinen <jkmaline@cc.hut.fi>)";
 static dev_info_t dev_info = "hostap_cs";
-static dev_link_t *dev_list = NULL;
 
 MODULE_AUTHOR("Jouni Malinen");
 MODULE_DESCRIPTION("Support for Intersil Prism2-based 802.11 wireless LAN "
@@ -203,10 +202,9 @@ static int hfa384x_to_bap(struct net_device *dev, u16 bap, void *buf, int len)
 
 
 
-static void prism2_detach(dev_link_t *link);
+static void prism2_detach(struct pcmcia_device *p_dev);
 static void prism2_release(u_long arg);
-static int prism2_event(event_t event, int priority,
-			event_callback_args_t *args);
+static int prism2_config(dev_link_t *link);
 
 
 static int prism2_pccard_card_present(local_info_t *local)
@@ -503,15 +501,13 @@ static struct prism2_helper_functions prism2_pccard_funcs =
 
 /* allocate local data and register with CardServices
  * initialize dev_link structure, but do not configure the card yet */
-static dev_link_t *prism2_attach(void)
+static int prism2_attach(struct pcmcia_device *p_dev)
 {
 	dev_link_t *link;
-	client_reg_t client_reg;
-	int ret;
 
 	link = kmalloc(sizeof(dev_link_t), GFP_KERNEL);
 	if (link == NULL)
-		return NULL;
+		return -ENOMEM;
 
 	memset(link, 0, sizeof(dev_link_t));
 
@@ -519,50 +515,27 @@ static dev_link_t *prism2_attach(void)
 	link->conf.Vcc = 33;
 	link->conf.IntType = INT_MEMORY_AND_IO;
 
-	/* register with CardServices */
-	link->next = dev_list;
-	dev_list = link;
-	client_reg.dev_info = &dev_info;
-	client_reg.Version = 0x0210;
-	client_reg.event_callback_args.client_data = link;
-	ret = pcmcia_register_client(&link->handle, &client_reg);
-	if (ret != CS_SUCCESS) {
-		cs_error(link->handle, RegisterClient, ret);
-		prism2_detach(link);
-		return NULL;
-	}
-	return link;
+	link->handle = p_dev;
+	p_dev->instance = link;
+
+	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+	if (prism2_config(link))
+		PDEBUG(DEBUG_EXTRA, "prism2_config() failed\n");
+
+	return 0;
 }
 
 
-static void prism2_detach(dev_link_t *link)
+static void prism2_detach(struct pcmcia_device *p_dev)
 {
-	dev_link_t **linkp;
+	dev_link_t *link = dev_to_instance(p_dev);
 
 	PDEBUG(DEBUG_FLOW, "prism2_detach\n");
 
-	for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
-		if (*linkp == link)
-			break;
-	if (*linkp == NULL) {
-		printk(KERN_WARNING "%s: Attempt to detach non-existing "
-		       "PCMCIA client\n", dev_info);
-		return;
-	}
-
 	if (link->state & DEV_CONFIG) {
 		prism2_release((u_long)link);
 	}
 
-	if (link->handle) {
-		int res = pcmcia_deregister_client(link->handle);
-		if (res) {
-			printk("CardService(DeregisterClient) => %d\n", res);
-			cs_error(link->handle, DeregisterClient, res);
-		}
-	}
-
-	*linkp = link->next;
 	/* release net devices */
 	if (link->priv) {
 		struct hostap_cs_priv *hw_priv;
@@ -846,84 +819,58 @@ static void prism2_release(u_long arg)
 	PDEBUG(DEBUG_FLOW, "release - done\n");
 }
 
-
-static int prism2_event(event_t event, int priority,
-			event_callback_args_t *args)
+static int hostap_cs_suspend(struct pcmcia_device *p_dev)
 {
-	dev_link_t *link = args->client_data;
+	dev_link_t *link = dev_to_instance(p_dev);
 	struct net_device *dev = (struct net_device *) link->priv;
 	int dev_open = 0;
 
+	PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_SUSPEND\n", dev_info);
+
+	link->state |= DEV_SUSPEND;
+
 	if (link->state & DEV_CONFIG) {
 		struct hostap_interface *iface = netdev_priv(dev);
 		if (iface && iface->local)
 			dev_open = iface->local->num_dev_open > 0;
-	}
-
-	switch (event) {
-	case CS_EVENT_CARD_INSERTION:
-		PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_CARD_INSERTION\n", dev_info);
-		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-		if (prism2_config(link)) {
-			PDEBUG(DEBUG_EXTRA, "prism2_config() failed\n");
-		}
-		break;
-
-	case CS_EVENT_CARD_REMOVAL:
-		PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_CARD_REMOVAL\n", dev_info);
-		link->state &= ~DEV_PRESENT;
-		if (link->state & DEV_CONFIG) {
+		if (dev_open) {
 			netif_stop_queue(dev);
 			netif_device_detach(dev);
-			prism2_release((u_long) link);
 		}
-		break;
+		prism2_suspend(dev);
+		pcmcia_release_configuration(link->handle);
+	}
 
-	case CS_EVENT_PM_SUSPEND:
-		PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_SUSPEND\n", dev_info);
-		link->state |= DEV_SUSPEND;
-		/* fall through */
-
-	case CS_EVENT_RESET_PHYSICAL:
-		PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_RESET_PHYSICAL\n", dev_info);
-		if (link->state & DEV_CONFIG) {
-			if (dev_open) {
-				netif_stop_queue(dev);
-				netif_device_detach(dev);
-			}
-			prism2_suspend(dev);
-			pcmcia_release_configuration(link->handle);
-		}
-		break;
+	return 0;
+}
 
-	case CS_EVENT_PM_RESUME:
-		PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_RESUME\n", dev_info);
-		link->state &= ~DEV_SUSPEND;
-		/* fall through */
-
-	case CS_EVENT_CARD_RESET:
-		PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_CARD_RESET\n", dev_info);
-		if (link->state & DEV_CONFIG) {
-			pcmcia_request_configuration(link->handle,
-						     &link->conf);
-			prism2_hw_shutdown(dev, 1);
-			prism2_hw_config(dev, dev_open ? 0 : 1);
-			if (dev_open) {
-				netif_device_attach(dev);
-				netif_start_queue(dev);
-			}
-		}
-		break;
+static int hostap_cs_resume(struct pcmcia_device *p_dev)
+{
+	dev_link_t *link = dev_to_instance(p_dev);
+	struct net_device *dev = (struct net_device *) link->priv;
+	int dev_open = 0;
 
-	default:
-		PDEBUG(DEBUG_EXTRA, "%s: prism2_event() - unknown event %d\n",
-		       dev_info, event);
-		break;
+	PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_RESUME\n", dev_info);
+
+	link->state &= ~DEV_SUSPEND;
+	if (link->state & DEV_CONFIG) {
+		struct hostap_interface *iface = netdev_priv(dev);
+		if (iface && iface->local)
+			dev_open = iface->local->num_dev_open > 0;
+
+		pcmcia_request_configuration(link->handle, &link->conf);
+
+		prism2_hw_shutdown(dev, 1);
+		prism2_hw_config(dev, dev_open ? 0 : 1);
+		if (dev_open) {
+			netif_device_attach(dev);
+			netif_start_queue(dev);
+		}
 	}
+
 	return 0;
 }
 
-
 static struct pcmcia_device_id hostap_cs_ids[] = {
 	PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7100),
 	PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300),
@@ -982,11 +929,12 @@ static struct pcmcia_driver hostap_driver = {
 	.drv		= {
 		.name	= "hostap_cs",
 	},
-	.attach		= prism2_attach,
-	.detach		= prism2_detach,
+	.probe		= prism2_attach,
+	.remove		= prism2_detach,
 	.owner		= THIS_MODULE,
-	.event		= prism2_event,
 	.id_table	= hostap_cs_ids,
+	.suspend	= hostap_cs_suspend,
+	.resume		= hostap_cs_resume,
 };
 
 static int __init init_prism2_pccard(void)
diff --git a/drivers/net/wireless/hostap/hostap.c b/drivers/net/wireless/hostap/hostap_main.c
index 3d2ea61033be..3d2ea61033be 100644
--- a/drivers/net/wireless/hostap/hostap.c
+++ b/drivers/net/wireless/hostap/hostap_main.c
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c
index 77d2a21d4cd0..44cd3fcd1572 100644
--- a/drivers/net/wireless/ipw2100.c
+++ b/drivers/net/wireless/ipw2100.c
@@ -175,7 +175,7 @@ that only one external action is invoked at a time.
 #define DRV_COPYRIGHT	"Copyright(c) 2003-2005 Intel Corporation"
 
 /* Debugging stuff */
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2100_DEBUG
 #define CONFIG_IPW2100_RX_DEBUG	/* Reception debugging */
 #endif
 
@@ -208,7 +208,7 @@ MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])");
 
 static u32 ipw2100_debug_level = IPW_DL_NONE;
 
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2100_DEBUG
 #define IPW_DEBUG(level, message...) \
 do { \
 	if (ipw2100_debug_level & (level)) { \
@@ -219,9 +219,9 @@ do { \
 } while (0)
 #else
 #define IPW_DEBUG(level, message...) do {} while (0)
-#endif				/* CONFIG_IPW_DEBUG */
+#endif				/* CONFIG_IPW2100_DEBUG */
 
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2100_DEBUG
 static const char *command_types[] = {
 	"undefined",
 	"unused",		/* HOST_ATTENTION */
@@ -2081,7 +2081,7 @@ static void isr_scan_complete(struct ipw2100_priv *priv, u32 status)
 	priv->status &= ~STATUS_SCANNING;
 }
 
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2100_DEBUG
 #define IPW2100_HANDLER(v, f) { v, f, # v }
 struct ipw2100_status_indicator {
 	int status;
@@ -2094,7 +2094,7 @@ struct ipw2100_status_indicator {
 	int status;
 	void (*cb) (struct ipw2100_priv * priv, u32 status);
 };
-#endif				/* CONFIG_IPW_DEBUG */
+#endif				/* CONFIG_IPW2100_DEBUG */
 
 static void isr_indicate_scanning(struct ipw2100_priv *priv, u32 status)
 {
@@ -2149,7 +2149,7 @@ static void isr_status_change(struct ipw2100_priv *priv, int status)
 static void isr_rx_complete_command(struct ipw2100_priv *priv,
 				    struct ipw2100_cmd_header *cmd)
 {
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2100_DEBUG
 	if (cmd->host_command_reg < ARRAY_SIZE(command_types)) {
 		IPW_DEBUG_HC("Command completed '%s (%d)'\n",
 			     command_types[cmd->host_command_reg],
@@ -2167,7 +2167,7 @@ static void isr_rx_complete_command(struct ipw2100_priv *priv,
 	wake_up_interruptible(&priv->wait_command_queue);
 }
 
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2100_DEBUG
 static const char *frame_types[] = {
 	"COMMAND_STATUS_VAL",
 	"STATUS_CHANGE_VAL",
@@ -2290,7 +2290,7 @@ static u8 packet_data[IPW_RX_NIC_BUFFER_LENGTH];
 
 static inline void ipw2100_corruption_detected(struct ipw2100_priv *priv, int i)
 {
-#ifdef CONFIG_IPW_DEBUG_C3
+#ifdef CONFIG_IPW2100_DEBUG_C3
 	struct ipw2100_status *status = &priv->status_queue.drv[i];
 	u32 match, reg;
 	int j;
@@ -2312,7 +2312,7 @@ static inline void ipw2100_corruption_detected(struct ipw2100_priv *priv, int i)
 	}
 #endif
 
-#ifdef CONFIG_IPW_DEBUG_C3
+#ifdef CONFIG_IPW2100_DEBUG_C3
 	/* Halt the fimrware so we can get a good image */
 	write_register(priv->net_dev, IPW_REG_RESET_REG,
 		       IPW_AUX_HOST_RESET_REG_STOP_MASTER);
@@ -2716,7 +2716,7 @@ static inline int __ipw2100_tx_process(struct ipw2100_priv *priv)
 	list_del(element);
 	DEC_STAT(&priv->fw_pend_stat);
 
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2100_DEBUG
 	{
 		int i = txq->oldest;
 		IPW_DEBUG_TX("TX%d V=%p P=%04X T=%04X L=%d\n", i,
@@ -2782,7 +2782,7 @@ static inline int __ipw2100_tx_process(struct ipw2100_priv *priv)
 			       "something else: ids %d=%d.\n",
 			       priv->net_dev->name, txq->oldest, packet->index);
 
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2100_DEBUG
 		if (packet->info.c_struct.cmd->host_command_reg <
 		    sizeof(command_types) / sizeof(*command_types))
 			IPW_DEBUG_TX("Command '%s (%d)' processed: %d.\n",
@@ -2975,7 +2975,7 @@ static void ipw2100_tx_send_data(struct ipw2100_priv *priv)
 
 		IPW_DEBUG_TX("data header tbd TX%d P=%08x L=%d\n",
 			     packet->index, tbd->host_addr, tbd->buf_length);
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2100_DEBUG
 		if (packet->info.d_struct.txb->nr_frags > 1)
 			IPW_DEBUG_FRAG("fragment Tx: %d frames\n",
 				       packet->info.d_struct.txb->nr_frags);
@@ -3827,7 +3827,7 @@ static ssize_t show_stats(struct device *d, struct device_attribute *attr,
 		       priv->rx_interrupts, priv->inta_other);
 	out += sprintf(out, "firmware resets: %d\n", priv->resets);
 	out += sprintf(out, "firmware hangs: %d\n", priv->hangs);
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2100_DEBUG
 	out += sprintf(out, "packet mismatch image: %s\n",
 		       priv->snapshot[0] ? "YES" : "NO");
 #endif
@@ -3982,7 +3982,7 @@ static ssize_t show_bssinfo(struct device *d, struct device_attribute *attr,
 
 static DEVICE_ATTR(bssinfo, S_IRUGO, show_bssinfo, NULL);
 
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2100_DEBUG
 static ssize_t show_debug_level(struct device_driver *d, char *buf)
 {
 	return sprintf(buf, "0x%08X\n", ipw2100_debug_level);
@@ -4011,7 +4011,7 @@ static ssize_t store_debug_level(struct device_driver *d,
 
 static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO, show_debug_level,
 		   store_debug_level);
-#endif				/* CONFIG_IPW_DEBUG */
+#endif				/* CONFIG_IPW2100_DEBUG */
 
 static ssize_t show_fatal_error(struct device *d,
 				struct device_attribute *attr, char *buf)
@@ -4937,7 +4937,7 @@ static int ipw2100_set_mandatory_bssid(struct ipw2100_priv *priv, u8 * bssid,
 	};
 	int err;
 
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2100_DEBUG
 	if (bssid != NULL)
 		IPW_DEBUG_HC("MANDATORY_BSSID: %02X:%02X:%02X:%02X:%02X:%02X\n",
 			     bssid[0], bssid[1], bssid[2], bssid[3], bssid[4],
@@ -6858,7 +6858,7 @@ static int __init ipw2100_init(void)
 
 	ret = pci_module_init(&ipw2100_pci_driver);
 
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2100_DEBUG
 	ipw2100_debug_level = debug;
 	driver_create_file(&ipw2100_pci_driver.driver,
 			   &driver_attr_debug_level);
@@ -6873,7 +6873,7 @@ static int __init ipw2100_init(void)
 static void __exit ipw2100_exit(void)
 {
 	/* FIXME: IPG: check that we have no instances of the devices open */
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2100_DEBUG
 	driver_remove_file(&ipw2100_pci_driver.driver,
 			   &driver_attr_debug_level);
 #endif
@@ -8558,7 +8558,7 @@ static struct iw_statistics *ipw2100_wx_wireless_stats(struct net_device *dev)
 
 		quality = min(beacon_qual, min(tx_qual, rssi_qual));
 
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2100_DEBUG
 		if (beacon_qual == quality)
 			IPW_DEBUG_WX("Quality clamped by Missed Beacons\n");
 		else if (tx_qual == quality)
diff --git a/drivers/net/wireless/ipw2100.h b/drivers/net/wireless/ipw2100.h
index 7c65b10bb164..f6c51441fa87 100644
--- a/drivers/net/wireless/ipw2100.h
+++ b/drivers/net/wireless/ipw2100.h
@@ -73,7 +73,7 @@ struct ipw2100_rx_packet;
  * you simply need to add your entry to the ipw2100_debug_levels array.
  *
  * If you do not see debug_level in /proc/net/ipw2100 then you do not have
- * CONFIG_IPW_DEBUG defined in your kernel configuration
+ * CONFIG_IPW2100_DEBUG defined in your kernel configuration
  *
  */
 
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index 5e7c7e944c9d..cdfe50207757 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -462,7 +462,7 @@ static inline void ipw_disable_interrupts(struct ipw_priv *priv)
 	ipw_write32(priv, IPW_INTA_MASK_R, ~IPW_INTA_MASK_ALL);
 }
 
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2200_DEBUG
 static char *ipw_error_desc(u32 val)
 {
 	switch (val) {
@@ -1235,7 +1235,7 @@ static ssize_t store_scan_age(struct device *d, struct device_attribute *attr,
 			      const char *buf, size_t count)
 {
 	struct ipw_priv *priv = dev_get_drvdata(d);
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2200_DEBUG
 	struct net_device *dev = priv->net_dev;
 #endif
 	char buffer[] = "00000000";
@@ -1754,7 +1754,7 @@ static void ipw_irq_tasklet(struct ipw_priv *priv)
 		IPW_ERROR("Firmware error detected.  Restarting.\n");
 		if (priv->error) {
 			IPW_ERROR("Sysfs 'error' log already exists.\n");
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2200_DEBUG
 			if (ipw_debug_level & IPW_DL_FW_ERRORS) {
 				struct ipw_fw_error *error =
 				    ipw_alloc_error_log(priv);
@@ -1770,7 +1770,7 @@ static void ipw_irq_tasklet(struct ipw_priv *priv)
 			else
 				IPW_ERROR("Error allocating sysfs 'error' "
 					  "log.\n");
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2200_DEBUG
 			if (ipw_debug_level & IPW_DL_FW_ERRORS)
 				ipw_dump_error_log(priv, priv->error);
 #endif
@@ -3778,7 +3778,7 @@ static const struct ipw_status_code ipw_status_codes[] = {
 	{0x2E, "Cipher suite is rejected per security policy"},
 };
 
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2200_DEBUG
 static const char *ipw_get_status_code(u16 status)
 {
 	int i;
@@ -4250,7 +4250,7 @@ static inline void ipw_rx_notification(struct ipw_priv *priv,
 					if (priv->
 					    status & (STATUS_ASSOCIATED |
 						      STATUS_AUTH)) {
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2200_DEBUG
 						struct notif_authenticate *auth
 						    = &notif->u.auth;
 						IPW_DEBUG(IPW_DL_NOTIF |
@@ -4944,12 +4944,11 @@ static struct ipw_rx_queue *ipw_rx_queue_alloc(struct ipw_priv *priv)
 	struct ipw_rx_queue *rxq;
 	int i;
 
-	rxq = (struct ipw_rx_queue *)kmalloc(sizeof(*rxq), GFP_KERNEL);
+	rxq = kzalloc(sizeof(*rxq), GFP_KERNEL);
 	if (unlikely(!rxq)) {
 		IPW_ERROR("memory allocation failed\n");
 		return NULL;
 	}
-	memset(rxq, 0, sizeof(*rxq));
 	spin_lock_init(&rxq->lock);
 	INIT_LIST_HEAD(&rxq->rx_free);
 	INIT_LIST_HEAD(&rxq->rx_used);
@@ -5828,7 +5827,7 @@ static void ipw_bg_adhoc_check(void *data)
 	up(&priv->sem);
 }
 
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2200_DEBUG
 static void ipw_debug_config(struct ipw_priv *priv)
 {
 	IPW_DEBUG_INFO("Scan completed, no valid APs matched "
@@ -7456,8 +7455,7 @@ static void ipw_handle_data_packet(struct ipw_priv *priv,
 	/* HW decrypt will not clear the WEP bit, MIC, PN, etc. */
 	hdr = (struct ieee80211_hdr_4addr *)rxb->skb->data;
 	if (priv->ieee->iw_mode != IW_MODE_MONITOR &&
-	    ((is_multicast_ether_addr(hdr->addr1) ||
-	      is_broadcast_ether_addr(hdr->addr1)) ?
+	    (is_multicast_ether_addr(hdr->addr1) ?
 	     !priv->ieee->host_mc_decrypt : !priv->ieee->host_decrypt))
 		ipw_rebuild_decrypted_skb(priv, rxb->skb);
 
@@ -7648,8 +7646,7 @@ static inline int is_network_packet(struct ipw_priv *priv,
 			return 0;
 
 		/* {broad,multi}cast packets to our BSSID go through */
-		if (is_multicast_ether_addr(header->addr1) ||
-		    is_broadcast_ether_addr(header->addr1))
+		if (is_multicast_ether_addr(header->addr1))
 			return !memcmp(header->addr3, priv->bssid, ETH_ALEN);
 
 		/* packets to our adapter go through */
@@ -7662,8 +7659,7 @@ static inline int is_network_packet(struct ipw_priv *priv,
 			return 0;
 
 		/* {broad,multi}cast packets to our BSS go through */
-		if (is_multicast_ether_addr(header->addr1) ||
-		    is_broadcast_ether_addr(header->addr1))
+		if (is_multicast_ether_addr(header->addr1))
 			return !memcmp(header->addr2, priv->bssid, ETH_ALEN);
 
 		/* packets to our adapter go through */
@@ -7815,7 +7811,7 @@ static void ipw_rx(struct ipw_priv *priv)
 
 	while (i != r) {
 		rxb = priv->rxq->queue[i];
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2200_DEBUG
 		if (unlikely(rxb == NULL)) {
 			printk(KERN_CRIT "Queue not allocated!\n");
 			break;
@@ -9657,8 +9653,7 @@ static inline int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb,
 	switch (priv->ieee->iw_mode) {
 	case IW_MODE_ADHOC:
 		hdr_len = IEEE80211_3ADDR_LEN;
-		unicast = !(is_multicast_ether_addr(hdr->addr1) ||
-			    is_broadcast_ether_addr(hdr->addr1));
+		unicast = !is_multicast_ether_addr(hdr->addr1);
 		id = ipw_find_station(priv, hdr->addr1);
 		if (id == IPW_INVALID_STATION) {
 			id = ipw_add_station(priv, hdr->addr1);
@@ -9673,8 +9668,7 @@ static inline int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb,
 
 	case IW_MODE_INFRA:
 	default:
-		unicast = !(is_multicast_ether_addr(hdr->addr3) ||
-			    is_broadcast_ether_addr(hdr->addr3));
+		unicast = !is_multicast_ether_addr(hdr->addr3);
 		hdr_len = IEEE80211_3ADDR_LEN;
 		id = 0;
 		break;
@@ -10956,7 +10950,7 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	priv->net_dev = net_dev;
 	priv->pci_dev = pdev;
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2200_DEBUG
 	ipw_debug_level = debug;
 #endif
 	spin_lock_init(&priv->lock);
diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h
index 1c98db0652c9..e65620a4d79e 100644
--- a/drivers/net/wireless/ipw2200.h
+++ b/drivers/net/wireless/ipw2200.h
@@ -1301,14 +1301,14 @@ struct ipw_priv {
 
 /* debug macros */
 
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2200_DEBUG
 #define IPW_DEBUG(level, fmt, args...) \
 do { if (ipw_debug_level & (level)) \
   printk(KERN_DEBUG DRV_NAME": %c %s " fmt, \
          in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0)
 #else
 #define IPW_DEBUG(level, fmt, args...) do {} while (0)
-#endif				/* CONFIG_IPW_DEBUG */
+#endif				/* CONFIG_IPW2200_DEBUG */
 
 /*
  * To use the debug system;
@@ -1332,7 +1332,7 @@ do { if (ipw_debug_level & (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_IPW_DEBUG defined in your kernel configuration
+ * CONFIG_IPW2200_DEBUG defined in your kernel configuration
  *
  */
 
diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c
index 92793b958e32..bf6271ee387a 100644
--- a/drivers/net/wireless/netwave_cs.c
+++ b/drivers/net/wireless/netwave_cs.c
@@ -166,8 +166,6 @@ static char *version =
 #define DEBUG(n, args...)
 #endif
 
-static dev_info_t dev_info = "netwave_cs";
-
 /*====================================================================*/
 
 /* Parameters that can be set with 'insmod' */
@@ -195,12 +193,9 @@ module_param(mem_speed, int, 0);
 
 /* PCMCIA (Card Services) related functions */
 static void netwave_release(dev_link_t *link);     /* Card removal */
-static int  netwave_event(event_t event, int priority, 
-					      event_callback_args_t *args);
 static void netwave_pcmcia_config(dev_link_t *arg); /* Runs after card 
 													   insertion */
-static dev_link_t *netwave_attach(void);     /* Create instance */
-static void netwave_detach(dev_link_t *);    /* Destroy instance */
+static void netwave_detach(struct pcmcia_device *p_dev);    /* Destroy instance */
 
 /* Hardware configuration */
 static void netwave_doreset(kio_addr_t iobase, u_char __iomem *ramBase);
@@ -228,17 +223,6 @@ static struct iw_statistics* netwave_get_wireless_stats(struct net_device *dev);
 static void set_multicast_list(struct net_device *dev);
 
 /*
-   A linked list of "instances" of the skeleton device.  Each actual
-   PCMCIA card corresponds to one device instance, and is described
-   by one dev_link_t structure (defined in ds.h).
-
-   You may not want to use a linked list for this -- for example, the
-   memory card driver uses an array of dev_link_t pointers, where minor
-   device numbers are used to derive the corresponding array index.
-*/
-static dev_link_t *dev_list;
-
-/*
    A dev_link_t structure has fields for most things that are needed
    to keep track of a socket, but there will usually be some device
    specific information that also needs to be kept track of.  The
@@ -394,20 +378,18 @@ static struct iw_statistics *netwave_get_wireless_stats(struct net_device *dev)
  *     configure the card at this point -- we wait until we receive a
  *     card insertion event.
  */
-static dev_link_t *netwave_attach(void)
+static int netwave_attach(struct pcmcia_device *p_dev)
 {
-    client_reg_t client_reg;
     dev_link_t *link;
     struct net_device *dev;
     netwave_private *priv;
-    int ret;
-    
+
     DEBUG(0, "netwave_attach()\n");
-    
+
     /* Initialize the dev_link_t structure */
     dev = alloc_etherdev(sizeof(netwave_private));
     if (!dev)
-	return NULL;
+	return -ENOMEM;
     priv = netdev_priv(dev);
     link = &priv->link;
     link->priv = dev;
@@ -449,21 +431,14 @@ static dev_link_t *netwave_attach(void)
     dev->open = &netwave_open;
     dev->stop = &netwave_close;
     link->irq.Instance = dev;
-    
-    /* Register with Card Services */
-    link->next = dev_list;
-    dev_list = link;
-    client_reg.dev_info = &dev_info;
-    client_reg.Version = 0x0210;
-    client_reg.event_callback_args.client_data = link;
-    ret = pcmcia_register_client(&link->handle, &client_reg);
-    if (ret != 0) {
-	cs_error(link->handle, RegisterClient, ret);
-	netwave_detach(link);
-	return NULL;
-    }
 
-    return link;
+    link->handle = p_dev;
+    p_dev->instance = link;
+
+    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+    netwave_pcmcia_config( link);
+
+    return 0;
 } /* netwave_attach */
 
 /*
@@ -474,42 +449,20 @@ static dev_link_t *netwave_attach(void)
  *    structures are freed.  Otherwise, the structures will be freed
  *    when the device is released.
  */
-static void netwave_detach(dev_link_t *link)
+static void netwave_detach(struct pcmcia_device *p_dev)
 {
-    struct net_device *dev = link->priv;
-    dev_link_t **linkp;
+	dev_link_t *link = dev_to_instance(p_dev);
+	struct net_device *dev = link->priv;
 
-    DEBUG(0, "netwave_detach(0x%p)\n", link);
-  
-    /*
-	  If the device is currently configured and active, we won't
-	  actually delete it yet.  Instead, it is marked so that when
-	  the release() function is called, that will trigger a proper
-	  detach().
-	*/
-    if (link->state & DEV_CONFIG)
-	netwave_release(link);
-	
-    /* Break the link with Card Services */
-    if (link->handle)
-	pcmcia_deregister_client(link->handle);
-    
-    /* Locate device structure */
-    for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
-	if (*linkp == link) break;
-    if (*linkp == NULL)
-      {
-	DEBUG(1, "netwave_cs: detach fail, '%s' not in list\n",
-	      link->dev->dev_name);
-	return;
-      }
-
-    /* Unlink device structure, free pieces */
-    *linkp = link->next;
-    if (link->dev) 
-	unregister_netdev(dev);
-    free_netdev(dev);
-    
+	DEBUG(0, "netwave_detach(0x%p)\n", link);
+
+	if (link->state & DEV_CONFIG)
+		netwave_release(link);
+
+	if (link->dev)
+		unregister_netdev(dev);
+
+	free_netdev(dev);
 } /* netwave_detach */
 
 /*
@@ -935,69 +888,38 @@ static void netwave_release(dev_link_t *link)
     link->state &= ~DEV_CONFIG;
 }
 
-/*
- * Function netwave_event (event, priority, args)
- *
- *    The card status event handler.  Mostly, this schedules other
- *    stuff to run after an event is received.  A CARD_REMOVAL event
- *    also sets some flags to discourage the net drivers from trying
- *    to talk to the card any more.
- *
- *    When a CARD_REMOVAL event is received, we immediately set a flag
- *    to block future accesses to this device.  All the functions that
- *    actually access the device should check this flag to make sure
- *    the card is still present.
- *
- */
-static int netwave_event(event_t event, int priority,
-			 event_callback_args_t *args)
+static int netwave_suspend(struct pcmcia_device *p_dev)
 {
-    dev_link_t *link = args->client_data;
-    struct net_device *dev = link->priv;
-	
-    DEBUG(1, "netwave_event(0x%06x)\n", event);
-  
-    switch (event) {
-    case CS_EVENT_REGISTRATION_COMPLETE:
-	DEBUG(0, "netwave_cs: registration complete\n");
-	break;
-
-    case CS_EVENT_CARD_REMOVAL:
-	link->state &= ~DEV_PRESENT;
-	if (link->state & DEV_CONFIG) {
-	    netif_device_detach(dev);
-	    netwave_release(link);
-	}
-	break;
-    case CS_EVENT_CARD_INSERTION:
-	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-	netwave_pcmcia_config( link);
-	break;
-    case CS_EVENT_PM_SUSPEND:
+	dev_link_t *link = dev_to_instance(p_dev);
+	struct net_device *dev = link->priv;
+
 	link->state |= DEV_SUSPEND;
-	/* Fall through... */
-    case CS_EVENT_RESET_PHYSICAL:
 	if (link->state & DEV_CONFIG) {
-	    if (link->open)
-		netif_device_detach(dev);
-	    pcmcia_release_configuration(link->handle);
+		if (link->open)
+			netif_device_detach(dev);
+		pcmcia_release_configuration(link->handle);
 	}
-	break;
-    case CS_EVENT_PM_RESUME:
+
+	return 0;
+}
+
+static int netwave_resume(struct pcmcia_device *p_dev)
+{
+	dev_link_t *link = dev_to_instance(p_dev);
+	struct net_device *dev = link->priv;
+
 	link->state &= ~DEV_SUSPEND;
-	/* Fall through... */
-    case CS_EVENT_CARD_RESET:
 	if (link->state & DEV_CONFIG) {
-	    pcmcia_request_configuration(link->handle, &link->conf);
-	    if (link->open) {
-		netwave_reset(dev);
-		netif_device_attach(dev);
-	    }
+		pcmcia_request_configuration(link->handle, &link->conf);
+		if (link->open) {
+			netwave_reset(dev);
+			netif_device_attach(dev);
+		}
 	}
-	break;
-    }
-    return 0;
-} /* netwave_event */
+
+	return 0;
+}
+
 
 /*
  * Function netwave_doreset (ioBase, ramBase)
@@ -1491,10 +1413,11 @@ static struct pcmcia_driver netwave_driver = {
 	.drv		= {
 		.name	= "netwave_cs",
 	},
-	.attach		= netwave_attach,
-	.event		= netwave_event,
-	.detach		= netwave_detach,
+	.probe		= netwave_attach,
+	.remove		= netwave_detach,
 	.id_table       = netwave_ids,
+	.suspend	= netwave_suspend,
+	.resume		= netwave_resume,
 };
 
 static int __init init_netwave_cs(void)
@@ -1505,7 +1428,6 @@ static int __init init_netwave_cs(void)
 static void __exit exit_netwave_cs(void)
 {
 	pcmcia_unregister_driver(&netwave_driver);
-	BUG_ON(dev_list != NULL);
 }
 
 module_init(init_netwave_cs);
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c
index dc1128a00971..b664708481cc 100644
--- a/drivers/net/wireless/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco_cs.c
@@ -43,17 +43,6 @@ module_param(ignore_cis_vcc, int, 0);
 MODULE_PARM_DESC(ignore_cis_vcc, "Allow voltage mismatch between card and socket");
 
 /********************************************************************/
-/* Magic constants						    */
-/********************************************************************/
-
-/*
- * The dev_info variable is the "key" that is used to match up this
- * device driver with appropriate cards, through the card
- * configuration database.
- */
-static dev_info_t dev_info = DRIVER_NAME;
-
-/********************************************************************/
 /* Data structures						    */
 /********************************************************************/
 
@@ -69,19 +58,14 @@ struct orinoco_pccard {
 	unsigned long hard_reset_in_progress; 
 };
 
-/*
- * A linked list of "instances" of the device.  Each actual PCMCIA
- * card corresponds to one device instance, and is described by one
- * dev_link_t structure (defined in ds.h).
- */
-static dev_link_t *dev_list; /* = NULL */
 
 /********************************************************************/
 /* Function prototypes						    */
 /********************************************************************/
 
+static void orinoco_cs_config(dev_link_t *link);
 static void orinoco_cs_release(dev_link_t *link);
-static void orinoco_cs_detach(dev_link_t *link);
+static void orinoco_cs_detach(struct pcmcia_device *p_dev);
 
 /********************************************************************/
 /* Device methods     						    */
@@ -119,19 +103,17 @@ orinoco_cs_hard_reset(struct orinoco_private *priv)
  * The dev_link structure is initialized, but we don't actually
  * configure the card at this point -- we wait until we receive a card
  * insertion event.  */
-static dev_link_t *
-orinoco_cs_attach(void)
+static int
+orinoco_cs_attach(struct pcmcia_device *p_dev)
 {
 	struct net_device *dev;
 	struct orinoco_private *priv;
 	struct orinoco_pccard *card;
 	dev_link_t *link;
-	client_reg_t client_reg;
-	int ret;
 
 	dev = alloc_orinocodev(sizeof(*card), orinoco_cs_hard_reset);
 	if (! dev)
-		return NULL;
+		return -ENOMEM;
 	priv = netdev_priv(dev);
 	card = priv->card;
 
@@ -154,22 +136,15 @@ orinoco_cs_attach(void)
 	link->conf.IntType = INT_MEMORY_AND_IO;
 
 	/* Register with Card Services */
-	/* FIXME: need a lock? */
-	link->next = dev_list;
-	dev_list = link;
-
-	client_reg.dev_info = &dev_info;
-	client_reg.Version = 0x0210; /* FIXME: what does this mean? */
-	client_reg.event_callback_args.client_data = link;
-
-	ret = pcmcia_register_client(&link->handle, &client_reg);
-	if (ret != CS_SUCCESS) {
-		cs_error(link->handle, RegisterClient, ret);
-		orinoco_cs_detach(link);
-		return NULL;
-	}
+	link->next = NULL;
+
+	link->handle = p_dev;
+	p_dev->instance = link;
+
+	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+	orinoco_cs_config(link);
 
-	return link;
+	return 0;
 }				/* orinoco_cs_attach */
 
 /*
@@ -178,27 +153,14 @@ orinoco_cs_attach(void)
  * are freed.  Otherwise, the structures will be freed when the device
  * is released.
  */
-static void orinoco_cs_detach(dev_link_t *link)
+static void orinoco_cs_detach(struct pcmcia_device *p_dev)
 {
-	dev_link_t **linkp;
+	dev_link_t *link = dev_to_instance(p_dev);
 	struct net_device *dev = link->priv;
 
-	/* Locate device structure */
-	for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
-		if (*linkp == link)
-			break;
-
-	BUG_ON(*linkp == NULL);
-
 	if (link->state & DEV_CONFIG)
 		orinoco_cs_release(link);
 
-	/* Break the link with Card Services */
-	if (link->handle)
-		pcmcia_deregister_client(link->handle);
-
-	/* Unlink device structure, and free it */
-	*linkp = link->next;
 	DEBUG(0, PFX "detach: link=%p link->dev=%p\n", link, link->dev);
 	if (link->dev) {
 		DEBUG(0, PFX "About to unregister net device %p\n",
@@ -465,106 +427,82 @@ orinoco_cs_release(dev_link_t *link)
 		ioport_unmap(priv->hw.iobase);
 }				/* orinoco_cs_release */
 
-/*
- * The card status event handler.  Mostly, this schedules other stuff
- * to run after an event is received.
- */
-static int
-orinoco_cs_event(event_t event, int priority,
-		       event_callback_args_t * args)
+static int orinoco_cs_suspend(struct pcmcia_device *p_dev)
 {
-	dev_link_t *link = args->client_data;
+	dev_link_t *link = dev_to_instance(p_dev);
 	struct net_device *dev = link->priv;
 	struct orinoco_private *priv = netdev_priv(dev);
 	struct orinoco_pccard *card = priv->card;
 	int err = 0;
 	unsigned long flags;
 
-	switch (event) {
-	case CS_EVENT_CARD_REMOVAL:
-		link->state &= ~DEV_PRESENT;
-		if (link->state & DEV_CONFIG) {
-			unsigned long flags;
-
+	link->state |= DEV_SUSPEND;
+	if (link->state & DEV_CONFIG) {
+		/* This is probably racy, but I can't think of
+		   a better way, short of rewriting the PCMCIA
+		   layer to not suck :-( */
+		if (! test_bit(0, &card->hard_reset_in_progress)) {
 			spin_lock_irqsave(&priv->lock, flags);
+
+			err = __orinoco_down(dev);
+			if (err)
+				printk(KERN_WARNING "%s: Error %d downing interface\n",
+				       dev->name, err);
+
 			netif_device_detach(dev);
 			priv->hw_unavailable++;
+
 			spin_unlock_irqrestore(&priv->lock, flags);
 		}
-		break;
 
-	case CS_EVENT_CARD_INSERTION:
-		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-		orinoco_cs_config(link);
-		break;
+		pcmcia_release_configuration(link->handle);
+	}
 
-	case CS_EVENT_PM_SUSPEND:
-		link->state |= DEV_SUSPEND;
-		/* Fall through... */
-	case CS_EVENT_RESET_PHYSICAL:
-		/* Mark the device as stopped, to block IO until later */
-		if (link->state & DEV_CONFIG) {
-			/* This is probably racy, but I can't think of
-                           a better way, short of rewriting the PCMCIA
-                           layer to not suck :-( */
-			if (! test_bit(0, &card->hard_reset_in_progress)) {
-				spin_lock_irqsave(&priv->lock, flags);
-
-				err = __orinoco_down(dev);
-				if (err)
-					printk(KERN_WARNING "%s: %s: Error %d downing interface\n",
-					       dev->name,
-					       event == CS_EVENT_PM_SUSPEND ? "SUSPEND" : "RESET_PHYSICAL",
-					       err);
-				
-				netif_device_detach(dev);
-				priv->hw_unavailable++;
-
-				spin_unlock_irqrestore(&priv->lock, flags);
+	return 0;
+}
+
+static int orinoco_cs_resume(struct pcmcia_device *p_dev)
+{
+	dev_link_t *link = dev_to_instance(p_dev);
+	struct net_device *dev = link->priv;
+	struct orinoco_private *priv = netdev_priv(dev);
+	struct orinoco_pccard *card = priv->card;
+	int err = 0;
+	unsigned long flags;
+
+	link->state &= ~DEV_SUSPEND;
+	if (link->state & DEV_CONFIG) {
+		/* FIXME: should we double check that this is
+		 * the same card as we had before */
+		pcmcia_request_configuration(link->handle, &link->conf);
+
+		if (! test_bit(0, &card->hard_reset_in_progress)) {
+			err = orinoco_reinit_firmware(dev);
+			if (err) {
+				printk(KERN_ERR "%s: Error %d re-initializing firmware\n",
+				       dev->name, err);
+				return -EIO;
 			}
 
-			pcmcia_release_configuration(link->handle);
-		}
-		break;
+			spin_lock_irqsave(&priv->lock, flags);
+
+			netif_device_attach(dev);
+			priv->hw_unavailable--;
 
-	case CS_EVENT_PM_RESUME:
-		link->state &= ~DEV_SUSPEND;
-		/* Fall through... */
-	case CS_EVENT_CARD_RESET:
-		if (link->state & DEV_CONFIG) {
-			/* FIXME: should we double check that this is
-			 * the same card as we had before */
-			pcmcia_request_configuration(link->handle, &link->conf);
-
-			if (! test_bit(0, &card->hard_reset_in_progress)) {
-				err = orinoco_reinit_firmware(dev);
-				if (err) {
-					printk(KERN_ERR "%s: Error %d re-initializing firmware\n",
+			if (priv->open && ! priv->hw_unavailable) {
+				err = __orinoco_up(dev);
+				if (err)
+					printk(KERN_ERR "%s: Error %d restarting card\n",
 					       dev->name, err);
-					break;
-				}
-				
-				spin_lock_irqsave(&priv->lock, flags);
-				
-				netif_device_attach(dev);
-				priv->hw_unavailable--;
-				
-				if (priv->open && ! priv->hw_unavailable) {
-					err = __orinoco_up(dev);
-					if (err)
-						printk(KERN_ERR "%s: Error %d restarting card\n",
-						       dev->name, err);
-					
-				}
-
-				spin_unlock_irqrestore(&priv->lock, flags);
 			}
+
+			spin_unlock_irqrestore(&priv->lock, flags);
 		}
-		break;
 	}
 
-	return err;
-}				/* orinoco_cs_event */
+	return 0;
+}
+
 
 /********************************************************************/
 /* Module initialization					    */
@@ -665,10 +603,11 @@ static struct pcmcia_driver orinoco_driver = {
 	.drv		= {
 		.name	= DRIVER_NAME,
 	},
-	.attach		= orinoco_cs_attach,
-	.detach		= orinoco_cs_detach,
-	.event		= orinoco_cs_event,
+	.probe		= orinoco_cs_attach,
+	.remove		= orinoco_cs_detach,
 	.id_table       = orinoco_cs_ids,
+	.suspend	= orinoco_cs_suspend,
+	.resume		= orinoco_cs_resume,
 };
 
 static int __init
@@ -683,7 +622,6 @@ static void __exit
 exit_orinoco_cs(void)
 {
 	pcmcia_unregister_driver(&orinoco_driver);
-	BUG_ON(dev_list != NULL);
 }
 
 module_init(init_orinoco_cs);
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index 70fd6fd8feb9..319180ca7e71 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -92,9 +92,7 @@ module_param(pc_debug, int, 0);
 /** Prototypes based on PCMCIA skeleton driver *******************************/
 static void ray_config(dev_link_t *link);
 static void ray_release(dev_link_t *link);
-static int ray_event(event_t event, int priority, event_callback_args_t *args);
-static dev_link_t *ray_attach(void);
-static void ray_detach(dev_link_t *);
+static void ray_detach(struct pcmcia_device *p_dev);
 
 /***** Prototypes indicated by device structure ******************************/
 static int ray_dev_close(struct net_device *dev);
@@ -192,12 +190,6 @@ static int bc;
 static char *phy_addr = NULL;
 
 
-/* The dev_info variable is the "key" that is used to match up this
-   device driver with appropriate cards, through the card configuration
-   database.
-*/
-static dev_info_t dev_info = "ray_cs";
-
 /* A linked list of "instances" of the ray device.  Each actual
    PCMCIA card corresponds to one device instance, and is described
    by one dev_link_t structure (defined in ds.h).
@@ -314,12 +306,10 @@ static char rcsid[] = "Raylink/WebGear wireless LAN - Corey <Thomas corey@world.
     configure the card at this point -- we wait until we receive a
     card insertion event.
 =============================================================================*/
-static dev_link_t *ray_attach(void)
+static int ray_attach(struct pcmcia_device *p_dev)
 {
-    client_reg_t client_reg;
     dev_link_t *link;
     ray_dev_t *local;
-    int ret;
     struct net_device *dev;
     
     DEBUG(1, "ray_attach()\n");
@@ -328,7 +318,7 @@ static dev_link_t *ray_attach(void)
     link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
 
     if (!link)
-	    return NULL;
+	    return -ENOMEM;
 
     /* Allocate space for private device-specific data */
     dev = alloc_etherdev(sizeof(ray_dev_t));
@@ -387,30 +377,19 @@ static dev_link_t *ray_attach(void)
     dev->stop = &ray_dev_close;
     netif_stop_queue(dev);
 
-    /* Register with Card Services */
-    link->next = dev_list;
-    dev_list = link;
-    client_reg.dev_info = &dev_info;
-    client_reg.Version = 0x0210;
-    client_reg.event_callback_args.client_data = link;
+    init_timer(&local->timer);
 
-    DEBUG(2,"ray_cs ray_attach calling pcmcia_register_client(...)\n");
+    link->handle = p_dev;
+    p_dev->instance = link;
 
-    init_timer(&local->timer);
+    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+    ray_config(link);
 
-    ret = pcmcia_register_client(&link->handle, &client_reg);
-    if (ret != 0) {
-        printk("ray_cs ray_attach RegisterClient unhappy - detaching\n");
-        cs_error(link->handle, RegisterClient, ret);
-        ray_detach(link);
-        return NULL;
-    }
-    DEBUG(2,"ray_cs ray_attach ending\n");
-    return link;
+    return 0;
 
 fail_alloc_dev:
     kfree(link);
-    return NULL;
+    return -ENOMEM;
 } /* ray_attach */
 /*=============================================================================
     This deletes a driver "instance".  The device is de-registered
@@ -418,9 +397,12 @@ fail_alloc_dev:
     structures are freed.  Otherwise, the structures will be freed
     when the device is released.
 =============================================================================*/
-static void ray_detach(dev_link_t *link)
+static void ray_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     dev_link_t **linkp;
+    struct net_device *dev;
+    ray_dev_t *local;
 
     DEBUG(1, "ray_detach(0x%p)\n", link);
     
@@ -430,22 +412,18 @@ static void ray_detach(dev_link_t *link)
     if (*linkp == NULL)
         return;
 
-    /* If the device is currently configured and active, we won't
-      actually delete it yet.  Instead, it is marked so that when
-      the release() function is called, that will trigger a proper
-      detach().
-    */
-    if (link->state & DEV_CONFIG)
-        ray_release(link);
+    dev = link->priv;
+
+    if (link->state & DEV_CONFIG) {
+	    ray_release(link);
+
+	    local = (ray_dev_t *)dev->priv;
+            del_timer(&local->timer);
+    }
 
-    /* Break the link with Card Services */
-    if (link->handle)
-        pcmcia_deregister_client(link->handle);
-    
     /* Unlink device structure, free pieces */
     *linkp = link->next;
     if (link->priv) {
-        struct net_device *dev = link->priv;
 	if (link->dev) unregister_netdev(dev);
         free_netdev(dev);
     }
@@ -891,65 +869,40 @@ static void ray_release(dev_link_t *link)
     DEBUG(2,"ray_release ending\n");
 }
 
-/*=============================================================================
-    The card status event handler.  Mostly, this schedules other
-    stuff to run after an event is received.  A CARD_REMOVAL event
-    also sets some flags to discourage the net drivers from trying
-    to talk to the card any more.
-
-    When a CARD_REMOVAL event is received, we immediately set a flag
-    to block future accesses to this device.  All the functions that
-    actually access the device should check this flag to make sure
-    the card is still present.
-=============================================================================*/
-static int ray_event(event_t event, int priority,
-                     event_callback_args_t *args)
+static int ray_suspend(struct pcmcia_device *p_dev)
 {
-    dev_link_t *link = args->client_data;
-    struct net_device *dev = link->priv;
-    ray_dev_t *local = (ray_dev_t *)dev->priv;
-    DEBUG(1, "ray_event(0x%06x)\n", event);
-    
-    switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-        link->state &= ~DEV_PRESENT;
-        netif_device_detach(dev);
-        if (link->state & DEV_CONFIG) {
-	    ray_release(link);
-            del_timer(&local->timer);
-        }
-        break;
-    case CS_EVENT_CARD_INSERTION:
-        link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-        ray_config(link);
-        break;
-    case CS_EVENT_PM_SUSPEND:
-        link->state |= DEV_SUSPEND;
-        /* Fall through... */
-    case CS_EVENT_RESET_PHYSICAL:
+	dev_link_t *link = dev_to_instance(p_dev);
+	struct net_device *dev = link->priv;
+
+	link->state |= DEV_SUSPEND;
         if (link->state & DEV_CONFIG) {
-            if (link->open)
-            	netif_device_detach(dev);
+		if (link->open)
+			netif_device_detach(dev);
 
-            pcmcia_release_configuration(link->handle);
+		pcmcia_release_configuration(link->handle);
         }
-        break;
-    case CS_EVENT_PM_RESUME:
-        link->state &= ~DEV_SUSPEND;
-        /* Fall through... */
-    case CS_EVENT_CARD_RESET:
+
+
+	return 0;
+}
+
+static int ray_resume(struct pcmcia_device *p_dev)
+{
+	dev_link_t *link = dev_to_instance(p_dev);
+	struct net_device *dev = link->priv;
+
+	link->state &= ~DEV_SUSPEND;
         if (link->state & DEV_CONFIG) {
-            pcmcia_request_configuration(link->handle, &link->conf);
-            if (link->open) {
-                ray_reset(dev);
-		netif_device_attach(dev);
-            }
+		pcmcia_request_configuration(link->handle, &link->conf);
+		if (link->open) {
+			ray_reset(dev);
+			netif_device_attach(dev);
+		}
         }
-        break;
-    }
-    return 0;
-    DEBUG(2,"ray_event ending\n");
-} /* ray_event */
+
+	return 0;
+}
+
 /*===========================================================================*/
 int ray_dev_init(struct net_device *dev)
 {
@@ -2945,10 +2898,11 @@ static struct pcmcia_driver ray_driver = {
 	.drv		= {
 		.name	= "ray_cs",
 	},
-	.attach		= ray_attach,
-	.event		= ray_event,
-	.detach		= ray_detach,
+	.probe		= ray_attach,
+	.remove		= ray_detach,
 	.id_table       = ray_ids,
+	.suspend	= ray_suspend,
+	.resume		= ray_resume,
 };
 
 static int __init init_ray_cs(void)
diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c
index b1bbc8e8e91f..fee4be1ce810 100644
--- a/drivers/net/wireless/spectrum_cs.c
+++ b/drivers/net/wireless/spectrum_cs.c
@@ -57,17 +57,6 @@ module_param(ignore_cis_vcc, int, 0);
 MODULE_PARM_DESC(ignore_cis_vcc, "Allow voltage mismatch between card and socket");
 
 /********************************************************************/
-/* Magic constants						    */
-/********************************************************************/
-
-/*
- * The dev_info variable is the "key" that is used to match up this
- * device driver with appropriate cards, through the card
- * configuration database.
- */
-static dev_info_t dev_info = DRIVER_NAME;
-
-/********************************************************************/
 /* Data structures						    */
 /********************************************************************/
 
@@ -78,19 +67,12 @@ struct orinoco_pccard {
 	dev_node_t node;
 };
 
-/*
- * A linked list of "instances" of the device.  Each actual PCMCIA
- * card corresponds to one device instance, and is described by one
- * dev_link_t structure (defined in ds.h).
- */
-static dev_link_t *dev_list; /* = NULL */
-
 /********************************************************************/
 /* Function prototypes						    */
 /********************************************************************/
 
+static void spectrum_cs_config(dev_link_t *link);
 static void spectrum_cs_release(dev_link_t *link);
-static void spectrum_cs_detach(dev_link_t *link);
 
 /********************************************************************/
 /* Firmware downloader						    */
@@ -601,19 +583,17 @@ spectrum_cs_hard_reset(struct orinoco_private *priv)
  * The dev_link structure is initialized, but we don't actually
  * configure the card at this point -- we wait until we receive a card
  * insertion event.  */
-static dev_link_t *
-spectrum_cs_attach(void)
+static int
+spectrum_cs_attach(struct pcmcia_device *p_dev)
 {
 	struct net_device *dev;
 	struct orinoco_private *priv;
 	struct orinoco_pccard *card;
 	dev_link_t *link;
-	client_reg_t client_reg;
-	int ret;
 
 	dev = alloc_orinocodev(sizeof(*card), spectrum_cs_hard_reset);
 	if (! dev)
-		return NULL;
+		return -ENOMEM;
 	priv = netdev_priv(dev);
 	card = priv->card;
 
@@ -635,23 +615,13 @@ spectrum_cs_attach(void)
 	link->conf.Attributes = 0;
 	link->conf.IntType = INT_MEMORY_AND_IO;
 
-	/* Register with Card Services */
-	/* FIXME: need a lock? */
-	link->next = dev_list;
-	dev_list = link;
+	link->handle = p_dev;
+	p_dev->instance = link;
 
-	client_reg.dev_info = &dev_info;
-	client_reg.Version = 0x0210; /* FIXME: what does this mean? */
-	client_reg.event_callback_args.client_data = link;
+	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+	spectrum_cs_config(link);
 
-	ret = pcmcia_register_client(&link->handle, &client_reg);
-	if (ret != CS_SUCCESS) {
-		cs_error(link->handle, RegisterClient, ret);
-		spectrum_cs_detach(link);
-		return NULL;
-	}
-
-	return link;
+	return 0;
 }				/* spectrum_cs_attach */
 
 /*
@@ -660,27 +630,14 @@ spectrum_cs_attach(void)
  * are freed.  Otherwise, the structures will be freed when the device
  * is released.
  */
-static void spectrum_cs_detach(dev_link_t *link)
+static void spectrum_cs_detach(struct pcmcia_device *p_dev)
 {
-	dev_link_t **linkp;
+	dev_link_t *link = dev_to_instance(p_dev);
 	struct net_device *dev = link->priv;
 
-	/* Locate device structure */
-	for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
-		if (*linkp == link)
-			break;
-
-	BUG_ON(*linkp == NULL);
-
 	if (link->state & DEV_CONFIG)
 		spectrum_cs_release(link);
 
-	/* Break the link with Card Services */
-	if (link->handle)
-		pcmcia_deregister_client(link->handle);
-
-	/* Unlink device structure, and free it */
-	*linkp = link->next;
 	DEBUG(0, PFX "detach: link=%p link->dev=%p\n", link, link->dev);
 	if (link->dev) {
 		DEBUG(0, PFX "About to unregister net device %p\n",
@@ -948,82 +905,56 @@ spectrum_cs_release(dev_link_t *link)
 		ioport_unmap(priv->hw.iobase);
 }				/* spectrum_cs_release */
 
-/*
- * The card status event handler.  Mostly, this schedules other stuff
- * to run after an event is received.
- */
+
 static int
-spectrum_cs_event(event_t event, int priority,
-		       event_callback_args_t * args)
+spectrum_cs_suspend(struct pcmcia_device *p_dev)
 {
-	dev_link_t *link = args->client_data;
+	dev_link_t *link = dev_to_instance(p_dev);
 	struct net_device *dev = link->priv;
 	struct orinoco_private *priv = netdev_priv(dev);
-	int err = 0;
 	unsigned long flags;
+	int err = 0;
 
-	switch (event) {
-	case CS_EVENT_CARD_REMOVAL:
-		link->state &= ~DEV_PRESENT;
-		if (link->state & DEV_CONFIG) {
-			unsigned long flags;
+	link->state |= DEV_SUSPEND;
+	/* Mark the device as stopped, to block IO until later */
+	if (link->state & DEV_CONFIG) {
+		spin_lock_irqsave(&priv->lock, flags);
 
-			spin_lock_irqsave(&priv->lock, flags);
-			netif_device_detach(dev);
-			priv->hw_unavailable++;
-			spin_unlock_irqrestore(&priv->lock, flags);
-		}
-		break;
+		err = __orinoco_down(dev);
+		if (err)
+			printk(KERN_WARNING "%s: Error %d downing interface\n",
+			       dev->name, err);
 
-	case CS_EVENT_CARD_INSERTION:
-		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-		spectrum_cs_config(link);
-		break;
+		netif_device_detach(dev);
+		priv->hw_unavailable++;
 
-	case CS_EVENT_PM_SUSPEND:
-		link->state |= DEV_SUSPEND;
-		/* Fall through... */
-	case CS_EVENT_RESET_PHYSICAL:
-		/* Mark the device as stopped, to block IO until later */
-		if (link->state & DEV_CONFIG) {
-			/* This is probably racy, but I can't think of
-                           a better way, short of rewriting the PCMCIA
-                           layer to not suck :-( */
-			spin_lock_irqsave(&priv->lock, flags);
-
-			err = __orinoco_down(dev);
-			if (err)
-				printk(KERN_WARNING "%s: %s: Error %d downing interface\n",
-				       dev->name,
-				       event == CS_EVENT_PM_SUSPEND ? "SUSPEND" : "RESET_PHYSICAL",
-				       err);
-
-			netif_device_detach(dev);
-			priv->hw_unavailable++;
-
-			spin_unlock_irqrestore(&priv->lock, flags);
-
-			pcmcia_release_configuration(link->handle);
-		}
-		break;
+		spin_unlock_irqrestore(&priv->lock, flags);
 
-	case CS_EVENT_PM_RESUME:
-		link->state &= ~DEV_SUSPEND;
-		/* Fall through... */
-	case CS_EVENT_CARD_RESET:
-		if (link->state & DEV_CONFIG) {
-			/* FIXME: should we double check that this is
-			 * the same card as we had before */
-			pcmcia_request_configuration(link->handle, &link->conf);
-			netif_device_attach(dev);
-			priv->hw_unavailable--;
-			schedule_work(&priv->reset_work);
-		}
-		break;
+		pcmcia_release_configuration(link->handle);
+	}
+
+	return 0;
+}
+
+static int
+spectrum_cs_resume(struct pcmcia_device *p_dev)
+{
+	dev_link_t *link = dev_to_instance(p_dev);
+	struct net_device *dev = link->priv;
+	struct orinoco_private *priv = netdev_priv(dev);
+
+	link->state &= ~DEV_SUSPEND;
+	if (link->state & DEV_CONFIG) {
+		/* FIXME: should we double check that this is
+		 * the same card as we had before */
+		pcmcia_request_configuration(link->handle, &link->conf);
+		netif_device_attach(dev);
+		priv->hw_unavailable--;
+		schedule_work(&priv->reset_work);
 	}
+	return 0;
+}
 
-	return err;
-}				/* spectrum_cs_event */
 
 /********************************************************************/
 /* Module initialization					    */
@@ -1048,9 +979,10 @@ static struct pcmcia_driver orinoco_driver = {
 	.drv		= {
 		.name	= DRIVER_NAME,
 	},
-	.attach		= spectrum_cs_attach,
-	.detach		= spectrum_cs_detach,
-	.event		= spectrum_cs_event,
+	.probe		= spectrum_cs_attach,
+	.remove		= spectrum_cs_detach,
+	.suspend	= spectrum_cs_suspend,
+	.resume		= spectrum_cs_resume,
 	.id_table       = spectrum_cs_ids,
 };
 
@@ -1066,7 +998,6 @@ static void __exit
 exit_spectrum_cs(void)
 {
 	pcmcia_unregister_driver(&orinoco_driver);
-	BUG_ON(dev_list != NULL);
 }
 
 module_init(init_spectrum_cs);
diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c
index c822cad3333f..7e2039f52c49 100644
--- a/drivers/net/wireless/wavelan_cs.c
+++ b/drivers/net/wireless/wavelan_cs.c
@@ -4594,14 +4594,12 @@ wavelan_close(struct net_device *	dev)
  * configure the card at this point -- we wait until we receive a
  * card insertion event.
  */
-static dev_link_t *
-wavelan_attach(void)
+static int
+wavelan_attach(struct pcmcia_device *p_dev)
 {
-  client_reg_t	client_reg;	/* Register with cardmgr */
   dev_link_t *	link;		/* Info for cardmgr */
   struct net_device *	dev;		/* Interface generic data */
   net_local *	lp;		/* Interface specific data */
-  int		ret;
 
 #ifdef DEBUG_CALLBACK_TRACE
   printk(KERN_DEBUG "-> wavelan_attach()\n");
@@ -4609,7 +4607,7 @@ wavelan_attach(void)
 
   /* Initialize the dev_link_t structure */
   link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL);
-  if (!link) return NULL;
+  if (!link) return -ENOMEM;
 
   /* The io structure describes IO port mapping */
   link->io.NumPorts1 = 8;
@@ -4627,14 +4625,13 @@ wavelan_attach(void)
   link->conf.IntType = INT_MEMORY_AND_IO;
 
   /* Chain drivers */
-  link->next = dev_list;
-  dev_list = link;
+  link->next = NULL;
 
   /* Allocate the generic data structure */
   dev = alloc_etherdev(sizeof(net_local));
   if (!dev) {
       kfree(link);
-      return NULL;
+      return -ENOMEM;
   }
   link->priv = link->irq.Instance = dev;
 
@@ -4679,28 +4676,21 @@ wavelan_attach(void)
   /* Other specific data */
   dev->mtu = WAVELAN_MTU;
 
-  /* Register with Card Services */
-  client_reg.dev_info = &dev_info;
-  client_reg.Version = 0x0210;
-  client_reg.event_callback_args.client_data = link;
+  link->handle = p_dev;
+  p_dev->instance = link;
 
-#ifdef DEBUG_CONFIG_INFO
-  printk(KERN_DEBUG "wavelan_attach(): almost done, calling pcmcia_register_client\n");
-#endif
-
-  ret = pcmcia_register_client(&link->handle, &client_reg);
-  if(ret != 0)
-    {
-      cs_error(link->handle, RegisterClient, ret);
-      wavelan_detach(link);
-      return NULL;
-    }
+  link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+  if(wv_pcmcia_config(link) &&
+     wv_hw_config(dev))
+	  wv_init_info(dev);
+  else
+	  dev->irq = 0;
 
 #ifdef DEBUG_CALLBACK_TRACE
   printk(KERN_DEBUG "<- wavelan_attach()\n");
 #endif
 
-  return link;
+  return 0;
 }
 
 /*------------------------------------------------------------------*/
@@ -4711,8 +4701,10 @@ wavelan_attach(void)
  * is released.
  */
 static void
-wavelan_detach(dev_link_t *	link)
+wavelan_detach(struct pcmcia_device *p_dev)
 {
+   dev_link_t *link = dev_to_instance(p_dev);
+
 #ifdef DEBUG_CALLBACK_TRACE
   printk(KERN_DEBUG "-> wavelan_detach(0x%p)\n", link);
 #endif
@@ -4729,31 +4721,6 @@ wavelan_detach(dev_link_t *	link)
       wv_pcmcia_release(link);
     }
 
-  /* Break the link with Card Services */
-  if(link->handle)
-    pcmcia_deregister_client(link->handle);
-    
-  /* Remove the interface data from the linked list */
-  if(dev_list == link)
-    dev_list = link->next;
-  else
-    {
-      dev_link_t *	prev = dev_list;
-
-      while((prev != (dev_link_t *) NULL) && (prev->next != link))
-	prev = prev->next;
-
-      if(prev == (dev_link_t *) NULL)
-	{
-#ifdef DEBUG_CONFIG_ERRORS
-	  printk(KERN_WARNING "wavelan_detach : Attempting to remove a nonexistent device.\n");
-#endif
-	  return;
-	}
-
-      prev->next = link->next;
-    }
-
   /* Free pieces */
   if(link->priv)
     {
@@ -4775,65 +4742,11 @@ wavelan_detach(dev_link_t *	link)
 #endif
 }
 
-/*------------------------------------------------------------------*/
-/*
- * The card status event handler. Mostly, this schedules other stuff
- * to run after an event is received. A CARD_REMOVAL event also sets
- * some flags to discourage the net drivers from trying to talk to the
- * card any more.
- */
-static int
-wavelan_event(event_t		event,		/* The event received */
-	      int		priority,
-	      event_callback_args_t *	args)
+static int wavelan_suspend(struct pcmcia_device *p_dev)
 {
-  dev_link_t *	link = (dev_link_t *) args->client_data;
-  struct net_device *	dev = (struct net_device *) link->priv;
-
-#ifdef DEBUG_CALLBACK_TRACE
-  printk(KERN_DEBUG "->wavelan_event(): %s\n",
-	 ((event == CS_EVENT_REGISTRATION_COMPLETE)?"registration complete" :
-	  ((event == CS_EVENT_CARD_REMOVAL) ? "card removal" :
-	   ((event == CS_EVENT_CARD_INSERTION) ? "card insertion" :
-	    ((event == CS_EVENT_PM_SUSPEND) ? "pm suspend" :
-	     ((event == CS_EVENT_RESET_PHYSICAL) ? "physical reset" :
-	      ((event == CS_EVENT_PM_RESUME) ? "pm resume" :
-	       ((event == CS_EVENT_CARD_RESET) ? "card reset" :
-		"unknown"))))))));
-#endif
-
-    switch(event)
-      {
-      case CS_EVENT_REGISTRATION_COMPLETE:
-#ifdef DEBUG_CONFIG_INFO
-	printk(KERN_DEBUG "wavelan_cs: registration complete\n");
-#endif
-	break;
+	dev_link_t *link = dev_to_instance(p_dev);
+	struct net_device *	dev = (struct net_device *) link->priv;
 
-      case CS_EVENT_CARD_REMOVAL:
-	/* Oups ! The card is no more there */
-	link->state &= ~DEV_PRESENT;
-	if(link->state & DEV_CONFIG)
-	  {
-	    /* Accept no more transmissions */
-	    netif_device_detach(dev);
-
-	    /* Release the card */
-	    wv_pcmcia_release(link);
-	  }
-	break;
-
-      case CS_EVENT_CARD_INSERTION:
-	/* Reset and configure the card */
-	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-	if(wv_pcmcia_config(link) &&
-	   wv_hw_config(dev))
-	  wv_init_info(dev);
-	else
-	  dev->irq = 0;
-	break;
-
-      case CS_EVENT_PM_SUSPEND:
 	/* NB: wavelan_close will be called, but too late, so we are
 	 * obliged to close nicely the wavelan here. David, could you
 	 * close the device before suspending them ? And, by the way,
@@ -4848,38 +4761,37 @@ wavelan_event(event_t		event,		/* The event received */
 
 	/* The card is now suspended */
 	link->state |= DEV_SUSPEND;
-	/* Fall through... */
-      case CS_EVENT_RESET_PHYSICAL:
+
     	if(link->state & DEV_CONFIG)
-	  {
-      	    if(link->open)
-	      netif_device_detach(dev);
-      	    pcmcia_release_configuration(link->handle);
-	  }
-	break;
+	{
+		if(link->open)
+			netif_device_detach(dev);
+		pcmcia_release_configuration(link->handle);
+	}
+
+	return 0;
+}
+
+static int wavelan_resume(struct pcmcia_device *p_dev)
+{
+	dev_link_t *link = dev_to_instance(p_dev);
+	struct net_device *	dev = (struct net_device *) link->priv;
 
-      case CS_EVENT_PM_RESUME:
 	link->state &= ~DEV_SUSPEND;
-	/* Fall through... */
-      case CS_EVENT_CARD_RESET:
 	if(link->state & DEV_CONFIG)
-	  {
-      	    pcmcia_request_configuration(link->handle, &link->conf);
-      	    if(link->open)	/* If RESET -> True, If RESUME -> False ? */
-	      {
-		wv_hw_reset(dev);
-		netif_device_attach(dev);
-	      }
-	  }
-	break;
-    }
+	{
+		pcmcia_request_configuration(link->handle, &link->conf);
+		if(link->open)	/* If RESET -> True, If RESUME -> False ? */
+		{
+			wv_hw_reset(dev);
+			netif_device_attach(dev);
+		}
+	}
 
-#ifdef DEBUG_CALLBACK_TRACE
-  printk(KERN_DEBUG "<-wavelan_event()\n");
-#endif
-  return 0;
+	return 0;
 }
 
+
 static struct pcmcia_device_id wavelan_ids[] = {
 	PCMCIA_DEVICE_PROD_ID12("AT&T","WaveLAN/PCMCIA", 0xe7c5affd, 0x1bc50975),
 	PCMCIA_DEVICE_PROD_ID12("Digital", "RoamAbout/DS", 0x9999ab35, 0x00d05e06),
@@ -4894,10 +4806,11 @@ static struct pcmcia_driver wavelan_driver = {
 	.drv		= {
 		.name	= "wavelan_cs",
 	},
-	.attach		= wavelan_attach,
-	.event		= wavelan_event,
-	.detach		= wavelan_detach,
+	.probe		= wavelan_attach,
+	.remove		= wavelan_detach,
 	.id_table       = wavelan_ids,
+	.suspend	= wavelan_suspend,
+	.resume		= wavelan_resume,
 };
 
 static int __init
diff --git a/drivers/net/wireless/wavelan_cs.p.h b/drivers/net/wireless/wavelan_cs.p.h
index 724a715089c9..f2d597568151 100644
--- a/drivers/net/wireless/wavelan_cs.p.h
+++ b/drivers/net/wireless/wavelan_cs.p.h
@@ -754,20 +754,11 @@ static void
 static int
 	wavelan_open(struct net_device *),		/* Open the device */
 	wavelan_close(struct net_device *);	/* Close the device */
-static dev_link_t *
-	wavelan_attach(void);		/* Create a new device */
 static void
-	wavelan_detach(dev_link_t *);	/* Destroy a removed device */
-static int
-	wavelan_event(event_t,		/* Manage pcmcia events */
-		      int,
-		      event_callback_args_t *);
+	wavelan_detach(struct pcmcia_device *p_dev);	/* Destroy a removed device */
 
 /**************************** VARIABLES ****************************/
 
-static dev_info_t dev_info = "wavelan_cs";
-static dev_link_t *dev_list = NULL;	/* Linked list of devices */
-
 /*
  * Parameters that can be set with 'insmod'
  * The exact syntax is 'insmod wavelan_cs.o <var>=<value>'
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c
index 978fdc606781..48e10b0c7e74 100644
--- a/drivers/net/wireless/wl3501_cs.c
+++ b/drivers/net/wireless/wl3501_cs.c
@@ -105,7 +105,6 @@ module_param(pc_debug, int, 0);
  */
 static void wl3501_config(dev_link_t *link);
 static void wl3501_release(dev_link_t *link);
-static int wl3501_event(event_t event, int pri, event_callback_args_t *args);
 
 /*
  * The dev_info variable is the "key" that is used to match up this
@@ -1498,9 +1497,11 @@ static struct ethtool_ops ops = {
  * Services. If it has been released, all local data structures are freed.
  * Otherwise, the structures will be freed when the device is released.
  */
-static void wl3501_detach(dev_link_t *link)
+static void wl3501_detach(struct pcmcia_device *p_dev)
 {
+	dev_link_t *link = dev_to_instance(p_dev);
 	dev_link_t **linkp;
+	struct net_device *dev = link->priv;
 
 	/* Locate device structure */
 	for (linkp = &wl3501_dev_list; *linkp; linkp = &(*linkp)->next)
@@ -1514,16 +1515,12 @@ static void wl3501_detach(dev_link_t *link)
 	 * function is called, that will trigger a proper detach(). */
 
 	if (link->state & DEV_CONFIG) {
-#ifdef PCMCIA_DEBUG
-		printk(KERN_DEBUG "wl3501_cs: detach postponed, '%s' "
-		       "still locked\n", link->dev->dev_name);
-#endif
-		goto out;
-	}
+		while (link->open > 0)
+			wl3501_close(dev);
 
-	/* Break the link with Card Services */
-	if (link->handle)
-		pcmcia_deregister_client(link->handle);
+		netif_device_detach(dev);
+		wl3501_release(link);
+	}
 
 	/* Unlink device structure, free pieces */
 	*linkp = link->next;
@@ -1956,18 +1953,16 @@ static const struct iw_handler_def wl3501_handler_def = {
  * The dev_link structure is initialized, but we don't actually configure the
  * card at this point -- we wait until we receive a card insertion event.
  */
-static dev_link_t *wl3501_attach(void)
+static int wl3501_attach(struct pcmcia_device *p_dev)
 {
-	client_reg_t client_reg;
 	dev_link_t *link;
 	struct net_device *dev;
 	struct wl3501_card *this;
-	int ret;
 
 	/* Initialize the dev_link_t structure */
 	link = kzalloc(sizeof(*link), GFP_KERNEL);
 	if (!link)
-		goto out;
+		return -ENOMEM;
 
 	/* The io structure describes IO port mapping */
 	link->io.NumPorts1	= 16;
@@ -2003,24 +1998,17 @@ static dev_link_t *wl3501_attach(void)
 	netif_stop_queue(dev);
 	link->priv = link->irq.Instance = dev;
 
-	/* Register with Card Services */
-	link->next		 = wl3501_dev_list;
-	wl3501_dev_list		 = link;
-	client_reg.dev_info	 = &wl3501_dev_info;
-	client_reg.Version	 = 0x0210;
-	client_reg.event_callback_args.client_data = link;
-	ret = pcmcia_register_client(&link->handle, &client_reg);
-	if (ret) {
-		cs_error(link->handle, RegisterClient, ret);
-		wl3501_detach(link);
-		link = NULL;
-	}
-out:
-	return link;
+	link->handle = p_dev;
+	p_dev->instance = link;
+
+	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+	wl3501_config(link);
+
+	return 0;
 out_link:
 	kfree(link);
 	link = NULL;
-	goto out;
+	return -ENOMEM;
 }
 
 #define CS_CHECK(fn, ret) \
@@ -2173,67 +2161,41 @@ static void wl3501_release(dev_link_t *link)
 	link->state &= ~DEV_CONFIG;
 }
 
-/**
- * wl3501_event - The card status event handler
- * @event - event
- * @pri - priority
- * @args - arguments for this event
- *
- * The card status event handler. Mostly, this schedules other stuff to run
- * after an event is received. A CARD_REMOVAL event also sets some flags to
- * discourage the net drivers from trying to talk to the card any more.
- *
- * When a CARD_REMOVAL event is received, we immediately set a flag to block
- * future accesses to this device. All the functions that actually access the
- * device should check this flag to make sure the card is still present.
- */
-static int wl3501_event(event_t event, int pri, event_callback_args_t *args)
+static int wl3501_suspend(struct pcmcia_device *p_dev)
 {
-	dev_link_t *link = args->client_data;
+	dev_link_t *link = dev_to_instance(p_dev);
 	struct net_device *dev = link->priv;
 
-	switch (event) {
-	case CS_EVENT_CARD_REMOVAL:
-		link->state &= ~DEV_PRESENT;
-		if (link->state & DEV_CONFIG) {
-			while (link->open > 0)
-				wl3501_close(dev);
+	link->state |= DEV_SUSPEND;
+
+	wl3501_pwr_mgmt(dev->priv, WL3501_SUSPEND);
+	if (link->state & DEV_CONFIG) {
+		if (link->open)
 			netif_device_detach(dev);
-			wl3501_release(link);
-		}
-		break;
-	case CS_EVENT_CARD_INSERTION:
-		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-		wl3501_config(link);
-		break;
-	case CS_EVENT_PM_SUSPEND:
-		link->state |= DEV_SUSPEND;
-		wl3501_pwr_mgmt(dev->priv, WL3501_SUSPEND);
-		/* Fall through... */
-	case CS_EVENT_RESET_PHYSICAL:
-		if (link->state & DEV_CONFIG) {
-			if (link->open)
-				netif_device_detach(dev);
-			pcmcia_release_configuration(link->handle);
-		}
-		break;
-	case CS_EVENT_PM_RESUME:
-		link->state &= ~DEV_SUSPEND;
-		wl3501_pwr_mgmt(dev->priv, WL3501_RESUME);
-		/* Fall through... */
-	case CS_EVENT_CARD_RESET:
-		if (link->state & DEV_CONFIG) {
-			pcmcia_request_configuration(link->handle, &link->conf);
-			if (link->open) {
-				wl3501_reset(dev);
-				netif_device_attach(dev);
-			}
+		pcmcia_release_configuration(link->handle);
+	}
+
+	return 0;
+}
+
+static int wl3501_resume(struct pcmcia_device *p_dev)
+{
+	dev_link_t *link = dev_to_instance(p_dev);
+	struct net_device *dev = link->priv;
+
+	wl3501_pwr_mgmt(dev->priv, WL3501_RESUME);
+	if (link->state & DEV_CONFIG) {
+		pcmcia_request_configuration(link->handle, &link->conf);
+		if (link->open) {
+			wl3501_reset(dev);
+			netif_device_attach(dev);
 		}
-		break;
 	}
+
 	return 0;
 }
 
+
 static struct pcmcia_device_id wl3501_ids[] = {
 	PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0001),
 	PCMCIA_DEVICE_NULL
@@ -2245,10 +2207,11 @@ static struct pcmcia_driver wl3501_driver = {
 	.drv		= {
 		.name	= "wl3501_cs",
 	},
-	.attach		= wl3501_attach,
-	.event		= wl3501_event,
-	.detach		= wl3501_detach,
+	.probe		= wl3501_attach,
+	.remove		= wl3501_detach,
 	.id_table	= wl3501_ids,
+	.suspend	= wl3501_suspend,
+	.resume		= wl3501_resume,
 };
 
 static int __init wl3501_init_module(void)
diff --git a/drivers/parport/Kconfig b/drivers/parport/Kconfig
index 725a14119f2a..b8241561da45 100644
--- a/drivers/parport/Kconfig
+++ b/drivers/parport/Kconfig
@@ -77,7 +77,7 @@ config PARPORT_PC_SUPERIO
 
 config PARPORT_PC_PCMCIA
 	tristate "Support for PCMCIA management for PC-style ports"
-	depends on PARPORT!=n && (PCMCIA!=n && PARPORT_PC=m && PARPORT_PC || PARPORT_PC=y && PCMCIA)
+	depends on PCMCIA && PARPORT_PC
 	help
 	  Say Y here if you need PCMCIA support for your PC-style parallel
 	  ports. If unsure, say N.
diff --git a/drivers/parport/daisy.c b/drivers/parport/daisy.c
index 075c7eb5c85d..9ee67321b630 100644
--- a/drivers/parport/daisy.c
+++ b/drivers/parport/daisy.c
@@ -144,9 +144,9 @@ again:
 	add_dev (numdevs++, port, -1);
 
 	/* Find out the legacy device's IEEE 1284 device ID. */
-	deviceid = kmalloc (1000, GFP_KERNEL);
+	deviceid = kmalloc (1024, GFP_KERNEL);
 	if (deviceid) {
-		if (parport_device_id (numdevs - 1, deviceid, 1000) > 2)
+		if (parport_device_id (numdevs - 1, deviceid, 1024) > 2)
 			detected++;
 
 		kfree (deviceid);
@@ -252,7 +252,7 @@ struct pardevice *parport_open (int devnum, const char *name,
 		selected = port->daisy;
 		parport_release (dev);
 
-		if (selected != port->daisy) {
+		if (selected != daisy) {
 			/* No corresponding device. */
 			parport_unregister_device (dev);
 			return NULL;
@@ -344,9 +344,9 @@ static int cpp_daisy (struct parport *port, int cmd)
 			      PARPORT_CONTROL_STROBE,
 			      PARPORT_CONTROL_STROBE);
 	udelay (1);
+	s = parport_read_status (port);
 	parport_frob_control (port, PARPORT_CONTROL_STROBE, 0);
 	udelay (1);
-	s = parport_read_status (port);
 	parport_write_data (port, 0xff); udelay (2);
 
 	return s;
@@ -395,15 +395,15 @@ int parport_daisy_select (struct parport *port, int daisy, int mode)
 		case IEEE1284_MODE_EPP:
 		case IEEE1284_MODE_EPPSL:
 		case IEEE1284_MODE_EPPSWE:
-			return (cpp_daisy (port, 0x20 + daisy) &
-				PARPORT_STATUS_ERROR);
+			return !(cpp_daisy (port, 0x20 + daisy) &
+				 PARPORT_STATUS_ERROR);
 
 		// For these modes we should switch to ECP mode:
 		case IEEE1284_MODE_ECP:
 		case IEEE1284_MODE_ECPRLE:
 		case IEEE1284_MODE_ECPSWE: 
-			return (cpp_daisy (port, 0xd0 + daisy) &
-				PARPORT_STATUS_ERROR);
+			return !(cpp_daisy (port, 0xd0 + daisy) &
+				 PARPORT_STATUS_ERROR);
 
 		// Nothing was told for BECP in Daisy chain specification.
 		// May be it's wise to use ECP?
@@ -413,8 +413,8 @@ int parport_daisy_select (struct parport *port, int daisy, int mode)
 		case IEEE1284_MODE_BYTE:
 		case IEEE1284_MODE_COMPAT:
 		default:
-			return (cpp_daisy (port, 0xe0 + daisy) &
-				PARPORT_STATUS_ERROR);
+			return !(cpp_daisy (port, 0xe0 + daisy) &
+				 PARPORT_STATUS_ERROR);
 	}
 }
 
@@ -436,7 +436,7 @@ static int select_port (struct parport *port)
 
 static int assign_addrs (struct parport *port)
 {
-	unsigned char s, last_dev;
+	unsigned char s;
 	unsigned char daisy;
 	int thisdev = numdevs;
 	int detected;
@@ -472,10 +472,13 @@ static int assign_addrs (struct parport *port)
 	}
 
 	parport_write_data (port, 0x78); udelay (2);
-	last_dev = 0; /* We've just been speaking to a device, so we
-			 know there must be at least _one_ out there. */
+	s = parport_read_status (port);
 
-	for (daisy = 0; daisy < 4; daisy++) {
+	for (daisy = 0;
+	     (s & (PARPORT_STATUS_PAPEROUT|PARPORT_STATUS_SELECT))
+		     == (PARPORT_STATUS_PAPEROUT|PARPORT_STATUS_SELECT)
+		     && daisy < 4;
+	     ++daisy) {
 		parport_write_data (port, daisy);
 		udelay (2);
 		parport_frob_control (port,
@@ -485,14 +488,18 @@ static int assign_addrs (struct parport *port)
 		parport_frob_control (port, PARPORT_CONTROL_STROBE, 0);
 		udelay (1);
 
-		if (last_dev)
-			/* No more devices. */
-			break;
+		add_dev (numdevs++, port, daisy);
 
-		last_dev = !(parport_read_status (port)
-			     & PARPORT_STATUS_BUSY);
+		/* See if this device thought it was the last in the
+		 * chain. */
+		if (!(s & PARPORT_STATUS_BUSY))
+			break;
 
-		add_dev (numdevs++, port, daisy);
+		/* We are seeing pass through status now. We see
+		   last_dev from next device or if last_dev does not
+		   work status lines from some non-daisy chain
+		   device. */
+		s = parport_read_status (port);
 	}
 
 	parport_write_data (port, 0xff); udelay (2);
@@ -501,11 +508,11 @@ static int assign_addrs (struct parport *port)
 		 detected);
 
 	/* Ask the new devices to introduce themselves. */
-	deviceid = kmalloc (1000, GFP_KERNEL);
+	deviceid = kmalloc (1024, GFP_KERNEL);
 	if (!deviceid) return 0;
 
 	for (daisy = 0; thisdev < numdevs; thisdev++, daisy++)
-		parport_device_id (thisdev, deviceid, 1000);
+		parport_device_id (thisdev, deviceid, 1024);
 
 	kfree (deviceid);
 	return detected;
diff --git a/drivers/parport/ieee1284_ops.c b/drivers/parport/ieee1284_ops.c
index ce1e2aad8b10..d6c77658231e 100644
--- a/drivers/parport/ieee1284_ops.c
+++ b/drivers/parport/ieee1284_ops.c
@@ -165,17 +165,7 @@ size_t parport_ieee1284_read_nibble (struct parport *port,
 		/* Does the error line indicate end of data? */
 		if (((i & 1) == 0) &&
 		    (parport_read_status(port) & PARPORT_STATUS_ERROR)) {
-			port->physport->ieee1284.phase = IEEE1284_PH_HBUSY_DNA;
-			DPRINTK (KERN_DEBUG
-				"%s: No more nibble data (%d bytes)\n",
-				port->name, i/2);
-
-			/* Go to reverse idle phase. */
-			parport_frob_control (port,
-					      PARPORT_CONTROL_AUTOFD,
-					      PARPORT_CONTROL_AUTOFD);
-			port->physport->ieee1284.phase = IEEE1284_PH_REV_IDLE;
-			break;
+			goto end_of_data;
 		}
 
 		/* Event 7: Set nAutoFd low. */
@@ -225,18 +215,25 @@ size_t parport_ieee1284_read_nibble (struct parport *port,
 			byte = nibble;
 	}
 
-	i /= 2; /* i is now in bytes */
-
 	if (i == len) {
 		/* Read the last nibble without checking data avail. */
-		port = port->physport;
-		if (parport_read_status (port) & PARPORT_STATUS_ERROR)
-			port->ieee1284.phase = IEEE1284_PH_HBUSY_DNA;
+		if (parport_read_status (port) & PARPORT_STATUS_ERROR) {
+		end_of_data:
+			DPRINTK (KERN_DEBUG
+				"%s: No more nibble data (%d bytes)\n",
+				port->name, i/2);
+
+			/* Go to reverse idle phase. */
+			parport_frob_control (port,
+					      PARPORT_CONTROL_AUTOFD,
+					      PARPORT_CONTROL_AUTOFD);
+			port->physport->ieee1284.phase = IEEE1284_PH_REV_IDLE;
+		}
 		else
-			port->ieee1284.phase = IEEE1284_PH_HBUSY_DAVAIL;
+			port->physport->ieee1284.phase = IEEE1284_PH_HBUSY_DAVAIL;
 	}
 
-	return i;
+	return i/2;
 #endif /* IEEE1284 support */
 }
 
@@ -256,17 +253,7 @@ size_t parport_ieee1284_read_byte (struct parport *port,
 
 		/* Data available? */
 		if (parport_read_status (port) & PARPORT_STATUS_ERROR) {
-			port->physport->ieee1284.phase = IEEE1284_PH_HBUSY_DNA;
-			DPRINTK (KERN_DEBUG
-				 "%s: No more byte data (%Zd bytes)\n",
-				 port->name, count);
-
-			/* Go to reverse idle phase. */
-			parport_frob_control (port,
-					      PARPORT_CONTROL_AUTOFD,
-					      PARPORT_CONTROL_AUTOFD);
-			port->physport->ieee1284.phase = IEEE1284_PH_REV_IDLE;
-			break;
+			goto end_of_data;
 		}
 
 		/* Event 14: Place data bus in high impedance state. */
@@ -318,11 +305,20 @@ size_t parport_ieee1284_read_byte (struct parport *port,
 
 	if (count == len) {
 		/* Read the last byte without checking data avail. */
-		port = port->physport;
-		if (parport_read_status (port) & PARPORT_STATUS_ERROR)
-			port->ieee1284.phase = IEEE1284_PH_HBUSY_DNA;
+		if (parport_read_status (port) & PARPORT_STATUS_ERROR) {
+		end_of_data:
+			DPRINTK (KERN_DEBUG
+				 "%s: No more byte data (%Zd bytes)\n",
+				 port->name, count);
+
+			/* Go to reverse idle phase. */
+			parport_frob_control (port,
+					      PARPORT_CONTROL_AUTOFD,
+					      PARPORT_CONTROL_AUTOFD);
+			port->physport->ieee1284.phase = IEEE1284_PH_REV_IDLE;
+		}
 		else
-			port->ieee1284.phase = IEEE1284_PH_HBUSY_DAVAIL;
+			port->physport->ieee1284.phase = IEEE1284_PH_HBUSY_DAVAIL;
 	}
 
 	return count;
diff --git a/drivers/parport/parport_cs.c b/drivers/parport/parport_cs.c
index 24e6aacddb74..158d92563259 100644
--- a/drivers/parport/parport_cs.c
+++ b/drivers/parport/parport_cs.c
@@ -87,15 +87,9 @@ typedef struct parport_info_t {
     struct parport	*port;
 } parport_info_t;
 
-static dev_link_t *parport_attach(void);
-static void parport_detach(dev_link_t *);
+static void parport_detach(struct pcmcia_device *p_dev);
 static void parport_config(dev_link_t *link);
 static void parport_cs_release(dev_link_t *);
-static int parport_event(event_t event, int priority,
-			 event_callback_args_t *args);
-
-static dev_info_t dev_info = "parport_cs";
-static dev_link_t *dev_list = NULL;
 
 /*======================================================================
 
@@ -105,18 +99,16 @@ static dev_link_t *dev_list = NULL;
 
 ======================================================================*/
 
-static dev_link_t *parport_attach(void)
+static int parport_attach(struct pcmcia_device *p_dev)
 {
     parport_info_t *info;
     dev_link_t *link;
-    client_reg_t client_reg;
-    int ret;
-    
+
     DEBUG(0, "parport_attach()\n");
 
     /* Create new parport device */
     info = kmalloc(sizeof(*info), GFP_KERNEL);
-    if (!info) return NULL;
+    if (!info) return -ENOMEM;
     memset(info, 0, sizeof(*info));
     link = &info->link; link->priv = info;
 
@@ -127,21 +119,14 @@ static dev_link_t *parport_attach(void)
     link->conf.Attributes = CONF_ENABLE_IRQ;
     link->conf.Vcc = 50;
     link->conf.IntType = INT_MEMORY_AND_IO;
-    
-    /* Register with Card Services */
-    link->next = dev_list;
-    dev_list = link;
-    client_reg.dev_info = &dev_info;
-    client_reg.Version = 0x0210;
-    client_reg.event_callback_args.client_data = link;
-    ret = pcmcia_register_client(&link->handle, &client_reg);
-    if (ret != CS_SUCCESS) {
-	cs_error(link->handle, RegisterClient, ret);
-	parport_detach(link);
-	return NULL;
-    }
-    
-    return link;
+
+    link->handle = p_dev;
+    p_dev->instance = link;
+
+    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+    parport_config(link);
+
+    return 0;
 } /* parport_attach */
 
 /*======================================================================
@@ -153,32 +138,16 @@ static dev_link_t *parport_attach(void)
 
 ======================================================================*/
 
-static void parport_detach(dev_link_t *link)
+static void parport_detach(struct pcmcia_device *p_dev)
 {
-    dev_link_t **linkp;
-    int ret;
+    dev_link_t *link = dev_to_instance(p_dev);
 
     DEBUG(0, "parport_detach(0x%p)\n", link);
-    
-    /* Locate device structure */
-    for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
-	if (*linkp == link) break;
-    if (*linkp == NULL)
-	return;
 
     if (link->state & DEV_CONFIG)
 	parport_cs_release(link);
-    
-    if (link->handle) {
-	ret = pcmcia_deregister_client(link->handle);
-	if (ret != CS_SUCCESS)
-	    cs_error(link->handle, DeregisterClient, ret);
-    }
-    
-    /* Unlink, free device structure */
-    *linkp = link->next;
+
     kfree(link->priv);
-    
 } /* parport_detach */
 
 /*======================================================================
@@ -325,47 +294,27 @@ void parport_cs_release(dev_link_t *link)
 
 } /* parport_cs_release */
 
-/*======================================================================
-
-    The card status event handler.  Mostly, this schedules other
-    stuff to run after an event is received.
-    
-======================================================================*/
-
-int parport_event(event_t event, int priority,
-		  event_callback_args_t *args)
+static int parport_suspend(struct pcmcia_device *dev)
 {
-    dev_link_t *link = args->client_data;
+	dev_link_t *link = dev_to_instance(dev);
 
-    DEBUG(1, "parport_event(0x%06x)\n", event);
-    
-    switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-	link->state &= ~DEV_PRESENT;
-	if (link->state & DEV_CONFIG)
-		parport_cs_release(link);
-	break;
-    case CS_EVENT_CARD_INSERTION:
-	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-	parport_config(link);
-	break;
-    case CS_EVENT_PM_SUSPEND:
 	link->state |= DEV_SUSPEND;
-	/* Fall through... */
-    case CS_EVENT_RESET_PHYSICAL:
 	if (link->state & DEV_CONFIG)
-	    pcmcia_release_configuration(link->handle);
-	break;
-    case CS_EVENT_PM_RESUME:
+		pcmcia_release_configuration(link->handle);
+
+	return 0;
+}
+
+static int parport_resume(struct pcmcia_device *dev)
+{
+	dev_link_t *link = dev_to_instance(dev);
+
 	link->state &= ~DEV_SUSPEND;
-	/* Fall through... */
-    case CS_EVENT_CARD_RESET:
 	if (DEV_OK(link))
-	    pcmcia_request_configuration(link->handle, &link->conf);
-	break;
-    }
-    return 0;
-} /* parport_event */
+		pcmcia_request_configuration(link->handle, &link->conf);
+
+	return 0;
+}
 
 static struct pcmcia_device_id parport_ids[] = {
 	PCMCIA_DEVICE_FUNC_ID(3),
@@ -379,11 +328,11 @@ static struct pcmcia_driver parport_cs_driver = {
 	.drv		= {
 		.name	= "parport_cs",
 	},
-	.attach		= parport_attach,
-	.event		= parport_event,
-	.detach		= parport_detach,
+	.probe		= parport_attach,
+	.remove		= parport_detach,
 	.id_table	= parport_ids,
-
+	.suspend	= parport_suspend,
+	.resume		= parport_resume,
 };
 
 static int __init init_parport_cs(void)
@@ -394,7 +343,6 @@ static int __init init_parport_cs(void)
 static void __exit exit_parport_cs(void)
 {
 	pcmcia_unregister_driver(&parport_cs_driver);
-	BUG_ON(dev_list != NULL);
 }
 
 module_init(init_parport_cs);
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index c6493ad7c0c8..18e85ccdae67 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -1169,7 +1169,7 @@ dump_parport_state ("fwd idle", port);
 
 /* GCC is not inlining extern inline function later overwriten to non-inline,
    so we use outlined_ variants here.  */
-static struct parport_operations parport_pc_ops =
+static const struct parport_operations parport_pc_ops =
 {
 	.write_data	= parport_pc_write_data,
 	.read_data	= parport_pc_read_data,
@@ -1211,10 +1211,11 @@ static struct parport_operations parport_pc_ops =
 static void __devinit show_parconfig_smsc37c669(int io, int key)
 {
 	int cr1,cr4,cra,cr23,cr26,cr27,i=0;
-	static const char *modes[]={ "SPP and Bidirectional (PS/2)",	
-				     "EPP and SPP",
-				     "ECP",
-				     "ECP and EPP" };
+	static const char *const modes[]={
+		"SPP and Bidirectional (PS/2)",
+		"EPP and SPP",
+		"ECP",
+		"ECP and EPP" };
 
 	outb(key,io);
 	outb(key,io);
@@ -1288,7 +1289,7 @@ static void __devinit show_parconfig_smsc37c669(int io, int key)
 static void __devinit show_parconfig_winbond(int io, int key)
 {
 	int cr30,cr60,cr61,cr70,cr74,crf0,i=0;
-	static const char *modes[] = {
+	static const char *const modes[] = {
 		"Standard (SPP) and Bidirectional(PS/2)", /* 0 */
 		"EPP-1.9 and SPP",
 		"ECP",
@@ -1297,7 +1298,9 @@ static void __devinit show_parconfig_winbond(int io, int key)
 		"EPP-1.7 and SPP",		/* 5 */
 		"undefined!",
 		"ECP and EPP-1.7" };
-	static char *irqtypes[] = { "pulsed low, high-Z", "follows nACK" };
+	static char *const irqtypes[] = {
+		"pulsed low, high-Z",
+		"follows nACK" };
 		
 	/* The registers are called compatible-PnP because the
            register layout is modelled after ISA-PnP, the access
@@ -2396,7 +2399,8 @@ EXPORT_SYMBOL (parport_pc_unregister_port);
 
 /* ITE support maintained by Rich Liu <richliu@poorman.org> */
 static int __devinit sio_ite_8872_probe (struct pci_dev *pdev, int autoirq,
-					 int autodma, struct parport_pc_via_data *via)
+					 int autodma,
+					 const struct parport_pc_via_data *via)
 {
 	short inta_addr[6] = { 0x2A0, 0x2C0, 0x220, 0x240, 0x1E0 };
 	struct resource *base_res;
@@ -2524,7 +2528,8 @@ static struct parport_pc_via_data via_8231_data __devinitdata = {
 };
 
 static int __devinit sio_via_probe (struct pci_dev *pdev, int autoirq,
-					 int autodma, struct parport_pc_via_data *via)
+				    int autodma,
+				    const struct parport_pc_via_data *via)
 {
 	u8 tmp, tmp2, siofunc;
 	u8 ppcontrol = 0;
@@ -2694,8 +2699,9 @@ enum parport_pc_sio_types {
 
 /* each element directly indexed from enum list, above */
 static struct parport_pc_superio {
-	int (*probe) (struct pci_dev *pdev, int autoirq, int autodma, struct parport_pc_via_data *via);
-	struct parport_pc_via_data *via;
+	int (*probe) (struct pci_dev *pdev, int autoirq, int autodma,
+		      const struct parport_pc_via_data *via);
+	const struct parport_pc_via_data *via;
 } parport_pc_superio_info[] __devinitdata = {
 	{ sio_via_probe, &via_686a_data, },
 	{ sio_via_probe, &via_8231_data, },
@@ -2828,7 +2834,7 @@ static struct parport_pc_pci {
 	/* netmos_9815 */               { 2, { { 0, -1 }, { 2, -1 }, } }, /* untested */
 };
 
-static struct pci_device_id parport_pc_pci_tbl[] = {
+static const struct pci_device_id parport_pc_pci_tbl[] = {
 	/* Super-IO onboard chips */
 	{ 0x1106, 0x0686, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sio_via_686a },
 	{ 0x1106, 0x8231, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sio_via_8231 },
diff --git a/drivers/parport/probe.c b/drivers/parport/probe.c
index 4b48b31ec235..b62aee8de3cb 100644
--- a/drivers/parport/probe.c
+++ b/drivers/parport/probe.c
@@ -11,9 +11,9 @@
 #include <linux/string.h>
 #include <asm/uaccess.h>
 
-static struct {
-	char *token;
-	char *descr;
+static const struct {
+	const char *token;
+	const char *descr;
 } classes[] = {
 	{ "",            "Legacy device" },
 	{ "PRINTER",     "Printer" },
@@ -128,8 +128,131 @@ static void parse_data(struct parport *port, int device, char *str)
 	kfree(txt);
 }
 
+/* Read up to count-1 bytes of device id. Terminate buffer with
+ * '\0'. Buffer begins with two Device ID length bytes as given by
+ * device. */
+static ssize_t parport_read_device_id (struct parport *port, char *buffer,
+				       size_t count)
+{
+	unsigned char length[2];
+	unsigned lelen, belen;
+	size_t idlens[4];
+	unsigned numidlens;
+	unsigned current_idlen;
+	ssize_t retval;
+	size_t len;
+
+	/* First two bytes are MSB,LSB of inclusive length. */
+	retval = parport_read (port, length, 2);
+
+	if (retval < 0)
+		return retval;
+	if (retval != 2)
+		return -EIO;
+
+	if (count < 2)
+		return 0;
+	memcpy(buffer, length, 2);
+	len = 2;
+
+	/* Some devices wrongly send LE length, and some send it two
+	 * bytes short. Construct a sorted array of lengths to try. */
+	belen = (length[0] << 8) + length[1];
+	lelen = (length[1] << 8) + length[0];
+	idlens[0] = min(belen, lelen);
+	idlens[1] = idlens[0]+2;
+	if (belen != lelen) {
+		int off = 2;
+		/* Don't try lenghts of 0x100 and 0x200 as 1 and 2 */
+		if (idlens[0] <= 2)
+			off = 0;
+		idlens[off] = max(belen, lelen);
+		idlens[off+1] = idlens[off]+2;
+		numidlens = off+2;
+	}
+	else {
+		/* Some devices don't truly implement Device ID, but
+		 * just return constant nibble forever. This catches
+		 * also those cases. */
+		if (idlens[0] == 0 || idlens[0] > 0xFFF) {
+			printk (KERN_DEBUG "%s: reported broken Device ID"
+				" length of %#zX bytes\n",
+				port->name, idlens[0]);
+			return -EIO;
+		}
+		numidlens = 2;
+	}
+
+	/* Try to respect the given ID length despite all the bugs in
+	 * the ID length. Read according to shortest possible ID
+	 * first. */
+	for (current_idlen = 0; current_idlen < numidlens; ++current_idlen) {
+		size_t idlen = idlens[current_idlen];
+		if (idlen+1 >= count)
+			break;
+
+		retval = parport_read (port, buffer+len, idlen-len);
+
+		if (retval < 0)
+			return retval;
+		len += retval;
+
+		if (port->physport->ieee1284.phase != IEEE1284_PH_HBUSY_DAVAIL) {
+			if (belen != len) {
+				printk (KERN_DEBUG "%s: Device ID was %d bytes"
+					" while device told it would be %d"
+					" bytes\n",
+					port->name, len, belen);
+			}
+			goto done;
+		}
+
+		/* This might end reading the Device ID too
+		 * soon. Hopefully the needed fields were already in
+		 * the first 256 bytes or so that we must have read so
+		 * far. */
+		if (buffer[len-1] == ';') {
+ 			printk (KERN_DEBUG "%s: Device ID reading stopped"
+				" before device told data not available. "
+				"Current idlen %d of %d, len bytes %02X %02X\n",
+				port->name, current_idlen, numidlens,
+				length[0], length[1]);
+			goto done;
+		}
+	}
+	if (current_idlen < numidlens) {
+		/* Buffer not large enough, read to end of buffer. */
+		size_t idlen, len2;
+		if (len+1 < count) {
+			retval = parport_read (port, buffer+len, count-len-1);
+			if (retval < 0)
+				return retval;
+			len += retval;
+		}
+		/* Read the whole ID since some devices would not
+		 * otherwise give back the Device ID from beginning
+		 * next time when asked. */
+		idlen = idlens[current_idlen];
+		len2 = len;
+		while(len2 < idlen && retval > 0) {
+			char tmp[4];
+			retval = parport_read (port, tmp,
+					       min(sizeof tmp, idlen-len2));
+			if (retval < 0)
+				return retval;
+			len2 += retval;
+		}
+	}
+	/* In addition, there are broken devices out there that don't
+	   even finish off with a semi-colon. We do not need to care
+	   about those at this time. */
+ done:
+	buffer[len] = '\0';
+	return len;
+}
+
 /* Get Std 1284 Device ID. */
-ssize_t parport_device_id (int devnum, char *buffer, size_t len)
+ssize_t parport_device_id (int devnum, char *buffer, size_t count)
 {
 	ssize_t retval = -ENXIO;
 	struct pardevice *dev = parport_open (devnum, "Device ID probe",
@@ -139,76 +262,20 @@ ssize_t parport_device_id (int devnum, char *buffer, size_t len)
 
 	parport_claim_or_block (dev);
 
-	/* Negotiate to compatibility mode, and then to device ID mode.
-	 * (This is in case we are already in device ID mode.) */
+	/* Negotiate to compatibility mode, and then to device ID
+	 * mode. (This so that we start form beginning of device ID if
+	 * already in device ID mode.) */
 	parport_negotiate (dev->port, IEEE1284_MODE_COMPAT);
 	retval = parport_negotiate (dev->port,
 				    IEEE1284_MODE_NIBBLE | IEEE1284_DEVICEID);
 
 	if (!retval) {
-		int idlen;
-		unsigned char length[2];
-
-		/* First two bytes are MSB,LSB of inclusive length. */
-		retval = parport_read (dev->port, length, 2);
-
-		if (retval != 2) goto end_id;
-
-		idlen = (length[0] << 8) + length[1] - 2;
-		/*
-		 * Check if the caller-allocated buffer is large enough
-		 * otherwise bail out or there will be an at least off by one.
-		 */
-		if (idlen + 1 < len)
-			len = idlen;
-		else {
-			retval = -EINVAL;
-			goto out;
-		}
-		retval = parport_read (dev->port, buffer, len);
-
-		if (retval != len)
-			printk (KERN_DEBUG "%s: only read %Zd of %Zd ID bytes\n",
-				dev->port->name, retval,
-				len);
-
-		/* Some printer manufacturers mistakenly believe that
-                   the length field is supposed to be _exclusive_.
-		   In addition, there are broken devices out there
-                   that don't even finish off with a semi-colon. */
-		if (buffer[len - 1] != ';') {
-			ssize_t diff;
-			diff = parport_read (dev->port, buffer + len, 2);
-			retval += diff;
-
-			if (diff)
-				printk (KERN_DEBUG
-					"%s: device reported incorrect "
-					"length field (%d, should be %Zd)\n",
-					dev->port->name, idlen, retval);
-			else {
-				/* One semi-colon short of a device ID. */
-				buffer[len++] = ';';
-				printk (KERN_DEBUG "%s: faking semi-colon\n",
-					dev->port->name);
-
-				/* If we get here, I don't think we
-                                   need to worry about the possible
-                                   standard violation of having read
-                                   more than we were told to.  The
-                                   device is non-compliant anyhow. */
-			}
-		}
-
-	end_id:
-		buffer[len] = '\0';
+		retval = parport_read_device_id (dev->port, buffer, count);
 		parport_negotiate (dev->port, IEEE1284_MODE_COMPAT);
+		if (retval > 2)
+			parse_data (dev->port, dev->daisy, buffer+2);
 	}
 
-	if (retval > 2)
-		parse_data (dev->port, dev->daisy, buffer);
-
-out:
 	parport_release (dev);
 	parport_close (dev);
 	return retval;
diff --git a/drivers/parport/share.c b/drivers/parport/share.c
index 9cb3ab156b09..ea62bed6bc83 100644
--- a/drivers/parport/share.c
+++ b/drivers/parport/share.c
@@ -1002,6 +1002,7 @@ EXPORT_SYMBOL(parport_register_driver);
 EXPORT_SYMBOL(parport_unregister_driver);
 EXPORT_SYMBOL(parport_register_device);
 EXPORT_SYMBOL(parport_unregister_device);
+EXPORT_SYMBOL(parport_get_port);
 EXPORT_SYMBOL(parport_put_port);
 EXPORT_SYMBOL(parport_find_number);
 EXPORT_SYMBOL(parport_find_base);
diff --git a/drivers/pci/hotplug.c b/drivers/pci/hotplug.c
index e1743be31909..1c97e7dd130b 100644
--- a/drivers/pci/hotplug.c
+++ b/drivers/pci/hotplug.c
@@ -3,8 +3,8 @@
 #include <linux/module.h>
 #include "pci.h"
 
-int pci_hotplug (struct device *dev, char **envp, int num_envp,
-		 char *buffer, int buffer_size)
+int pci_uevent(struct device *dev, char **envp, int num_envp,
+	       char *buffer, int buffer_size)
 {
 	struct pci_dev *pdev;
 	int i = 0;
@@ -17,34 +17,34 @@ int pci_hotplug (struct device *dev, char **envp, int num_envp,
 	if (!pdev)
 		return -ENODEV;
 
-	if (add_hotplug_env_var(envp, num_envp, &i,
-				buffer, buffer_size, &length,
-				"PCI_CLASS=%04X", pdev->class))
+	if (add_uevent_var(envp, num_envp, &i,
+			   buffer, buffer_size, &length,
+			   "PCI_CLASS=%04X", pdev->class))
 		return -ENOMEM;
 
-	if (add_hotplug_env_var(envp, num_envp, &i,
-				buffer, buffer_size, &length,
-				"PCI_ID=%04X:%04X", pdev->vendor, pdev->device))
+	if (add_uevent_var(envp, num_envp, &i,
+			   buffer, buffer_size, &length,
+			   "PCI_ID=%04X:%04X", pdev->vendor, pdev->device))
 		return -ENOMEM;
 
-	if (add_hotplug_env_var(envp, num_envp, &i,
-				buffer, buffer_size, &length,
-				"PCI_SUBSYS_ID=%04X:%04X", pdev->subsystem_vendor,
-				pdev->subsystem_device))
+	if (add_uevent_var(envp, num_envp, &i,
+			   buffer, buffer_size, &length,
+			   "PCI_SUBSYS_ID=%04X:%04X", pdev->subsystem_vendor,
+			   pdev->subsystem_device))
 		return -ENOMEM;
 
-	if (add_hotplug_env_var(envp, num_envp, &i,
-				buffer, buffer_size, &length,
-				"PCI_SLOT_NAME=%s", pci_name(pdev)))
+	if (add_uevent_var(envp, num_envp, &i,
+			   buffer, buffer_size, &length,
+			   "PCI_SLOT_NAME=%s", pci_name(pdev)))
 		return -ENOMEM;
 
-	if (add_hotplug_env_var(envp, num_envp, &i,
-				buffer, buffer_size, &length,
-				"MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x",
-				pdev->vendor, pdev->device,
-				pdev->subsystem_vendor, pdev->subsystem_device,
-				(u8)(pdev->class >> 16), (u8)(pdev->class >> 8),
-				(u8)(pdev->class)))
+	if (add_uevent_var(envp, num_envp, &i,
+			   buffer, buffer_size, &length,
+			   "MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x",
+			   pdev->vendor, pdev->device,
+			   pdev->subsystem_vendor, pdev->subsystem_device,
+			   (u8)(pdev->class >> 16), (u8)(pdev->class >> 8),
+			   (u8)(pdev->class)))
 		return -ENOMEM;
 
 	envp[i] = NULL;
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index a9046d4b8af3..7146b69b812c 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -502,8 +502,8 @@ void pci_dev_put(struct pci_dev *dev)
 }
 
 #ifndef CONFIG_HOTPLUG
-int pci_hotplug (struct device *dev, char **envp, int num_envp,
-		 char *buffer, int buffer_size)
+int pci_uevent(struct device *dev, char **envp, int num_envp,
+	       char *buffer, int buffer_size)
 {
 	return -ENODEV;
 }
@@ -512,7 +512,7 @@ int pci_hotplug (struct device *dev, char **envp, int num_envp,
 struct bus_type pci_bus_type = {
 	.name		= "pci",
 	.match		= pci_bus_match,
-	.hotplug	= pci_hotplug,
+	.uevent		= pci_uevent,
 	.suspend	= pci_device_suspend,
 	.resume		= pci_device_resume,
 	.dev_attrs	= pci_dev_attrs,
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 6527b36c9a61..294849d24590 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -1,7 +1,7 @@
 /* Functions internal to the PCI core code */
 
-extern int pci_hotplug (struct device *dev, char **envp, int num_envp,
-			 char *buffer, int buffer_size);
+extern int pci_uevent(struct device *dev, char **envp, int num_envp,
+		      char *buffer, int buffer_size);
 extern int pci_create_sysfs_dev_files(struct pci_dev *pdev);
 extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev);
 extern void pci_cleanup_rom(struct pci_dev *dev);
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 3a4f49f4effb..f28ebdd3958a 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -1098,6 +1098,23 @@ static void __init quirk_alder_ioapic(struct pci_dev *pdev)
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_EESSC,	quirk_alder_ioapic );
 #endif
 
+enum ide_combined_type { COMBINED = 0, IDE = 1, LIBATA = 2 };
+/* Defaults to combined */
+static enum ide_combined_type combined_mode;
+
+static int __init combined_setup(char *str)
+{
+	if (!strncmp(str, "ide", 3))
+		combined_mode = IDE;
+	else if (!strncmp(str, "libata", 6))
+		combined_mode = LIBATA;
+	else /* "combined" or anything else defaults to old behavior */
+		combined_mode = COMBINED;
+
+	return 1;
+}
+__setup("combined_mode=", combined_setup);
+
 #ifdef CONFIG_SCSI_SATA_INTEL_COMBINED
 static void __devinit quirk_intel_ide_combined(struct pci_dev *pdev)
 {
@@ -1164,6 +1181,19 @@ static void __devinit quirk_intel_ide_combined(struct pci_dev *pdev)
 	if (prog & comb)
 		return;
 
+	/* Don't reserve any so the IDE driver can get them (but only if
+	 * combined_mode=ide).
+	 */
+	if (combined_mode == IDE)
+		return;
+
+	/* Grab them both for libata if combined_mode=libata. */
+	if (combined_mode == LIBATA) {
+		request_region(0x1f0, 8, "libata");	/* port 0 */
+		request_region(0x170, 8, "libata");	/* port 1 */
+		return;
+	}
+
 	/* SATA port is in legacy mode.  Reserve port so that
 	 * IDE driver does not attempt to use it.  If request_region
 	 * fails, it will be obvious at boot time, so we don't bother
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index 309eb557f9a3..1f4ad0e7836e 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -116,6 +116,31 @@ config YENTA
 
 	  If unsure, say Y.
 
+config YENTA_O2
+	default y
+	bool "Special initialization for O2Micro bridges" if EMBEDDED
+	depends on YENTA
+
+config YENTA_RICOH
+	default y
+	bool "Special initialization for Ricoh bridges" if EMBEDDED
+	depends on YENTA
+
+config YENTA_TI
+	default y
+	bool "Special initialization for TI and EnE bridges" if EMBEDDED
+	depends on YENTA
+
+config YENTA_ENE_TUNE
+	default y
+	bool "Auto-tune EnE bridges for CB cards" if EMBEDDED
+	depends on YENTA_TI && CARDBUS
+
+config YENTA_TOSHIBA
+	default y
+	bool "Special initialization for Toshiba ToPIC bridges" if EMBEDDED
+	depends on YENTA
+
 config PD6729
 	tristate "Cirrus PD6729 compatible bridge support"
 	depends on PCMCIA && PCI
@@ -157,7 +182,7 @@ config TCIC
 config PCMCIA_M8XX
         tristate "MPC8xx PCMCIA support"
         depends on PCMCIA && PPC && 8xx 
-        select PCCARD_NONSTATIC
+        select PCCARD_IODYN
         help
         Say Y here to include support for PowerPC 8xx series PCMCIA
         controller.
@@ -200,7 +225,7 @@ config PCMCIA_PXA2XX
 
 config PCMCIA_PROBE
 	bool
-	default y if ISA && !ARCH_SA1100 && !ARCH_CLPS711X
+	default y if ISA && !ARCH_SA1100 && !ARCH_CLPS711X && !PARISC
 
 config M32R_PCC
 	bool "M32R PCMCIA I/F"
@@ -241,6 +266,9 @@ config OMAP_CF
 config PCCARD_NONSTATIC
 	tristate
 
+config PCCARD_IODYN
+	bool
+
 endif	# PCCARD
 
 endmenu
diff --git a/drivers/pcmcia/au1000_generic.c b/drivers/pcmcia/au1000_generic.c
index 87302c548c24..971a35281649 100644
--- a/drivers/pcmcia/au1000_generic.c
+++ b/drivers/pcmcia/au1000_generic.c
@@ -241,23 +241,6 @@ au1x00_pcmcia_get_status(struct pcmcia_socket *sock, unsigned int *status)
 	return 0;
 }
 
-/* au1x00_pcmcia_get_socket()
- * Implements the get_socket() operation for the in-kernel PCMCIA
- * service (formerly SS_GetSocket in Card Services). Not a very
- * exciting routine.
- *
- * Returns: 0
- */
-static int
-au1x00_pcmcia_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
-{
-  struct au1000_pcmcia_socket *skt = to_au1000_socket(sock);
-
-  debug("for sock %u\n", skt->nr);
-  *state = skt->cs_state;
-  return 0;
-}
-
 /* au1x00_pcmcia_set_socket()
  * Implements the set_socket() operation for the in-kernel PCMCIA
  * service (formerly SS_SetSocket in Card Services). We more or
@@ -352,7 +335,6 @@ static struct pccard_operations au1x00_pcmcia_operations = {
 	.init			= au1x00_pcmcia_sock_init,
 	.suspend		= au1x00_pcmcia_suspend,
 	.get_status		= au1x00_pcmcia_get_status,
-	.get_socket		= au1x00_pcmcia_get_socket,
 	.set_socket		= au1x00_pcmcia_set_socket,
 	.set_io_map		= au1x00_pcmcia_set_io_map,
 	.set_mem_map		= au1x00_pcmcia_set_mem_map,
@@ -372,13 +354,12 @@ int au1x00_pcmcia_socket_probe(struct device *dev, struct pcmcia_low_level *ops,
 	struct skt_dev_info *sinfo;
 	int ret, i;
 
-	sinfo = kmalloc(sizeof(struct skt_dev_info), GFP_KERNEL);
+	sinfo = kzalloc(sizeof(struct skt_dev_info), GFP_KERNEL);
 	if (!sinfo) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
-	memset(sinfo, 0, sizeof(struct skt_dev_info));
 	sinfo->nskt = nr;
 
 	/*
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
index 2dc3e611a9a3..120fa8da6392 100644
--- a/drivers/pcmcia/cistpl.c
+++ b/drivers/pcmcia/cistpl.c
@@ -60,9 +60,9 @@ static const u_int exponent[] = {
 
 /* Parameters that can be set with 'insmod' */
 
-#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0444)
-
-INT_MODULE_PARM(cis_width,	0);		/* 16-bit CIS? */
+/* 16-bit CIS? */
+static int cis_width;
+module_param(cis_width, int, 0444);
 
 void release_cis_mem(struct pcmcia_socket *s)
 {
@@ -463,7 +463,7 @@ static int follow_link(struct pcmcia_socket *s, tuple_t *tuple)
 	/* Get indirect link from the MFC tuple */
 	read_cis_cache(s, LINK_SPACE(tuple->Flags),
 		       tuple->LinkOffset, 5, link);
-	ofs = le32_to_cpu(*(u_int *)(link+1));
+	ofs = le32_to_cpu(*(__le32 *)(link+1));
 	SPACE(tuple->Flags) = (link[0] == CISTPL_MFC_ATTR);
 	/* Move to the next indirect link */
 	tuple->LinkOffset += 5;
@@ -671,8 +671,8 @@ static int parse_checksum(tuple_t *tuple, cistpl_checksum_t *csum)
     if (tuple->TupleDataLen < 5)
 	return CS_BAD_TUPLE;
     p = (u_char *)tuple->TupleData;
-    csum->addr = tuple->CISOffset+(short)le16_to_cpu(*(u_short *)p)-2;
-    csum->len = le16_to_cpu(*(u_short *)(p + 2));
+    csum->addr = tuple->CISOffset+(short)le16_to_cpu(*(__le16 *)p)-2;
+    csum->len = le16_to_cpu(*(__le16 *)(p + 2));
     csum->sum = *(p+4);
     return CS_SUCCESS;
 }
@@ -683,7 +683,7 @@ static int parse_longlink(tuple_t *tuple, cistpl_longlink_t *link)
 {
     if (tuple->TupleDataLen < 4)
 	return CS_BAD_TUPLE;
-    link->addr = le32_to_cpu(*(u_int *)tuple->TupleData);
+    link->addr = le32_to_cpu(*(__le32 *)tuple->TupleData);
     return CS_SUCCESS;
 }
 
@@ -702,7 +702,7 @@ static int parse_longlink_mfc(tuple_t *tuple,
 	return CS_BAD_TUPLE;
     for (i = 0; i < link->nfn; i++) {
 	link->fn[i].space = *p; p++;
-	link->fn[i].addr = le32_to_cpu(*(u_int *)p); p += 4;
+	link->fn[i].addr = le32_to_cpu(*(__le32 *)p); p += 4;
     }
     return CS_SUCCESS;
 }
@@ -789,10 +789,10 @@ static int parse_jedec(tuple_t *tuple, cistpl_jedec_t *jedec)
 
 static int parse_manfid(tuple_t *tuple, cistpl_manfid_t *m)
 {
-    u_short *p;
+    __le16 *p;
     if (tuple->TupleDataLen < 4)
 	return CS_BAD_TUPLE;
-    p = (u_short *)tuple->TupleData;
+    p = (__le16 *)tuple->TupleData;
     m->manf = le16_to_cpu(p[0]);
     m->card = le16_to_cpu(p[1]);
     return CS_SUCCESS;
@@ -1093,7 +1093,7 @@ static int parse_cftable_entry(tuple_t *tuple,
 	break;
     case 0x20:
 	entry->mem.nwin = 1;
-	entry->mem.win[0].len = le16_to_cpu(*(u_short *)p) << 8;
+	entry->mem.win[0].len = le16_to_cpu(*(__le16 *)p) << 8;
 	entry->mem.win[0].card_addr = 0;
 	entry->mem.win[0].host_addr = 0;
 	p += 2;
@@ -1101,9 +1101,9 @@ static int parse_cftable_entry(tuple_t *tuple,
 	break;
     case 0x40:
 	entry->mem.nwin = 1;
-	entry->mem.win[0].len = le16_to_cpu(*(u_short *)p) << 8;
+	entry->mem.win[0].len = le16_to_cpu(*(__le16 *)p) << 8;
 	entry->mem.win[0].card_addr =
-	    le16_to_cpu(*(u_short *)(p+2)) << 8;
+	    le16_to_cpu(*(__le16 *)(p+2)) << 8;
 	entry->mem.win[0].host_addr = 0;
 	p += 4;
 	if (p > q) return CS_BAD_TUPLE;
@@ -1140,7 +1140,7 @@ static int parse_bar(tuple_t *tuple, cistpl_bar_t *bar)
     p = (u_char *)tuple->TupleData;
     bar->attr = *p;
     p += 2;
-    bar->size = le32_to_cpu(*(u_int *)p);
+    bar->size = le32_to_cpu(*(__le32 *)p);
     return CS_SUCCESS;
 }
 
@@ -1153,7 +1153,7 @@ static int parse_config_cb(tuple_t *tuple, cistpl_config_t *config)
 	return CS_BAD_TUPLE;
     config->last_idx = *(++p);
     p++;
-    config->base = le32_to_cpu(*(u_int *)p);
+    config->base = le32_to_cpu(*(__le32 *)p);
     config->subtuples = tuple->TupleDataLen - 6;
     return CS_SUCCESS;
 }
@@ -1269,7 +1269,7 @@ static int parse_vers_2(tuple_t *tuple, cistpl_vers_2_t *v2)
 
     v2->vers = p[0];
     v2->comply = p[1];
-    v2->dindex = le16_to_cpu(*(u_short *)(p+2));
+    v2->dindex = le16_to_cpu(*(__le16 *)(p+2));
     v2->vspec8 = p[6];
     v2->vspec9 = p[7];
     v2->nhdr = p[8];
@@ -1310,8 +1310,8 @@ static int parse_format(tuple_t *tuple, cistpl_format_t *fmt)
 
     fmt->type = p[0];
     fmt->edc = p[1];
-    fmt->offset = le32_to_cpu(*(u_int *)(p+2));
-    fmt->length = le32_to_cpu(*(u_int *)(p+6));
+    fmt->offset = le32_to_cpu(*(__le32 *)(p+2));
+    fmt->length = le32_to_cpu(*(__le32 *)(p+6));
 
     return CS_SUCCESS;
 }
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index a30aa74304a2..613f2f1fbfdd 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -309,41 +309,6 @@ struct pcmcia_socket * pcmcia_get_socket_by_nr(unsigned int nr)
 }
 EXPORT_SYMBOL(pcmcia_get_socket_by_nr);
 
-
-/**
- * socket_setup() and shutdown_socket() are called by the main event
- * handler when card insertion and removal events are received.
- * socket_setup() turns on socket power and resets the socket, in two stages.
- * shutdown_socket() unconfigures a socket and turns off socket power.
- */
-static void shutdown_socket(struct pcmcia_socket *s)
-{
-	cs_dbg(s, 1, "shutdown_socket\n");
-
-	/* Blank out the socket state */
-	s->socket = dead_socket;
-	s->ops->init(s);
-	s->ops->set_socket(s, &s->socket);
-	s->irq.AssignedIRQ = s->irq.Config = 0;
-	s->lock_count = 0;
-	destroy_cis_cache(s);
-#ifdef CONFIG_CARDBUS
-	cb_free(s);
-#endif
-	s->functions = 0;
-	kfree(s->config);
-	s->config = NULL;
-
-	{
-		int status;
-		s->ops->get_status(s, &status);
-		if (status & SS_POWERON) {
-			printk(KERN_ERR "PCMCIA: socket %p: *** DANGER *** unable to remove socket power\n", s);
-		}
-	}
-} /* shutdown_socket */
-
-
 /**
  * The central event handler.  Send_event() sends an event to the
  * 16-bit subsystem, which then calls the relevant device drivers.
@@ -383,17 +348,6 @@ static void socket_remove_drivers(struct pcmcia_socket *skt)
 	send_event(skt, CS_EVENT_CARD_REMOVAL, CS_EVENT_PRI_HIGH);
 }
 
-static void socket_shutdown(struct pcmcia_socket *skt)
-{
-	cs_dbg(skt, 4, "shutdown\n");
-
-	socket_remove_drivers(skt);
-	skt->state &= SOCKET_INUSE|SOCKET_PRESENT;
-	msleep(shutdown_delay * 10);
-	skt->state &= SOCKET_INUSE;
-	shutdown_socket(skt);
-}
-
 static int socket_reset(struct pcmcia_socket *skt)
 {
 	int status, i;
@@ -424,6 +378,45 @@ static int socket_reset(struct pcmcia_socket *skt)
 	return CS_GENERAL_FAILURE;
 }
 
+/**
+ * socket_setup() and socket_shutdown() are called by the main event handler
+ * when card insertion and removal events are received.
+ * socket_setup() turns on socket power and resets the socket, in two stages.
+ * socket_shutdown() unconfigures a socket and turns off socket power.
+ */
+static void socket_shutdown(struct pcmcia_socket *s)
+{
+	int status;
+
+	cs_dbg(s, 4, "shutdown\n");
+
+	socket_remove_drivers(s);
+	s->state &= SOCKET_INUSE | SOCKET_PRESENT;
+	msleep(shutdown_delay * 10);
+	s->state &= SOCKET_INUSE;
+
+	/* Blank out the socket state */
+	s->socket = dead_socket;
+	s->ops->init(s);
+	s->ops->set_socket(s, &s->socket);
+	s->irq.AssignedIRQ = s->irq.Config = 0;
+	s->lock_count = 0;
+	destroy_cis_cache(s);
+#ifdef CONFIG_CARDBUS
+	cb_free(s);
+#endif
+	s->functions = 0;
+	kfree(s->config);
+	s->config = NULL;
+
+	s->ops->get_status(s, &status);
+	if (status & SS_POWERON) {
+		printk(KERN_ERR "PCMCIA: socket %p: *** DANGER *** unable to remove socket power\n", s);
+	}
+
+	cs_socket_put(s);
+}
+
 static int socket_setup(struct pcmcia_socket *skt, int initial_delay)
 {
 	int status, i;
@@ -529,7 +522,6 @@ static int socket_insert(struct pcmcia_socket *skt)
 		send_event(skt, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW);
 	} else {
 		socket_shutdown(skt);
-		cs_socket_put(skt);
 	}
 
 	return ret;
@@ -593,7 +585,6 @@ static int socket_resume(struct pcmcia_socket *skt)
 		}
 	} else {
 		socket_shutdown(skt);
-		cs_socket_put(skt);
 	}
 
 	skt->state &= ~SOCKET_SUSPEND;
@@ -605,7 +596,6 @@ static void socket_remove(struct pcmcia_socket *skt)
 {
 	printk(KERN_NOTICE "pccard: card ejected from slot %d\n", skt->sock);
 	socket_shutdown(skt);
-	cs_socket_put(skt);
 }
 
 /*
@@ -780,8 +770,13 @@ int pccard_reset_card(struct pcmcia_socket *skt)
 		ret = send_event(skt, CS_EVENT_RESET_REQUEST, CS_EVENT_PRI_LOW);
 		if (ret == 0) {
 			send_event(skt, CS_EVENT_RESET_PHYSICAL, CS_EVENT_PRI_LOW);
-			if (socket_reset(skt) == CS_SUCCESS)
+			if (skt->callback)
+				skt->callback->suspend(skt);
+			if (socket_reset(skt) == CS_SUCCESS) {
 				send_event(skt, CS_EVENT_CARD_RESET, CS_EVENT_PRI_LOW);
+				if (skt->callback)
+					skt->callback->resume(skt);
+			}
 		}
 
 		ret = CS_SUCCESS;
@@ -812,6 +807,11 @@ int pcmcia_suspend_card(struct pcmcia_socket *skt)
 			ret = CS_UNSUPPORTED_FUNCTION;
 			break;
 		}
+		if (skt->callback) {
+			ret = skt->callback->suspend(skt);
+			if (ret)
+				break;
+		}
 		ret = socket_suspend(skt);
 	} while (0);
 	up(&skt->skt_sem);
@@ -838,6 +838,8 @@ int pcmcia_resume_card(struct pcmcia_socket *skt)
 			break;
 		}
 		ret = socket_resume(skt);
+		if (!ret && skt->callback)
+			skt->callback->resume(skt);
 	} while (0);
 	up(&skt->skt_sem);
 
@@ -901,14 +903,14 @@ int pcmcia_insert_card(struct pcmcia_socket *skt)
 EXPORT_SYMBOL(pcmcia_insert_card);
 
 
-static int pcmcia_socket_hotplug(struct class_device *dev, char **envp,
-				int num_envp, char *buffer, int buffer_size)
+static int pcmcia_socket_uevent(struct class_device *dev, char **envp,
+			        int num_envp, char *buffer, int buffer_size)
 {
 	struct pcmcia_socket *s = container_of(dev, struct pcmcia_socket, dev);
 	int i = 0, length = 0;
 
-	if (add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size,
-				&length, "SOCKET_NO=%u", s->sock))
+	if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
+			   &length, "SOCKET_NO=%u", s->sock))
 		return -ENOMEM;
 
 	envp[i] = NULL;
@@ -927,7 +929,7 @@ static void pcmcia_release_socket_class(struct class *data)
 
 struct class pcmcia_socket_class = {
 	.name = "pcmcia_socket",
-        .hotplug = pcmcia_socket_hotplug,
+	.uevent = pcmcia_socket_uevent,
 	.release = pcmcia_release_socket,
 	.class_release = pcmcia_release_socket_class,
 };
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h
index 55867bc7f199..7b37eba35bf1 100644
--- a/drivers/pcmcia/cs_internal.h
+++ b/drivers/pcmcia/cs_internal.h
@@ -117,7 +117,7 @@ int verify_cis_cache(struct pcmcia_socket *s);
 int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function, cisdata_t code, void *parse);
 
 /* In rsrc_mgr */
-void pcmcia_validate_mem(struct pcmcia_socket *s);
+int pcmcia_validate_mem(struct pcmcia_socket *s);
 struct resource *pcmcia_find_io_region(unsigned long base, int num, unsigned long align,
 		   struct pcmcia_socket *s);
 int pcmcia_adjust_io_region(struct resource *res, unsigned long r_start,
@@ -143,6 +143,8 @@ struct pcmcia_callback{
 	struct module	*owner;
 	int		(*event) (struct pcmcia_socket *s, event_t event, int priority);
 	void		(*requery) (struct pcmcia_socket *s);
+	int		(*suspend) (struct pcmcia_socket *s);
+	int		(*resume) (struct pcmcia_socket *s);
 };
 
 int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c);
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 7f8219f3fd9e..0252582b91cd 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -57,8 +57,6 @@ module_param_named(pc_debug, ds_pc_debug, int, 0644);
 
 spinlock_t pcmcia_dev_list_lock;
 
-static int unbind_request(struct pcmcia_socket *s);
-
 /*====================================================================*/
 
 /* code which was in cs.c before */
@@ -205,7 +203,7 @@ static void pcmcia_check_driver(struct pcmcia_driver *p_drv)
 	unsigned int i;
 	u32 hash;
 
-	if (!p_drv->attach || !p_drv->event || !p_drv->detach)
+	if (!p_drv->probe || !p_drv->remove)
 		printk(KERN_DEBUG "pcmcia: %s lacks a requisite callback "
 		       "function\n", p_drv->drv.name);
 
@@ -266,12 +264,10 @@ static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename)
 		if (fw->size >= CISTPL_MAX_CIS_SIZE)
 			goto release;
 
-		cis = kmalloc(sizeof(cisdump_t), GFP_KERNEL);
+		cis = kzalloc(sizeof(cisdump_t), GFP_KERNEL);
 		if (!cis)
 			goto release;
 
-		memset(cis, 0, sizeof(cisdump_t));
-
 		cis->Length = fw->size + 1;
 		memcpy(cis->Data, fw->data, fw->size);
 
@@ -363,6 +359,7 @@ static int pcmcia_device_probe(struct device * dev)
 {
 	struct pcmcia_device *p_dev;
 	struct pcmcia_driver *p_drv;
+	struct pcmcia_socket *s;
 	int ret = 0;
 
 	dev = get_device(dev);
@@ -371,25 +368,38 @@ static int pcmcia_device_probe(struct device * dev)
 
 	p_dev = to_pcmcia_dev(dev);
 	p_drv = to_pcmcia_drv(dev->driver);
+	s = p_dev->socket;
 
-	if (!try_module_get(p_drv->owner)) {
+	if ((!p_drv->probe) || (!try_module_get(p_drv->owner))) {
 		ret = -EINVAL;
 		goto put_dev;
 	}
 
-	if (p_drv->attach) {
-		p_dev->instance = p_drv->attach();
-		if ((!p_dev->instance) || (p_dev->state & CLIENT_UNBOUND)) {
-			printk(KERN_NOTICE "ds: unable to create instance "
-			       "of '%s'!\n", p_drv->drv.name);
-			ret = -EINVAL;
+	p_dev->state &= ~CLIENT_UNBOUND;
+
+	/* set up the device configuration, if it hasn't been done before */
+	if (!s->functions) {
+		cistpl_longlink_mfc_t mfc;
+		if (pccard_read_tuple(s, p_dev->func, CISTPL_LONGLINK_MFC,
+				      &mfc) == CS_SUCCESS)
+			s->functions = mfc.nfn;
+		else
+			s->functions = 1;
+		s->config = kzalloc(sizeof(config_t) * s->functions,
+				    GFP_KERNEL);
+		if (!s->config) {
+			ret = -ENOMEM;
+			goto put_module;
 		}
 	}
 
+	ret = p_drv->probe(p_dev);
+
+ put_module:
 	if (ret)
 		module_put(p_drv->owner);
  put_dev:
-	if ((ret) || !(p_drv->attach))
+	if (ret)
 		put_device(dev);
 	return (ret);
 }
@@ -399,24 +409,66 @@ static int pcmcia_device_remove(struct device * dev)
 {
 	struct pcmcia_device *p_dev;
 	struct pcmcia_driver *p_drv;
+	int i;
 
 	/* detach the "instance" */
 	p_dev = to_pcmcia_dev(dev);
 	p_drv = to_pcmcia_drv(dev->driver);
+	if (!p_drv)
+		return 0;
 
-	if (p_drv) {
-		if ((p_drv->detach) && (p_dev->instance)) {
-			p_drv->detach(p_dev->instance);
-			/* from pcmcia_probe_device */
-			put_device(&p_dev->dev);
-		}
-		module_put(p_drv->owner);
-	}
+	if (p_drv->remove)
+	       	p_drv->remove(p_dev);
+
+	/* check for proper unloading */
+	if (p_dev->state & (CLIENT_IRQ_REQ|CLIENT_IO_REQ|CLIENT_CONFIG_LOCKED))
+		printk(KERN_INFO "pcmcia: driver %s did not release config properly\n",
+		       p_drv->drv.name);
+
+	for (i = 0; i < MAX_WIN; i++)
+		if (p_dev->state & CLIENT_WIN_REQ(i))
+			printk(KERN_INFO "pcmcia: driver %s did not release windows properly\n",
+			       p_drv->drv.name);
+
+	/* references from pcmcia_probe_device */
+	p_dev->state = CLIENT_UNBOUND;
+	pcmcia_put_dev(p_dev);
+	module_put(p_drv->owner);
 
 	return 0;
 }
 
 
+/*
+ * Removes a PCMCIA card from the device tree and socket list.
+ */
+static void pcmcia_card_remove(struct pcmcia_socket *s)
+{
+	struct pcmcia_device	*p_dev;
+	unsigned long		flags;
+
+	ds_dbg(2, "unbind_request(%d)\n", s->sock);
+
+	s->device_count = 0;
+
+	for (;;) {
+		/* unregister all pcmcia_devices registered with this socket*/
+		spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
+		if (list_empty(&s->devices_list)) {
+			spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+ 			return;
+		}
+		p_dev = list_entry((&s->devices_list)->next, struct pcmcia_device, socket_device_list);
+		list_del(&p_dev->socket_device_list);
+		p_dev->state |= CLIENT_STALE;
+		spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+
+		device_unregister(&p_dev->dev);
+	}
+
+	return;
+} /* unbind_request */
+
 
 /*
  * pcmcia_device_query -- determine information about a pcmcia device
@@ -517,10 +569,9 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f
 	if (s->device_count == 2)
 		goto err_put;
 
-	p_dev = kmalloc(sizeof(struct pcmcia_device), GFP_KERNEL);
+	p_dev = kzalloc(sizeof(struct pcmcia_device), GFP_KERNEL);
 	if (!p_dev)
 		goto err_put;
-	memset(p_dev, 0, sizeof(struct pcmcia_device));
 
 	p_dev->socket = s;
 	p_dev->device_no = (s->device_count++);
@@ -583,7 +634,9 @@ static int pcmcia_card_add(struct pcmcia_socket *s)
 	if (!(s->resource_setup_done))
 		return -EAGAIN; /* try again, but later... */
 
-	pcmcia_validate_mem(s);
+	if (pcmcia_validate_mem(s))
+		return -EAGAIN; /* try again, but later... */
+
 	ret = pccard_validate_cis(s, BIND_FN_ALL, &cisinfo);
 	if (ret || !cisinfo.Chains) {
 		ds_dbg(0, "invalid CIS or invalid resources\n");
@@ -779,8 +832,8 @@ static int pcmcia_bus_match(struct device * dev, struct device_driver * drv) {
 
 #ifdef CONFIG_HOTPLUG
 
-static int pcmcia_bus_hotplug(struct device *dev, char **envp, int num_envp,
-			      char *buffer, int buffer_size)
+static int pcmcia_bus_uevent(struct device *dev, char **envp, int num_envp,
+			     char *buffer, int buffer_size)
 {
 	struct pcmcia_device *p_dev;
 	int i, length = 0;
@@ -800,31 +853,31 @@ static int pcmcia_bus_hotplug(struct device *dev, char **envp, int num_envp,
 
 	i = 0;
 
-	if (add_hotplug_env_var(envp, num_envp, &i,
-				buffer, buffer_size, &length,
-				"SOCKET_NO=%u",
-				p_dev->socket->sock))
+	if (add_uevent_var(envp, num_envp, &i,
+			   buffer, buffer_size, &length,
+			   "SOCKET_NO=%u",
+			   p_dev->socket->sock))
 		return -ENOMEM;
 
-	if (add_hotplug_env_var(envp, num_envp, &i,
-				buffer, buffer_size, &length,
-				"DEVICE_NO=%02X",
-				p_dev->device_no))
+	if (add_uevent_var(envp, num_envp, &i,
+			   buffer, buffer_size, &length,
+			   "DEVICE_NO=%02X",
+			   p_dev->device_no))
 		return -ENOMEM;
 
-	if (add_hotplug_env_var(envp, num_envp, &i,
-				buffer, buffer_size, &length,
-				"MODALIAS=pcmcia:m%04Xc%04Xf%02Xfn%02Xpfn%02X"
-				"pa%08Xpb%08Xpc%08Xpd%08X",
-				p_dev->has_manf_id ? p_dev->manf_id : 0,
-				p_dev->has_card_id ? p_dev->card_id : 0,
-				p_dev->has_func_id ? p_dev->func_id : 0,
-				p_dev->func,
-				p_dev->device_no,
-				hash[0],
-				hash[1],
-				hash[2],
-				hash[3]))
+	if (add_uevent_var(envp, num_envp, &i,
+			   buffer, buffer_size, &length,
+			   "MODALIAS=pcmcia:m%04Xc%04Xf%02Xfn%02Xpfn%02X"
+			   "pa%08Xpb%08Xpc%08Xpd%08X",
+			   p_dev->has_manf_id ? p_dev->manf_id : 0,
+			   p_dev->has_card_id ? p_dev->card_id : 0,
+			   p_dev->has_func_id ? p_dev->func_id : 0,
+			   p_dev->func,
+			   p_dev->device_no,
+			   hash[0],
+			   hash[1],
+			   hash[2],
+			   hash[3]))
 		return -ENOMEM;
 
 	envp[i] = NULL;
@@ -834,7 +887,7 @@ static int pcmcia_bus_hotplug(struct device *dev, char **envp, int num_envp,
 
 #else
 
-static int pcmcia_bus_hotplug(struct device *dev, char **envp, int num_envp,
+static int pcmcia_bus_uevent(struct device *dev, char **envp, int num_envp,
 			      char *buffer, int buffer_size)
 {
 	return -ENODEV;
@@ -918,55 +971,84 @@ static struct device_attribute pcmcia_dev_attrs[] = {
 	__ATTR_NULL,
 };
 
+/* PM support, also needed for reset */
 
-/*======================================================================
+static int pcmcia_dev_suspend(struct device * dev, pm_message_t state)
+{
+	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
+	struct pcmcia_driver *p_drv = NULL;
 
-    The card status event handler.
-    
-======================================================================*/
+	if (dev->driver)
+		p_drv = to_pcmcia_drv(dev->driver);
 
-struct send_event_data {
-	struct pcmcia_socket *skt;
-	event_t event;
-	int priority;
-};
+	if (p_drv && p_drv->suspend)
+		return p_drv->suspend(p_dev);
 
-static int send_event_callback(struct device *dev, void * _data)
+	return 0;
+}
+
+
+static int pcmcia_dev_resume(struct device * dev)
 {
 	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
-	struct pcmcia_driver *p_drv;
-	struct send_event_data *data = _data;
+        struct pcmcia_driver *p_drv = NULL;
 
-	/* we get called for all sockets, but may only pass the event
-	 * for drivers _on the affected socket_ */
-	if (p_dev->socket != data->skt)
-		return 0;
+	if (dev->driver)
+		p_drv = to_pcmcia_drv(dev->driver);
 
-	p_drv = to_pcmcia_drv(p_dev->dev.driver);
-	if (!p_drv)
+	if (p_drv && p_drv->resume)
+		return p_drv->resume(p_dev);
+
+	return 0;
+}
+
+
+static int pcmcia_bus_suspend_callback(struct device *dev, void * _data)
+{
+	struct pcmcia_socket *skt = _data;
+	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
+
+	if (p_dev->socket != skt)
 		return 0;
 
-	if (p_dev->state & (CLIENT_UNBOUND|CLIENT_STALE))
+	return dpm_runtime_suspend(dev, PMSG_SUSPEND);
+}
+
+static int pcmcia_bus_resume_callback(struct device *dev, void * _data)
+{
+	struct pcmcia_socket *skt = _data;
+	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
+
+	if (p_dev->socket != skt)
 		return 0;
 
-	if (p_drv->event)
-		return p_drv->event(data->event, data->priority,
-				    &p_dev->event_callback_args);
+	dpm_runtime_resume(dev);
+
+	return 0;
+}
 
+static int pcmcia_bus_resume(struct pcmcia_socket *skt)
+{
+	bus_for_each_dev(&pcmcia_bus_type, NULL, skt, pcmcia_bus_resume_callback);
 	return 0;
 }
 
-static int send_event(struct pcmcia_socket *s, event_t event, int priority)
+static int pcmcia_bus_suspend(struct pcmcia_socket *skt)
 {
-	struct send_event_data private;
+	if (bus_for_each_dev(&pcmcia_bus_type, NULL, skt,
+			     pcmcia_bus_suspend_callback)) {
+		pcmcia_bus_resume(skt);
+		return -EIO;
+	}
+	return 0;
+}
 
-	private.skt = s;
-	private.event = event;
-	private.priority = priority;
 
-	return bus_for_each_dev(&pcmcia_bus_type, NULL, &private, send_event_callback);
-} /* send_event */
+/*======================================================================
 
+    The card status event handler.
+    
+======================================================================*/
 
 /* Normally, the event is passed to individual drivers after
  * informing userspace. Only for CS_EVENT_CARD_REMOVAL this
@@ -976,20 +1058,17 @@ static int send_event(struct pcmcia_socket *s, event_t event, int priority)
 static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)
 {
 	struct pcmcia_socket *s = pcmcia_get_socket(skt);
-	int ret = 0;
 
 	ds_dbg(1, "ds_event(0x%06x, %d, 0x%p)\n",
 	       event, priority, skt);
-    
-	switch (event) {
 
+	switch (event) {
 	case CS_EVENT_CARD_REMOVAL:
 		s->pcmcia_state.present = 0;
-	    	send_event(skt, event, priority);
-		unbind_request(skt);
+		pcmcia_card_remove(skt);
 		handle_event(skt, event);
 		break;
-	
+
 	case CS_EVENT_CARD_INSERTION:
 		s->pcmcia_state.present = 1;
 		pcmcia_card_add(skt);
@@ -997,12 +1076,14 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)
 		break;
 
 	case CS_EVENT_EJECTION_REQUEST:
-		ret = send_event(skt, event, priority);
 		break;
 
+	case CS_EVENT_PM_SUSPEND:
+	case CS_EVENT_PM_RESUME:
+	case CS_EVENT_RESET_PHYSICAL:
+	case CS_EVENT_CARD_RESET:
 	default:
 		handle_event(skt, event);
-		send_event(skt, event, priority);
 		break;
     }
 
@@ -1012,152 +1093,12 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)
 } /* ds_event */
 
 
-
-int pcmcia_register_client(struct pcmcia_device **handle, client_reg_t *req)
-{
-	struct pcmcia_socket *s = NULL;
-	struct pcmcia_device *p_dev = NULL;
-	struct pcmcia_driver *p_drv = NULL;
-
-	/* Look for unbound client with matching dev_info */
-	down_read(&pcmcia_socket_list_rwsem);
-	list_for_each_entry(s, &pcmcia_socket_list, socket_list) {
-		unsigned long flags;
-
-		if (s->state & SOCKET_CARDBUS)
-			continue;
-
-		s = pcmcia_get_socket(s);
-		if (!s)
-			continue;
-		spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
-		list_for_each_entry(p_dev, &s->devices_list, socket_device_list) {
-			p_dev = pcmcia_get_dev(p_dev);
-			if (!p_dev)
-				continue;
-			if (!(p_dev->state & CLIENT_UNBOUND) ||
-			    (!p_dev->dev.driver)) {
-				pcmcia_put_dev(p_dev);
-				continue;
-			}
-			p_drv = to_pcmcia_drv(p_dev->dev.driver);
-			if (!strncmp(p_drv->drv.name, (char *)req->dev_info, DEV_NAME_LEN)) {
-				spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
-				goto found;
-			}
-			pcmcia_put_dev(p_dev);
-		}
-		spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
-		pcmcia_put_socket(s);
-	}
- found:
-	up_read(&pcmcia_socket_list_rwsem);
-	if (!p_dev)
-		return -ENODEV;
-
-	pcmcia_put_socket(s); /* safe, as we already hold a reference from bind_device */
-
-	*handle = p_dev;
-	p_dev->state &= ~CLIENT_UNBOUND;
-	p_dev->event_callback_args = req->event_callback_args;
-	p_dev->event_callback_args.client_handle = p_dev;
-
-
-	if (!s->functions) {
-		cistpl_longlink_mfc_t mfc;
-		if (pccard_read_tuple(s, p_dev->func, CISTPL_LONGLINK_MFC, &mfc)
-		    == CS_SUCCESS)
-			s->functions = mfc.nfn;
-		else
-			s->functions = 1;
-		s->config = kmalloc(sizeof(config_t) * s->functions,
-				    GFP_KERNEL);
-		if (!s->config)
-			goto out_no_resource;
-		memset(s->config, 0, sizeof(config_t) * s->functions);
-	}
-
-	ds_dbg(1, "register_client(): client 0x%p, dev %s\n",
-	       p_dev, p_dev->dev.bus_id);
-
-	if ((s->state & (SOCKET_PRESENT|SOCKET_CARDBUS)) == SOCKET_PRESENT) {
-		if (p_drv->event)
-			p_drv->event(CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW,
-				     &p_dev->event_callback_args);
-
-	}
-
-	return CS_SUCCESS;
-
- out_no_resource:
-	pcmcia_put_dev(p_dev);
-	return CS_OUT_OF_RESOURCE;
-} /* register_client */
-EXPORT_SYMBOL(pcmcia_register_client);
-
-
-/* unbind _all_ devices attached to a given pcmcia_bus_socket. The
- * drivers have been called with EVENT_CARD_REMOVAL before.
- */
-static int unbind_request(struct pcmcia_socket *s)
-{
-	struct pcmcia_device	*p_dev;
-	unsigned long		flags;
-
-	ds_dbg(2, "unbind_request(%d)\n", s->sock);
-
-	s->device_count = 0;
-
-	for (;;) {
-		/* unregister all pcmcia_devices registered with this socket*/
-		spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
-		if (list_empty(&s->devices_list)) {
-			spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
- 			return 0;
-		}
-		p_dev = list_entry((&s->devices_list)->next, struct pcmcia_device, socket_device_list);
-		list_del(&p_dev->socket_device_list);
-		p_dev->state |= CLIENT_STALE;
-		spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
-
-		device_unregister(&p_dev->dev);
-	}
-
-	return 0;
-} /* unbind_request */
-
-int pcmcia_deregister_client(struct pcmcia_device *p_dev)
-{
-	struct pcmcia_socket *s;
-	int i;
-
-	s = p_dev->socket;
-	ds_dbg(1, "deregister_client(%p)\n", p_dev);
-
-	if (p_dev->state & (CLIENT_IRQ_REQ|CLIENT_IO_REQ|CLIENT_CONFIG_LOCKED))
-		goto warn_out;
-	for (i = 0; i < MAX_WIN; i++)
-		if (p_dev->state & CLIENT_WIN_REQ(i))
-			goto warn_out;
-
-	if (p_dev->state & CLIENT_STALE) {
-		p_dev->state &= ~CLIENT_STALE;
-		pcmcia_put_dev(p_dev);
-	} else {
-		p_dev->state = CLIENT_UNBOUND;
-	}
-
-	return CS_SUCCESS;
- warn_out:
-	printk(KERN_WARNING "ds: deregister_client was called too early.\n");
-	return CS_IN_USE;
-} /* deregister_client */
-EXPORT_SYMBOL(pcmcia_deregister_client);
-
 static struct pcmcia_callback pcmcia_bus_callback = {
 	.owner = THIS_MODULE,
 	.event = ds_event,
 	.requery = pcmcia_bus_rescan,
+	.suspend = pcmcia_bus_suspend,
+	.resume = pcmcia_bus_resume,
 };
 
 static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev,
@@ -1223,9 +1164,11 @@ static struct class_interface pcmcia_bus_interface = {
 
 struct bus_type pcmcia_bus_type = {
 	.name = "pcmcia",
-	.hotplug = pcmcia_bus_hotplug,
+	.uevent = pcmcia_bus_uevent,
 	.match = pcmcia_bus_match,
 	.dev_attrs = pcmcia_dev_attrs,
+	.suspend = pcmcia_dev_suspend,
+	.resume = pcmcia_dev_resume,
 };
 
 
diff --git a/drivers/pcmcia/hd64465_ss.c b/drivers/pcmcia/hd64465_ss.c
index 561706ba4499..b39435bbfaeb 100644
--- a/drivers/pcmcia/hd64465_ss.c
+++ b/drivers/pcmcia/hd64465_ss.c
@@ -417,18 +417,6 @@ static int hs_get_status(struct pcmcia_socket *s, u_int *value)
 
 /*============================================================*/
 
-static int hs_get_socket(struct pcmcia_socket *s, socket_state_t *state)
-{
-    	hs_socket_t *sp = container_of(s, struct hs_socket_t, socket);
-
-    	DPRINTK("hs_get_socket(%d)\n", sock);
-	
-	*state = sp->state;
-	return 0;
-}
-
-/*============================================================*/
-
 static int hs_set_socket(struct pcmcia_socket *s, socket_state_t *state)
 {
     	hs_socket_t *sp = container_of(s, struct hs_socket_t, socket);
@@ -749,7 +737,6 @@ static irqreturn_t hs_interrupt(int irq, void *dev, struct pt_regs *regs)
 static struct pccard_operations hs_operations = {
 	.init			= hs_init,
 	.get_status		= hs_get_status,
-	.get_socket		= hs_get_socket,
 	.set_socket		= hs_set_socket,
 	.set_io_map		= hs_set_io_map,
 	.set_mem_map		= hs_set_mem_map,
diff --git a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c
index f3fdc748659d..7979c85df3dc 100644
--- a/drivers/pcmcia/i82092.c
+++ b/drivers/pcmcia/i82092.c
@@ -66,7 +66,6 @@ static struct pci_driver i82092aa_pci_drv = {
 static struct pccard_operations i82092aa_operations = {
 	.init 		 	= i82092aa_init,
 	.get_status		= i82092aa_get_status,
-	.get_socket		= i82092aa_get_socket,
 	.set_socket		= i82092aa_set_socket,
 	.set_io_map		= i82092aa_set_io_map,
 	.set_mem_map		= i82092aa_set_mem_map,
@@ -482,78 +481,6 @@ static int i82092aa_get_status(struct pcmcia_socket *socket, u_int *value)
 }
 
 
-static int i82092aa_get_socket(struct pcmcia_socket *socket, socket_state_t *state) 
-{
-	unsigned int sock = container_of(socket, struct socket_info, socket)->number;
-	unsigned char reg,vcc,vpp;
-	
-	enter("i82092aa_get_socket");
-	state->flags    = 0;
-	state->Vcc      = 0;
-	state->Vpp      = 0;
-	state->io_irq   = 0;
-	state->csc_mask = 0;
-
-	/* First the power status of the socket */
-	reg = indirect_read(sock,I365_POWER); /* PCTRL - Power Control Register */
-
-	if (reg & I365_PWR_AUTO)
-		state->flags |= SS_PWR_AUTO;  /* Automatic Power Switch */
-		
-	if (reg & I365_PWR_OUT)
-		state->flags |= SS_OUTPUT_ENA; /* Output signals are enabled */
-		
-	vcc = reg & I365_VCC_MASK;    vpp = reg & I365_VPP1_MASK;
-	
-	if (reg & I365_VCC_5V) { /* Can still be 3.3V, in this case the Vcc value will be overwritten later */
-		state->Vcc = 50;
-		
-		if (vpp == I365_VPP1_5V)
-			state->Vpp = 50;
-		if (vpp == I365_VPP1_12V)
-			state->Vpp = 120;
-			
-	}
-	
-	if ((reg & I365_VCC_3V)==I365_VCC_3V)
-		state->Vcc = 33;
-	
-	
-	/* Now the IO card, RESET flags and IO interrupt */
-	
-	reg = indirect_read(sock, I365_INTCTL); /* IGENC, Interrupt and General Control */
-	
-	if ((reg & I365_PC_RESET)==0)
-		state->flags |= SS_RESET;
-	if (reg & I365_PC_IOCARD) 
-		state->flags |= SS_IOCARD; /* This is an IO card */
-	
-	/* Set the IRQ number */
-	if (sockets[sock].dev!=NULL)
-		state->io_irq = sockets[sock].dev->irq;
-	
-	/* Card status change */
-	reg = indirect_read(sock, I365_CSCINT); /* CSCICR, Card Status Change Interrupt Configuration */
-	
-	if (reg & I365_CSC_DETECT) 
-		state->csc_mask |= SS_DETECT; /* Card detect is enabled */
-	
-	if (state->flags & SS_IOCARD) {/* IO Cards behave different */
-		if (reg & I365_CSC_STSCHG)
-			state->csc_mask |= SS_STSCHG;
-	} else {
-		if (reg & I365_CSC_BVD1) 
-			state->csc_mask |= SS_BATDEAD;
-		if (reg & I365_CSC_BVD2) 
-			state->csc_mask |= SS_BATWARN;
-		if (reg & I365_CSC_READY) 
-			state->csc_mask |= SS_READY;
-	}
-		
-	leave("i82092aa_get_socket");
-	return 0;
-}
-
 static int i82092aa_set_socket(struct pcmcia_socket *socket, socket_state_t *state) 
 {
 	unsigned int sock = container_of(socket, struct socket_info, socket)->number;
diff --git a/drivers/pcmcia/i82092aa.h b/drivers/pcmcia/i82092aa.h
index b98cac7bda9f..9c14599d0673 100644
--- a/drivers/pcmcia/i82092aa.h
+++ b/drivers/pcmcia/i82092aa.h
@@ -29,7 +29,6 @@ static irqreturn_t i82092aa_interrupt(int irq, void *dev, struct pt_regs *regs);
 
 
 static int i82092aa_get_status(struct pcmcia_socket *socket, u_int *value);
-static int i82092aa_get_socket(struct pcmcia_socket *socket, socket_state_t *state);
 static int i82092aa_set_socket(struct pcmcia_socket *socket, socket_state_t *state);
 static int i82092aa_set_io_map(struct pcmcia_socket *socket, struct pccard_io_map *io);
 static int i82092aa_set_mem_map(struct pcmcia_socket *socket, struct pccard_mem_map *mem);
diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c
index 4d56bc9926d6..35a92d1e4945 100644
--- a/drivers/pcmcia/i82365.c
+++ b/drivers/pcmcia/i82365.c
@@ -940,78 +940,6 @@ static int i365_get_status(u_short sock, u_int *value)
 
 /*====================================================================*/
 
-static int i365_get_socket(u_short sock, socket_state_t *state)
-{
-    struct i82365_socket *t = &socket[sock];
-    u_char reg, vcc, vpp;
-    
-    reg = i365_get(sock, I365_POWER);
-    state->flags = (reg & I365_PWR_AUTO) ? SS_PWR_AUTO : 0;
-    state->flags |= (reg & I365_PWR_OUT) ? SS_OUTPUT_ENA : 0;
-    vcc = reg & I365_VCC_MASK; vpp = reg & I365_VPP1_MASK;
-    state->Vcc = state->Vpp = 0;
-    if (t->flags & IS_CIRRUS) {
-	if (i365_get(sock, PD67_MISC_CTL_1) & PD67_MC1_VCC_3V) {
-	    if (reg & I365_VCC_5V) state->Vcc = 33;
-	    if (vpp == I365_VPP1_5V) state->Vpp = 33;
-	} else {
-	    if (reg & I365_VCC_5V) state->Vcc = 50;
-	    if (vpp == I365_VPP1_5V) state->Vpp = 50;
-	}
-	if (vpp == I365_VPP1_12V) state->Vpp = 120;
-    } else if (t->flags & IS_VG_PWR) {
-	if (i365_get(sock, VG469_VSELECT) & VG469_VSEL_VCC) {
-	    if (reg & I365_VCC_5V) state->Vcc = 33;
-	    if (vpp == I365_VPP1_5V) state->Vpp = 33;
-	} else {
-	    if (reg & I365_VCC_5V) state->Vcc = 50;
-	    if (vpp == I365_VPP1_5V) state->Vpp = 50;
-	}
-	if (vpp == I365_VPP1_12V) state->Vpp = 120;
-    } else if (t->flags & IS_DF_PWR) {
-	if (vcc == I365_VCC_3V) state->Vcc = 33;
-	if (vcc == I365_VCC_5V) state->Vcc = 50;
-	if (vpp == I365_VPP1_5V) state->Vpp = 50;
-	if (vpp == I365_VPP1_12V) state->Vpp = 120;
-    } else {
-	if (reg & I365_VCC_5V) {
-	    state->Vcc = 50;
-	    if (vpp == I365_VPP1_5V) state->Vpp = 50;
-	    if (vpp == I365_VPP1_12V) state->Vpp = 120;
-	}
-    }
-
-    /* IO card, RESET flags, IO interrupt */
-    reg = i365_get(sock, I365_INTCTL);
-    state->flags |= (reg & I365_PC_RESET) ? 0 : SS_RESET;
-    if (reg & I365_PC_IOCARD) state->flags |= SS_IOCARD;
-    state->io_irq = reg & I365_IRQ_MASK;
-    
-    /* speaker control */
-    if (t->flags & IS_CIRRUS) {
-	if (i365_get(sock, PD67_MISC_CTL_1) & PD67_MC1_SPKR_ENA)
-	    state->flags |= SS_SPKR_ENA;
-    }
-    
-    /* Card status change mask */
-    reg = i365_get(sock, I365_CSCINT);
-    state->csc_mask = (reg & I365_CSC_DETECT) ? SS_DETECT : 0;
-    if (state->flags & SS_IOCARD)
-	state->csc_mask |= (reg & I365_CSC_STSCHG) ? SS_STSCHG : 0;
-    else {
-	state->csc_mask |= (reg & I365_CSC_BVD1) ? SS_BATDEAD : 0;
-	state->csc_mask |= (reg & I365_CSC_BVD2) ? SS_BATWARN : 0;
-	state->csc_mask |= (reg & I365_CSC_READY) ? SS_READY : 0;
-    }
-    
-    debug(1, "GetSocket(%d) = flags %#3.3x, Vcc %d, Vpp %d, "
-	  "io_irq %d, csc_mask %#2.2x\n", sock, state->flags,
-	  state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
-    return 0;
-} /* i365_get_socket */
-
-/*====================================================================*/
-
 static int i365_set_socket(u_short sock, socket_state_t *state)
 {
     struct i82365_socket *t = &socket[sock];
@@ -1265,16 +1193,6 @@ static int pcic_get_status(struct pcmcia_socket *s, u_int *value)
 	LOCKED(i365_get_status(sock, value));
 }
 
-static int pcic_get_socket(struct pcmcia_socket *s, socket_state_t *state)
-{
-	unsigned int sock = container_of(s, struct i82365_socket, socket)->number;
-
-	if (socket[sock].flags & IS_ALIVE)
-		return -EINVAL;
-
-	LOCKED(i365_get_socket(sock, state));
-}
-
 static int pcic_set_socket(struct pcmcia_socket *s, socket_state_t *state)
 {
 	unsigned int sock = container_of(s, struct i82365_socket, socket)->number;
@@ -1324,7 +1242,6 @@ static int pcic_init(struct pcmcia_socket *s)
 static struct pccard_operations pcic_operations = {
 	.init			= pcic_init,
 	.get_status		= pcic_get_status,
-	.get_socket		= pcic_get_socket,
 	.set_socket		= pcic_set_socket,
 	.set_io_map		= pcic_set_io_map,
 	.set_mem_map		= pcic_set_mem_map,
diff --git a/drivers/pcmcia/m32r_cfc.c b/drivers/pcmcia/m32r_cfc.c
index 078579ae6359..071cf485e1a3 100644
--- a/drivers/pcmcia/m32r_cfc.c
+++ b/drivers/pcmcia/m32r_cfc.c
@@ -480,25 +480,6 @@ static int _pcc_get_status(u_short sock, u_int *value)
 
 /*====================================================================*/
 
-static int _pcc_get_socket(u_short sock, socket_state_t *state)
-{
-//	pcc_socket_t *t = &socket[sock];
-
-	state->flags = 0;
-	state->csc_mask = SS_DETECT;
-	state->csc_mask |= SS_READY;
-	state->io_irq = 0;
-	state->Vcc = 33;	/* 3.3V fixed */
-	state->Vpp = 33;
-
-	debug(3, "m32r_cfc: GetSocket(%d) = flags %#3.3x, Vcc %d, Vpp %d, "
-		  "io_irq %d, csc_mask %#2.2x\n", sock, state->flags,
-		  state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
-	return 0;
-} /* _get_socket */
-
-/*====================================================================*/
-
 static int _pcc_set_socket(u_short sock, socket_state_t *state)
 {
 	debug(3, "m32r_cfc: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
@@ -667,18 +648,6 @@ static int pcc_get_status(struct pcmcia_socket *s, u_int *value)
 	LOCKED(_pcc_get_status(sock, value));
 }
 
-static int pcc_get_socket(struct pcmcia_socket *s, socket_state_t *state)
-{
-	unsigned int sock = container_of(s, struct pcc_socket, socket)->number;
-
-	if (socket[sock].flags & IS_ALIVE) {
-		debug(3, "m32r_cfc: pcc_get_socket: sock(%d) -EINVAL\n", sock);
-		return -EINVAL;
-	}
-	debug(3, "m32r_cfc: pcc_get_socket: sock(%d)\n", sock);
-	LOCKED(_pcc_get_socket(sock, state));
-}
-
 static int pcc_set_socket(struct pcmcia_socket *s, socket_state_t *state)
 {
 	unsigned int sock = container_of(s, struct pcc_socket, socket)->number;
@@ -724,7 +693,6 @@ static int pcc_init(struct pcmcia_socket *s)
 static struct pccard_operations pcc_operations = {
 	.init			= pcc_init,
 	.get_status		= pcc_get_status,
-	.get_socket		= pcc_get_socket,
 	.set_socket		= pcc_set_socket,
 	.set_io_map		= pcc_set_io_map,
 	.set_mem_map		= pcc_set_mem_map,
diff --git a/drivers/pcmcia/m32r_pcc.c b/drivers/pcmcia/m32r_pcc.c
index 356a6fb416a1..70d5f0748d55 100644
--- a/drivers/pcmcia/m32r_pcc.c
+++ b/drivers/pcmcia/m32r_pcc.c
@@ -429,16 +429,6 @@ static int _pcc_get_status(u_short sock, u_int *value)
 
 /*====================================================================*/
 
-static int _pcc_get_socket(u_short sock, socket_state_t *state)
-{
-	debug(3, "m32r-pcc: GetSocket(%d) = flags %#3.3x, Vcc %d, Vpp %d, "
-		  "io_irq %d, csc_mask %#2.2x\n", sock, state->flags,
-		  state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
-	return 0;
-} /* _get_socket */
-
-/*====================================================================*/
-
 static int _pcc_set_socket(u_short sock, socket_state_t *state)
 {
 	u_long reg = 0;
@@ -641,15 +631,6 @@ static int pcc_get_status(struct pcmcia_socket *s, u_int *value)
 	LOCKED(_pcc_get_status(sock, value));
 }
 
-static int pcc_get_socket(struct pcmcia_socket *s, socket_state_t *state)
-{
-	unsigned int sock = container_of(s, struct pcc_socket, socket)->number;
-
-	if (socket[sock].flags & IS_ALIVE)
-		return -EINVAL;
-	LOCKED(_pcc_get_socket(sock, state));
-}
-
 static int pcc_set_socket(struct pcmcia_socket *s, socket_state_t *state)
 {
 	unsigned int sock = container_of(s, struct pcc_socket, socket)->number;
@@ -687,7 +668,6 @@ static int pcc_init(struct pcmcia_socket *s)
 static struct pccard_operations pcc_operations = {
 	.init			= pcc_init,
 	.get_status		= pcc_get_status,
-	.get_socket		= pcc_get_socket,
 	.set_socket		= pcc_set_socket,
 	.set_io_map		= pcc_set_io_map,
 	.set_mem_map		= pcc_set_mem_map,
diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c
index 6d9f71cfcb34..0e07d9535116 100644
--- a/drivers/pcmcia/m8xx_pcmcia.c
+++ b/drivers/pcmcia/m8xx_pcmcia.c
@@ -9,6 +9,9 @@
  *     <oliver.kurth@cyclades.de>
  * Further fixes, v2.6 kernel port
  *     <marcelo.tosatti@cyclades.com>
+ * 
+ * Some fixes, additions (C) 2005 Montavista Software, Inc. 
+ *     <vbordug@ru.mvista.com>
  *
  * "The ExCA standard specifies that socket controllers should provide
  * two IO and five memory windows per socket, which can be independently
@@ -97,6 +100,11 @@ MODULE_LICENSE("Dual MPL/GPL");
 #endif
 #endif
 
+#if defined(CONFIG_MPC885ADS)
+#define CONFIG_PCMCIA_SLOT_A
+#define PCMCIA_GLITCHY_CD
+#endif
+
 /* Cyclades ACS uses both slots */
 #ifdef CONFIG_PRxK
 #define CONFIG_PCMCIA_SLOT_A
@@ -374,10 +382,10 @@ static int voltage_set(int slot, int vcc, int vpp)
 	}
 
 	/* first, turn off all power */
-	out_be32(&((u32 *)BCSR1), in_be32(&((u32 *)BCSR1)) & ~(BCSR1_PCCVCC_MASK | BCSR1_PCCVPP_MASK));
+	out_be32((u32 *)BCSR1, in_be32((u32 *)BCSR1) & ~(BCSR1_PCCVCC_MASK | BCSR1_PCCVPP_MASK));
 
 	/* enable new powersettings */
-	out_be32(&((u32 *)BCSR1), in_be32(&((u32 *)BCSR1)) | reg);
+	out_be32((u32 *)BCSR1, in_be32((u32 *)BCSR1) | reg);
 
 	return 0;
 }
@@ -386,12 +394,89 @@ static int voltage_set(int slot, int vcc, int vpp)
 
 static void hardware_enable(int slot)
 {
-	out_be32(&((u32 *)BCSR1), in_be32(&((u32 *)BCSR1)) & ~BCSR1_PCCEN);
+	out_be32((u32 *)BCSR1, in_be32((u32 *)BCSR1) & ~BCSR1_PCCEN);
 }
 
 static void hardware_disable(int slot)
 {
-	out_be32(&((u32 *)BCSR1), in_be32(&((u32 *)BCSR1)) |  BCSR1_PCCEN);
+	out_be32((u32 *)BCSR1, in_be32((u32 *)BCSR1) |  BCSR1_PCCEN);
+}
+
+#endif
+
+/* MPC885ADS Boards */
+
+#if defined(CONFIG_MPC885ADS)
+
+#define PCMCIA_BOARD_MSG "MPC885ADS"
+
+static int voltage_set(int slot, int vcc, int vpp)
+{
+	u32 reg = 0;
+	unsigned *bcsr_io;
+
+	bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
+
+	switch(vcc) {
+		case 0:
+			break;
+		case 33:
+			reg |= BCSR1_PCCVCC0;
+			break;
+		case 50:
+			reg |= BCSR1_PCCVCC1;
+			break;
+		default:
+			return 1;
+	}
+
+	switch(vpp) {
+		case 0:
+			break;
+		case 33:
+		case 50:
+			if(vcc == vpp)
+				reg |= BCSR1_PCCVPP1;
+			else
+				return 1;
+			break;
+		case 120:
+			if ((vcc == 33) || (vcc == 50))
+				reg |= BCSR1_PCCVPP0;
+			else
+				return 1;
+		default:
+			return 1;
+	}
+
+	/* first, turn off all power */
+	out_be32(bcsr_io, in_be32(bcsr_io) & ~(BCSR1_PCCVCC_MASK | BCSR1_PCCVPP_MASK));
+
+	/* enable new powersettings */
+	out_be32(bcsr_io, in_be32(bcsr_io) | reg);
+
+	iounmap(bcsr_io);
+	return 0;
+}
+
+#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
+
+static void hardware_enable(int slot)
+{
+	unsigned *bcsr_io;
+
+	bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
+	out_be32(bcsr_io, in_be32(bcsr_io) & ~BCSR1_PCCEN);
+	iounmap(bcsr_io);
+}
+
+static void hardware_disable(int slot)
+{
+	unsigned *bcsr_io;
+
+	bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
+	out_be32(bcsr_io, in_be32(bcsr_io) |  BCSR1_PCCEN);
+	iounmap(bcsr_io);
 }
 
 #endif
@@ -440,10 +525,10 @@ static int voltage_set(int slot, int vcc, int vpp)
 	}
 
 	/* first, turn off all power */
-	out_8(&((u8 *)MBX_CSR2_ADDR), in_8(&((u8 *)MBX_CSR2_ADDR)) & ~(CSR2_VCC_MASK | CSR2_VPP_MASK));
+	out_8((u8 *)MBX_CSR2_ADDR, in_8((u8 *)MBX_CSR2_ADDR) & ~(CSR2_VCC_MASK | CSR2_VPP_MASK));
 
 	/* enable new powersettings */
-	out_8(&((u8 *)MBX_CSR2_ADDR), in_8(&((u8 *)MBX_CSR2_ADDR)) | reg);
+	out_8((u8 *)MBX_CSR2_ADDR, in_8((u8 *)MBX_CSR2_ADDR) | reg);
 
 	return 0;
 }
@@ -823,17 +908,6 @@ static int m8xx_get_status(struct pcmcia_socket *sock, unsigned int *value)
 	return 0;
 }
 
-static int m8xx_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
-{
-	int lsock = container_of(sock, struct socket_info, socket)->slot;
-	*state = socket[lsock].state; /* copy the whole structure */
-
-	dprintk("GetSocket(%d) = flags %#3.3x, Vcc %d, Vpp %d, "
-	      "io_irq %d, csc_mask %#2.2x\n", lsock, state->flags,
-	      state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
-	return 0;
-}
-
 static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
 {
 	int lsock = container_of(sock, struct socket_info, socket)->slot;
@@ -1023,8 +1097,7 @@ static int m8xx_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io)
 		if(io->flags & MAP_WRPROT)
 			reg |= M8XX_PCMCIA_POR_WRPROT;
 
-		/*if(io->flags & (MAP_16BIT | MAP_AUTOSZ))*/
-		if(io->flags & MAP_16BIT)
+		if(io->flags & (MAP_16BIT | MAP_AUTOSZ))
 			reg |= M8XX_PCMCIA_POR_16BIT;
 
 		if(io->flags & MAP_ACTIVE)
@@ -1169,7 +1242,6 @@ static struct pccard_operations m8xx_services = {
 	.init	= m8xx_sock_init,
 	.suspend = m8xx_suspend,
 	.get_status = m8xx_get_status,
-	.get_socket = m8xx_get_socket,
 	.set_socket = m8xx_set_socket,
 	.set_io_map = m8xx_set_io_map,
 	.set_mem_map = m8xx_set_mem_map,
@@ -1244,7 +1316,7 @@ static int __init m8xx_init(void)
 		socket[i].socket.io_offset = 0;
 		socket[i].socket.pci_irq = i  ? 7 : 9;
 		socket[i].socket.ops = &m8xx_services;
-		socket[i].socket.resource_ops = &pccard_nonstatic_ops;
+		socket[i].socket.resource_ops = &pccard_iodyn_ops;
 		socket[i].socket.cb_dev = NULL;
 		socket[i].socket.dev.dev = &m8xx_device.dev;
 	}
diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c
index 20642f0e7bfe..f2789afb22b2 100644
--- a/drivers/pcmcia/pd6729.c
+++ b/drivers/pcmcia/pd6729.c
@@ -304,75 +304,6 @@ static int pd6729_get_status(struct pcmcia_socket *sock, u_int *value)
 }
 
 
-static int pd6729_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
-{
-	struct pd6729_socket *socket
-			= container_of(sock, struct pd6729_socket, socket);
-	unsigned char reg, vcc, vpp;
-
-	state->flags    = 0;
-	state->Vcc      = 0;
-	state->Vpp      = 0;
-	state->io_irq   = 0;
-	state->csc_mask = 0;
-
-	/* First the power status of the socket */
-	reg = indirect_read(socket, I365_POWER);
-
-	if (reg & I365_PWR_AUTO)
-		state->flags |= SS_PWR_AUTO;  /* Automatic Power Switch */
-
-	if (reg & I365_PWR_OUT)
-		state->flags |= SS_OUTPUT_ENA; /* Output signals are enabled */
-
-	vcc = reg & I365_VCC_MASK;    vpp = reg & I365_VPP1_MASK;
-
-	if (reg & I365_VCC_5V) {
-		state->Vcc = (indirect_read(socket, PD67_MISC_CTL_1) &
-			PD67_MC1_VCC_3V) ? 33 : 50;
-
-		if (vpp == I365_VPP1_5V) {
-			if (state->Vcc == 50)
-				state->Vpp = 50;
-			else
-				state->Vpp = 33;
-		}
-		if (vpp == I365_VPP1_12V)
-			state->Vpp = 120;
-	}
-
-	/* Now the IO card, RESET flags and IO interrupt */
-	reg = indirect_read(socket, I365_INTCTL);
-
-	if ((reg & I365_PC_RESET) == 0)
-		state->flags |= SS_RESET;
-	if (reg & I365_PC_IOCARD)
-		state->flags |= SS_IOCARD; /* This is an IO card */
-
-	/* Set the IRQ number */
-	state->io_irq = socket->card_irq;
-
-	/* Card status change */
-	reg = indirect_read(socket, I365_CSCINT);
-
-	if (reg & I365_CSC_DETECT)
-		state->csc_mask |= SS_DETECT; /* Card detect is enabled */
-
-	if (state->flags & SS_IOCARD) {/* IO Cards behave different */
-		if (reg & I365_CSC_STSCHG)
-			state->csc_mask |= SS_STSCHG;
-	} else {
-		if (reg & I365_CSC_BVD1)
-			state->csc_mask |= SS_BATDEAD;
-		if (reg & I365_CSC_BVD2)
-			state->csc_mask |= SS_BATWARN;
-		if (reg & I365_CSC_READY)
-			state->csc_mask |= SS_READY;
-	}
-
-	return 0;
-}
-
 static int pd6729_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
 {
 	struct pd6729_socket *socket
@@ -640,7 +571,6 @@ static int pd6729_init(struct pcmcia_socket *sock)
 static struct pccard_operations pd6729_operations = {
 	.init 			= pd6729_init,
 	.get_status		= pd6729_get_status,
-	.get_socket		= pd6729_get_socket,
 	.set_socket		= pd6729_set_socket,
 	.set_io_map		= pd6729_set_io_map,
 	.set_mem_map		= pd6729_set_mem_map,
@@ -704,13 +634,11 @@ static int __devinit pd6729_pci_probe(struct pci_dev *dev,
 	char configbyte;
 	struct pd6729_socket *socket;
 
-	socket = kmalloc(sizeof(struct pd6729_socket) * MAX_SOCKETS,
+	socket = kzalloc(sizeof(struct pd6729_socket) * MAX_SOCKETS,
 			 GFP_KERNEL);
 	if (!socket)
 		return -ENOMEM;
 
-	memset(socket, 0, sizeof(struct pd6729_socket) * MAX_SOCKETS);
-
 	if ((ret = pci_enable_device(dev)))
 		goto err_out_free_mem;
 
diff --git a/drivers/pcmcia/pxa2xx_mainstone.c b/drivers/pcmcia/pxa2xx_mainstone.c
index 5209d8c7764f..5d957dfe23d9 100644
--- a/drivers/pcmcia/pxa2xx_mainstone.c
+++ b/drivers/pcmcia/pxa2xx_mainstone.c
@@ -171,10 +171,9 @@ static int __init mst_pcmcia_init(void)
 {
 	int ret;
 
-	mst_pcmcia_device = kmalloc(sizeof(*mst_pcmcia_device), GFP_KERNEL);
+	mst_pcmcia_device = kzalloc(sizeof(*mst_pcmcia_device), GFP_KERNEL);
 	if (!mst_pcmcia_device)
 		return -ENOMEM;
-	memset(mst_pcmcia_device, 0, sizeof(*mst_pcmcia_device));
 	mst_pcmcia_device->name = "pxa2xx-pcmcia";
 	mst_pcmcia_device->dev.platform_data = &mst_pcmcia_ops;
 
diff --git a/drivers/pcmcia/pxa2xx_sharpsl.c b/drivers/pcmcia/pxa2xx_sharpsl.c
index 4fbd995360b0..12a7244a5ec8 100644
--- a/drivers/pcmcia/pxa2xx_sharpsl.c
+++ b/drivers/pcmcia/pxa2xx_sharpsl.c
@@ -264,11 +264,10 @@ static int __init sharpsl_pcmcia_init(void)
 	int ret;
 
 	sharpsl_pcmcia_ops.nr=platform_scoop_config->num_devs;
-	sharpsl_pcmcia_device = kmalloc(sizeof(*sharpsl_pcmcia_device), GFP_KERNEL);
+	sharpsl_pcmcia_device = kzalloc(sizeof(*sharpsl_pcmcia_device), GFP_KERNEL);
 	if (!sharpsl_pcmcia_device)
 		return -ENOMEM;
 
-	memset(sharpsl_pcmcia_device, 0, sizeof(*sharpsl_pcmcia_device));
 	sharpsl_pcmcia_device->name = "pxa2xx-pcmcia";
 	sharpsl_pcmcia_device->dev.platform_data = &sharpsl_pcmcia_ops;
 	sharpsl_pcmcia_device->dev.parent=platform_scoop_config->devs[0].dev;
diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c
index 0668384ebc8b..514609369836 100644
--- a/drivers/pcmcia/rsrc_mgr.c
+++ b/drivers/pcmcia/rsrc_mgr.c
@@ -98,10 +98,12 @@ int pcmcia_adjust_resource_info(adjust_t *adj)
 }
 EXPORT_SYMBOL(pcmcia_adjust_resource_info);
 
-void pcmcia_validate_mem(struct pcmcia_socket *s)
+int pcmcia_validate_mem(struct pcmcia_socket *s)
 {
 	if (s->resource_ops->validate_mem)
-		s->resource_ops->validate_mem(s);
+		return s->resource_ops->validate_mem(s);
+	/* if there is no callback, we can assume that everything is OK */
+	return 0;
 }
 EXPORT_SYMBOL(pcmcia_validate_mem);
 
@@ -164,3 +166,105 @@ struct pccard_resource_ops pccard_static_ops = {
 	.exit = NULL,
 };
 EXPORT_SYMBOL(pccard_static_ops);
+
+
+#ifdef CONFIG_PCCARD_IODYN
+
+static struct resource *
+make_resource(unsigned long b, unsigned long n, int flags, char *name)
+{
+	struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL);
+
+	if (res) {
+		res->name = name;
+		res->start = b;
+		res->end = b + n - 1;
+		res->flags = flags;
+	}
+	return res;
+}
+
+struct pcmcia_align_data {
+	unsigned long	mask;
+	unsigned long	offset;
+};
+
+static void pcmcia_align(void *align_data, struct resource *res,
+			unsigned long size, unsigned long align)
+{
+	struct pcmcia_align_data *data = align_data;
+	unsigned long start;
+
+	start = (res->start & ~data->mask) + data->offset;
+	if (start < res->start)
+		start += data->mask + 1;
+	res->start = start;
+
+#ifdef CONFIG_X86
+        if (res->flags & IORESOURCE_IO) {
+                if (start & 0x300) {
+                        start = (start + 0x3ff) & ~0x3ff;
+                        res->start = start;
+                }
+        }
+#endif
+
+#ifdef CONFIG_M68K
+        if (res->flags & IORESOURCE_IO) {
+		if ((res->start + size - 1) >= 1024)
+			res->start = res->end;
+	}
+#endif
+}
+
+
+static int iodyn_adjust_io_region(struct resource *res, unsigned long r_start,
+				      unsigned long r_end, struct pcmcia_socket *s)
+{
+	return adjust_resource(res, r_start, r_end - r_start + 1);
+}
+
+
+static struct resource *iodyn_find_io_region(unsigned long base, int num,
+		unsigned long align, struct pcmcia_socket *s)
+{
+	struct resource *res = make_resource(0, num, IORESOURCE_IO,
+					     s->dev.class_id);
+	struct pcmcia_align_data data;
+	unsigned long min = base;
+	int ret;
+
+	if (align == 0)
+		align = 0x10000;
+
+	data.mask = align - 1;
+	data.offset = base & data.mask;
+
+#ifdef CONFIG_PCI
+	if (s->cb_dev) {
+		ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, 1,
+					     min, 0, pcmcia_align, &data);
+	} else
+#endif
+		ret = allocate_resource(&ioport_resource, res, num, min, ~0UL,
+					1, pcmcia_align, &data);
+
+	if (ret != 0) {
+		kfree(res);
+		res = NULL;
+	}
+	return res;
+}
+
+struct pccard_resource_ops pccard_iodyn_ops = {
+	.validate_mem = NULL,
+	.adjust_io_region = iodyn_adjust_io_region,
+	.find_io = iodyn_find_io_region,
+	.find_mem = NULL,
+	.adjust_resource = NULL,
+	.init = static_init,
+	.exit = NULL,
+};
+EXPORT_SYMBOL(pccard_iodyn_ops);
+
+#endif /* CONFIG_PCCARD_IODYN */
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
index 00960a379b9c..5301ac60358f 100644
--- a/drivers/pcmcia/rsrc_nonstatic.c
+++ b/drivers/pcmcia/rsrc_nonstatic.c
@@ -75,10 +75,9 @@ static DECLARE_MUTEX(rsrc_sem);
 static struct resource *
 make_resource(unsigned long b, unsigned long n, int flags, char *name)
 {
-	struct resource *res = kmalloc(sizeof(*res), GFP_KERNEL);
+	struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL);
 
 	if (res) {
-		memset(res, 0, sizeof(*res));
 		res->name = name;
 		res->start = b;
 		res->end = b + n - 1;
@@ -200,12 +199,11 @@ static void do_io_probe(struct pcmcia_socket *s, kio_addr_t base, kio_addr_t num
 	   base, base+num-1);
 
     /* First, what does a floating port look like? */
-    b = kmalloc(256, GFP_KERNEL);
+    b = kzalloc(256, GFP_KERNEL);
     if (!b) {
             printk(KERN_ERR "do_io_probe: unable to kmalloc 256 bytes");
             return;
     }
-    memset(b, 0, 256);
     for (i = base, most = 0; i < base+num; i += 8) {
 	res = claim_region(NULL, i, 8, IORESOURCE_IO, "PCMCIA IO probe");
 	if (!res)
@@ -407,69 +405,79 @@ static int do_mem_probe(u_long base, u_long num, struct pcmcia_socket *s)
 
 static u_long inv_probe(struct resource_map *m, struct pcmcia_socket *s)
 {
-    struct socket_data *s_data = s->resource_data;
-    u_long ok;
-    if (m == &s_data->mem_db)
-	return 0;
-    ok = inv_probe(m->next, s);
-    if (ok) {
-	if (m->base >= 0x100000)
-	    sub_interval(&s_data->mem_db, m->base, m->num);
-	return ok;
-    }
-    if (m->base < 0x100000)
-	return 0;
-    return do_mem_probe(m->base, m->num, s);
+	struct socket_data *s_data = s->resource_data;
+	u_long ok;
+	if (m == &s_data->mem_db)
+		return 0;
+	ok = inv_probe(m->next, s);
+	if (ok) {
+		if (m->base >= 0x100000)
+			sub_interval(&s_data->mem_db, m->base, m->num);
+		return ok;
+	}
+	if (m->base < 0x100000)
+		return 0;
+	return do_mem_probe(m->base, m->num, s);
 }
 
-static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
+static int validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
 {
-    struct resource_map *m, mm;
-    static u_char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 };
-    u_long b, i, ok = 0;
-    struct socket_data *s_data = s->resource_data;
+	struct resource_map *m, mm;
+	static unsigned char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 };
+	unsigned long b, i, ok = 0;
+	struct socket_data *s_data = s->resource_data;
 
-    /* We do up to four passes through the list */
-    if (probe_mask & MEM_PROBE_HIGH) {
-	if (inv_probe(s_data->mem_db.next, s) > 0)
-	    return;
-	printk(KERN_NOTICE "cs: warning: no high memory space "
-	       "available!\n");
-    }
-    if ((probe_mask & MEM_PROBE_LOW) == 0)
-	return;
-    for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) {
-	mm = *m;
-	/* Only probe < 1 MB */
-	if (mm.base >= 0x100000) continue;
-	if ((mm.base | mm.num) & 0xffff) {
-	    ok += do_mem_probe(mm.base, mm.num, s);
-	    continue;
+	/* We do up to four passes through the list */
+	if (probe_mask & MEM_PROBE_HIGH) {
+		if (inv_probe(s_data->mem_db.next, s) > 0)
+			return 0;
+		printk(KERN_NOTICE "cs: warning: no high memory space "
+		       "available!\n");
+		return -ENODEV;
 	}
-	/* Special probe for 64K-aligned block */
-	for (i = 0; i < 4; i++) {
-	    b = order[i] << 12;
-	    if ((b >= mm.base) && (b+0x10000 <= mm.base+mm.num)) {
-		if (ok >= mem_limit)
-		    sub_interval(&s_data->mem_db, b, 0x10000);
-		else
-		    ok += do_mem_probe(b, 0x10000, s);
-	    }
+
+	for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) {
+		mm = *m;
+		/* Only probe < 1 MB */
+		if (mm.base >= 0x100000)
+			continue;
+		if ((mm.base | mm.num) & 0xffff) {
+			ok += do_mem_probe(mm.base, mm.num, s);
+			continue;
+		}
+		/* Special probe for 64K-aligned block */
+		for (i = 0; i < 4; i++) {
+			b = order[i] << 12;
+			if ((b >= mm.base) && (b+0x10000 <= mm.base+mm.num)) {
+				if (ok >= mem_limit)
+					sub_interval(&s_data->mem_db, b, 0x10000);
+				else
+					ok += do_mem_probe(b, 0x10000, s);
+			}
+		}
 	}
-    }
+
+	if (ok > 0)
+		return 0;
+
+	return -ENODEV;
 }
 
 #else /* CONFIG_PCMCIA_PROBE */
 
-static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
+static int validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
 {
 	struct resource_map *m, mm;
 	struct socket_data *s_data = s->resource_data;
+	unsigned long ok = 0;
 
 	for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) {
 		mm = *m;
-		do_mem_probe(mm.base, mm.num, s);
+		ok += do_mem_probe(mm.base, mm.num, s);
 	}
+	if (ok > 0)
+		return 0;
+	return -ENODEV;
 }
 
 #endif /* CONFIG_PCMCIA_PROBE */
@@ -478,27 +486,30 @@ static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
 /*
  * Locking note: Must be called with skt_sem held!
  */
-static void pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s)
+static int pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s)
 {
 	struct socket_data *s_data = s->resource_data;
-	if (probe_mem) {
-		unsigned int probe_mask;
+	unsigned int probe_mask = MEM_PROBE_LOW;
+	int ret = 0;
 
-		down(&rsrc_sem);
+	if (!probe_mem)
+		return 0;
 
-		probe_mask = MEM_PROBE_LOW;
-		if (s->features & SS_CAP_PAGE_REGS)
-			probe_mask = MEM_PROBE_HIGH;
+	down(&rsrc_sem);
 
-		if (probe_mask & ~s_data->rsrc_mem_probe) {
+	if (s->features & SS_CAP_PAGE_REGS)
+		probe_mask = MEM_PROBE_HIGH;
+
+	if (probe_mask & ~s_data->rsrc_mem_probe) {
+		if (s->state & SOCKET_PRESENT)
+			ret = validate_mem(s, probe_mask);
+		if (!ret)
 			s_data->rsrc_mem_probe |= probe_mask;
+	}
 
-			if (s->state & SOCKET_PRESENT)
-				validate_mem(s, probe_mask);
-		}
+	up(&rsrc_sem);
 
-		up(&rsrc_sem);
-	}
+	return ret;
 }
 
 struct pcmcia_align_data {
@@ -837,10 +848,9 @@ static int nonstatic_init(struct pcmcia_socket *s)
 {
 	struct socket_data *data;
 
-	data = kmalloc(sizeof(struct socket_data), GFP_KERNEL);
+	data = kzalloc(sizeof(struct socket_data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
-	memset(data, 0, sizeof(struct socket_data));
 
 	data->mem_db.next = &data->mem_db;
 	data->io_db.next = &data->io_db;
diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c
index 9e7ccd8a4321..ea7d9ca160b2 100644
--- a/drivers/pcmcia/soc_common.c
+++ b/drivers/pcmcia/soc_common.c
@@ -297,25 +297,6 @@ soc_common_pcmcia_get_status(struct pcmcia_socket *sock, unsigned int *status)
 
 
 /*
- * Implements the get_socket() operation for the in-kernel PCMCIA
- * service (formerly SS_GetSocket in Card Services). Not a very
- * exciting routine.
- *
- * Returns: 0
- */
-static int
-soc_common_pcmcia_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
-{
-	struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock);
-
-	debug(skt, 2, "\n");
-
-	*state = skt->cs_state;
-
-	return 0;
-}
-
-/*
  * Implements the set_socket() operation for the in-kernel PCMCIA
  * service (formerly SS_SetSocket in Card Services). We more or
  * less punt all of this work and let the kernel handle the details
@@ -528,7 +509,6 @@ static struct pccard_operations soc_common_pcmcia_operations = {
 	.init			= soc_common_pcmcia_sock_init,
 	.suspend		= soc_common_pcmcia_suspend,
 	.get_status		= soc_common_pcmcia_get_status,
-	.get_socket		= soc_common_pcmcia_get_socket,
 	.set_socket		= soc_common_pcmcia_set_socket,
 	.set_io_map		= soc_common_pcmcia_set_io_map,
 	.set_mem_map		= soc_common_pcmcia_set_mem_map,
@@ -665,13 +645,12 @@ int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops
 
 	down(&soc_pcmcia_sockets_lock);
 
-	sinfo = kmalloc(SKT_DEV_INFO_SIZE(nr), GFP_KERNEL);
+	sinfo = kzalloc(SKT_DEV_INFO_SIZE(nr), GFP_KERNEL);
 	if (!sinfo) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
-	memset(sinfo, 0, SKT_DEV_INFO_SIZE(nr));
 	sinfo->nskt = nr;
 
 	/*
diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c
index 4a3150a7854c..7a7744662d54 100644
--- a/drivers/pcmcia/socket_sysfs.c
+++ b/drivers/pcmcia/socket_sysfs.c
@@ -42,35 +42,28 @@
 
 static ssize_t pccard_show_type(struct class_device *dev, char *buf)
 {
-	int val;
 	struct pcmcia_socket *s = to_socket(dev);
 
 	if (!(s->state & SOCKET_PRESENT))
 		return -ENODEV;
-	s->ops->get_status(s, &val);
-	if (val & SS_CARDBUS)
+	if (s->state & SOCKET_CARDBUS)
 		return sprintf(buf, "32-bit\n");
-	if (val & SS_DETECT)
-		return sprintf(buf, "16-bit\n");
-	return sprintf(buf, "invalid\n");
+	return sprintf(buf, "16-bit\n");
 }
-static CLASS_DEVICE_ATTR(card_type, 0400, pccard_show_type, NULL);
+static CLASS_DEVICE_ATTR(card_type, 0444, pccard_show_type, NULL);
 
 static ssize_t pccard_show_voltage(struct class_device *dev, char *buf)
 {
-	int val;
 	struct pcmcia_socket *s = to_socket(dev);
 
 	if (!(s->state & SOCKET_PRESENT))
 		return -ENODEV;
-	s->ops->get_status(s, &val);
-	if (val & SS_3VCARD)
-		return sprintf(buf, "3.3V\n");
-	if (val & SS_XVCARD)
-		return sprintf(buf, "X.XV\n");
-	return sprintf(buf, "5.0V\n");
+	if (s->socket.Vcc)
+		return sprintf(buf, "%d.%dV\n", s->socket.Vcc / 10,
+			       s->socket.Vcc % 10);
+	return sprintf(buf, "X.XV\n");
 }
-static CLASS_DEVICE_ATTR(card_voltage, 0400, pccard_show_voltage, NULL);
+static CLASS_DEVICE_ATTR(card_voltage, 0444, pccard_show_voltage, NULL);
 
 static ssize_t pccard_show_vpp(struct class_device *dev, char *buf)
 {
@@ -79,7 +72,7 @@ static ssize_t pccard_show_vpp(struct class_device *dev, char *buf)
 		return -ENODEV;
 	return sprintf(buf, "%d.%dV\n", s->socket.Vpp / 10, s->socket.Vpp % 10);
 }
-static CLASS_DEVICE_ATTR(card_vpp, 0400, pccard_show_vpp, NULL);
+static CLASS_DEVICE_ATTR(card_vpp, 0444, pccard_show_vpp, NULL);
 
 static ssize_t pccard_show_vcc(struct class_device *dev, char *buf)
 {
@@ -88,7 +81,7 @@ static ssize_t pccard_show_vcc(struct class_device *dev, char *buf)
 		return -ENODEV;
 	return sprintf(buf, "%d.%dV\n", s->socket.Vcc / 10, s->socket.Vcc % 10);
 }
-static CLASS_DEVICE_ATTR(card_vcc, 0400, pccard_show_vcc, NULL);
+static CLASS_DEVICE_ATTR(card_vcc, 0444, pccard_show_vcc, NULL);
 
 
 static ssize_t pccard_store_insert(struct class_device *dev, const char *buf, size_t count)
@@ -292,10 +285,9 @@ static ssize_t pccard_store_cis(struct kobject *kobj, char *buf, loff_t off, siz
 	if (!(s->state & SOCKET_PRESENT))
 		return -ENODEV;
 
-	cis = kmalloc(sizeof(cisdump_t), GFP_KERNEL);
+	cis = kzalloc(sizeof(cisdump_t), GFP_KERNEL);
 	if (!cis)
 		return -ENOMEM;
-	memset(cis, 0, sizeof(cisdump_t));
 
 	cis->Length = count + 1;
 	memcpy(cis->Data, buf, count);
diff --git a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c
index e31263864377..73bad1d5cb23 100644
--- a/drivers/pcmcia/tcic.c
+++ b/drivers/pcmcia/tcic.c
@@ -181,13 +181,6 @@ static void tcic_setl(u_char reg, u_int data)
     outw(data >> 16, tcic_base+reg+2);
 }
 
-static u_char tcic_aux_getb(u_short reg)
-{
-    u_char mode = (tcic_getb(TCIC_MODE) & TCIC_MODE_PGMMASK) | reg;
-    tcic_setb(TCIC_MODE, mode);
-    return tcic_getb(TCIC_AUX);
-}
-
 static void tcic_aux_setb(u_short reg, u_char data)
 {
     u_char mode = (tcic_getb(TCIC_MODE) & TCIC_MODE_PGMMASK) | reg;
@@ -641,59 +634,6 @@ static int tcic_get_status(struct pcmcia_socket *sock, u_int *value)
     debug(1, "GetStatus(%d) = %#2.2x\n", psock, *value);
     return 0;
 } /* tcic_get_status */
-  
-/*====================================================================*/
-
-static int tcic_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
-{
-    u_short psock = container_of(sock, struct tcic_socket, socket)->psock;
-    u_char reg;
-    u_short scf1, scf2;
-    
-    tcic_setl(TCIC_ADDR, (psock << TCIC_ADDR_SS_SHFT)
-	      | TCIC_ADDR_INDREG | TCIC_SCF1(psock));
-    scf1 = tcic_getw(TCIC_DATA);
-    state->flags = (scf1 & TCIC_SCF1_IOSTS) ? SS_IOCARD : 0;
-    state->flags |= (scf1 & TCIC_SCF1_DMA_MASK) ? SS_DMA_MODE : 0;
-    state->flags |= (scf1 & TCIC_SCF1_SPKR) ? SS_SPKR_ENA : 0;
-    if (tcic_getb(TCIC_SCTRL) & TCIC_SCTRL_ENA)
-	state->flags |= SS_OUTPUT_ENA;
-    state->io_irq = scf1 & TCIC_SCF1_IRQ_MASK;
-    if (state->io_irq == 1) state->io_irq = 11;
-
-    reg = tcic_getb(TCIC_PWR);
-    state->Vcc = state->Vpp = 0;
-    if (reg & TCIC_PWR_VCC(psock)) {
-	if (reg & TCIC_PWR_VPP(psock))
-	    state->Vcc = 50;
-	else
-	    state->Vcc = state->Vpp = 50;
-    } else {
-	if (reg & TCIC_PWR_VPP(psock)) {
-	    state->Vcc = 50;
-	    state->Vpp = 120;
-	}
-    }
-    reg = tcic_aux_getb(TCIC_AUX_ILOCK);
-    state->flags |= (reg & TCIC_ILOCK_CRESET) ? SS_RESET : 0;
-
-    /* Card status change interrupt mask */
-    tcic_setw(TCIC_ADDR, TCIC_SCF2(psock));
-    scf2 = tcic_getw(TCIC_DATA);
-    state->csc_mask = (scf2 & TCIC_SCF2_MCD) ? 0 : SS_DETECT;
-    if (state->flags & SS_IOCARD) {
-	state->csc_mask |= (scf2 & TCIC_SCF2_MLBAT1) ? 0 : SS_STSCHG;
-    } else {
-	state->csc_mask |= (scf2 & TCIC_SCF2_MLBAT1) ? 0 : SS_BATDEAD;
-	state->csc_mask |= (scf2 & TCIC_SCF2_MLBAT2) ? 0 : SS_BATWARN;
-	state->csc_mask |= (scf2 & TCIC_SCF2_MRDY) ? 0 : SS_READY;
-    }
-
-    debug(1, "GetSocket(%d) = flags %#3.3x, Vcc %d, Vpp %d, "
-	  "io_irq %d, csc_mask %#2.2x\n", psock, state->flags,
-	  state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
-    return 0;
-} /* tcic_get_socket */
 
 /*====================================================================*/
 
@@ -874,7 +814,6 @@ static int tcic_init(struct pcmcia_socket *s)
 static struct pccard_operations tcic_operations = {
 	.init		   = tcic_init,
 	.get_status	   = tcic_get_status,
-	.get_socket	   = tcic_get_socket,
 	.set_socket	   = tcic_set_socket,
 	.set_io_map	   = tcic_set_io_map,
 	.set_mem_map	   = tcic_set_mem_map,
diff --git a/drivers/pcmcia/ti113x.h b/drivers/pcmcia/ti113x.h
index 539b5cd1a598..d5b4ff74462e 100644
--- a/drivers/pcmcia/ti113x.h
+++ b/drivers/pcmcia/ti113x.h
@@ -873,7 +873,7 @@ static int ti1250_override(struct yenta_socket *socket)
  * Some fixup code to make everybody happy (TM).
  */
 
-#ifdef CONFIG_CARDBUS
+#ifdef CONFIG_YENTA_ENE_TUNE
 /**
  * set/clear various test bits:
  * Defaults to clear the bit.
@@ -937,7 +937,7 @@ static int ene_override(struct yenta_socket *socket)
 }
 #else
 #  define ene_override ti1250_override
-#endif
+#endif /* !CONFIG_YENTA_ENE_TUNE */
 
 #endif /* _LINUX_TI113X_H */
 
diff --git a/drivers/pcmcia/vrc4171_card.c b/drivers/pcmcia/vrc4171_card.c
index 38a028c725d4..24c547ef512b 100644
--- a/drivers/pcmcia/vrc4171_card.c
+++ b/drivers/pcmcia/vrc4171_card.c
@@ -301,75 +301,6 @@ static int pccard_get_status(struct pcmcia_socket *sock, u_int *value)
 	return 0;
 }
 
-static inline u_char get_Vcc_value(uint8_t voltage)
-{
-	switch (voltage) {
-	case VCC_STATUS_3V:
-		return 33;
-	case VCC_STATUS_5V:
-		return 50;
-	default:
-		break;
-	}
-
-	return 0;
-}
-
-static inline u_char get_Vpp_value(uint8_t power, u_char Vcc)
-{
-	if ((power & 0x03) == 0x01 || (power & 0x03) == 0x02)
-		return Vcc;
-
-	return 0;
-}
-
-static int pccard_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
-{
-	unsigned int slot;
-	uint8_t power, voltage, control, cscint;
-
-	if (sock == NULL || sock->sock >= CARD_MAX_SLOTS || state == NULL)
-		return -EINVAL;
-
-	slot = sock->sock;
-
-	power = exca_read_byte(slot, I365_POWER);
-	voltage = exca_read_byte(slot, CARD_VOLTAGE_SELECT);
-
-	state->Vcc = get_Vcc_value(voltage);
-	state->Vpp = get_Vpp_value(power, state->Vcc);
-
-	state->flags = 0;
-	if (power & POWER_ENABLE)
-		state->flags |= SS_PWR_AUTO;
-	if (power & I365_PWR_OUT)
-		state->flags |= SS_OUTPUT_ENA;
-
-	control = exca_read_byte(slot, I365_INTCTL);
-	if (control & I365_PC_IOCARD)
-		state->flags |= SS_IOCARD;
-	if (!(control & I365_PC_RESET))
-		state->flags |= SS_RESET;
-
-        cscint = exca_read_byte(slot, I365_CSCINT);
-	state->csc_mask = 0;
-	if (state->flags & SS_IOCARD) {
-		if (cscint & I365_CSC_STSCHG)
-			state->flags |= SS_STSCHG;
-	} else {
-		if (cscint & I365_CSC_BVD1)
-			state->csc_mask |= SS_BATDEAD;
-		if (cscint & I365_CSC_BVD2)
-			state->csc_mask |= SS_BATWARN;
-	}
-	if (cscint & I365_CSC_READY)
-		state->csc_mask |= SS_READY;
-	if (cscint & I365_CSC_DETECT)
-		state->csc_mask |= SS_DETECT;
-
-	return 0;
-}
-
 static inline uint8_t set_Vcc_value(u_char Vcc)
 {
 	switch (Vcc) {
@@ -551,7 +482,6 @@ static int pccard_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map
 static struct pccard_operations vrc4171_pccard_operations = {
 	.init			= pccard_init,
 	.get_status		= pccard_get_status,
-	.get_socket		= pccard_get_socket,
 	.set_socket		= pccard_set_socket,
 	.set_io_map		= pccard_set_io_map,
 	.set_mem_map		= pccard_set_mem_map,
diff --git a/drivers/pcmcia/vrc4173_cardu.c b/drivers/pcmcia/vrc4173_cardu.c
index db91259dc50e..1b277d2c1c96 100644
--- a/drivers/pcmcia/vrc4173_cardu.c
+++ b/drivers/pcmcia/vrc4173_cardu.c
@@ -198,48 +198,6 @@ static int cardu_get_status(unsigned int sock, u_int *value)
 	return 0;
 }
 
-static inline u_char get_Vcc_value(uint8_t val)
-{
-	switch (val & VCC_MASK) {
-	case VCC_3V:
-		return 33;
-	case VCC_5V:
-		return 50;
-	}
-
-	return 0;
-}
-
-static inline u_char get_Vpp_value(uint8_t val)
-{
-	switch (val & VPP_MASK) {
-	case VPP_12V:
-		return 120;
-	case VPP_VCC:
-		return get_Vcc_value(val);
-	}
-
-	return 0;
-}
-
-static int cardu_get_socket(unsigned int sock, socket_state_t *state)
-{
-	vrc4173_socket_t *socket = &cardu_sockets[sock];
-	uint8_t val;
-
-	val = exca_readb(socket, PWR_CNT);
-	state->Vcc = get_Vcc_value(val);
-	state->Vpp = get_Vpp_value(val);
-	state->flags = 0;
-	if (val & CARD_OUT_EN) state->flags |= SS_OUTPUT_ENA;
-
-	val = exca_readb(socket, INT_GEN_CNT);
-	if (!(val & CARD_REST0)) state->flags |= SS_RESET;
-	if (val & CARD_TYPE_IO) state->flags |= SS_IOCARD;
-
-	return 0;
-}
-
 static inline uint8_t set_Vcc_value(u_char Vcc)
 {
 	switch (Vcc) {
@@ -431,7 +389,6 @@ static struct pccard_operations cardu_operations = {
 	.register_callback	= cardu_register_callback,
 	.inquire_socket		= cardu_inquire_socket,
 	.get_status		= cardu_get_status,
-	.get_socket		= cardu_get_socket,
 	.set_socket		= cardu_set_socket,
 	.get_io_map		= cardu_get_io_map,
 	.set_io_map		= cardu_set_io_map,
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index ec6ab65f0872..4145eb83b9b6 100644
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -49,7 +49,13 @@ MODULE_PARM_DESC(pwr_irqs_off, "Force IRQs off during power-on of slot. Use only
 #define to_cycles(ns)	((ns)/120)
 #define to_ns(cycles)	((cycles)*120)
 
+/**
+ * yenta PCI irq probing.
+ * currently only used in the TI/EnE initialization code
+ */
+#ifdef CONFIG_YENTA_TI
 static int yenta_probe_cb_irq(struct yenta_socket *socket);
+#endif
 
 
 static unsigned int override_bios;
@@ -224,95 +230,6 @@ static int yenta_get_status(struct pcmcia_socket *sock, unsigned int *value)
 	return 0;
 }
 
-static void yenta_get_power(struct yenta_socket *socket, socket_state_t *state)
-{
-	if (!(cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) &&
-	    (socket->flags & YENTA_16BIT_POWER_EXCA)) {
-		u8 reg, vcc, vpp;
-
-		reg = exca_readb(socket, I365_POWER);
-		vcc = reg & I365_VCC_MASK;
-		vpp = reg & I365_VPP1_MASK;
-		state->Vcc = state->Vpp = 0;
-
-		if (socket->flags & YENTA_16BIT_POWER_DF) {
-			if (vcc == I365_VCC_3V)
-				state->Vcc = 33;
-			if (vcc == I365_VCC_5V)
-				state->Vcc = 50;
-			if (vpp == I365_VPP1_5V)
-				state->Vpp = state->Vcc;
-			if (vpp == I365_VPP1_12V)
-				state->Vpp = 120;
-		} else {
-			if (reg & I365_VCC_5V) {
-				state->Vcc = 50;
-				if (vpp == I365_VPP1_5V)
-					state->Vpp = 50;
-				if (vpp == I365_VPP1_12V)
-					state->Vpp = 120;
-			}
-		}
-	} else {
-		u32 control;
-
-		control = cb_readl(socket, CB_SOCKET_CONTROL);
-
-		switch (control & CB_SC_VCC_MASK) {
-		case CB_SC_VCC_5V: state->Vcc = 50; break;
-		case CB_SC_VCC_3V: state->Vcc = 33; break;
-		default: state->Vcc = 0;
-		}
-
-		switch (control & CB_SC_VPP_MASK) {
-		case CB_SC_VPP_12V: state->Vpp = 120; break;
-		case CB_SC_VPP_5V: state->Vpp = 50; break;
-		case CB_SC_VPP_3V: state->Vpp = 33; break;
-		default: state->Vpp = 0;
-		}
-	}
-}
-
-static int yenta_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
-{
-	struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
-	u8 reg;
-	u32 control;
-
-	control = cb_readl(socket, CB_SOCKET_CONTROL);
-
-	yenta_get_power(socket, state);
-	state->io_irq = socket->io_irq;
-
-	if (cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) {
-		u16 bridge = config_readw(socket, CB_BRIDGE_CONTROL);
-		if (bridge & CB_BRIDGE_CRST)
-			state->flags |= SS_RESET;
-		return 0;
-	}
-
-	/* 16-bit card state.. */
-	reg = exca_readb(socket, I365_POWER);
-	state->flags = (reg & I365_PWR_AUTO) ? SS_PWR_AUTO : 0;
-	state->flags |= (reg & I365_PWR_OUT) ? SS_OUTPUT_ENA : 0;
-
-	reg = exca_readb(socket, I365_INTCTL);
-	state->flags |= (reg & I365_PC_RESET) ? 0 : SS_RESET;
-	state->flags |= (reg & I365_PC_IOCARD) ? SS_IOCARD : 0;
-
-	reg = exca_readb(socket, I365_CSCINT);
-	state->csc_mask = (reg & I365_CSC_DETECT) ? SS_DETECT : 0;
-	if (state->flags & SS_IOCARD) {
-		state->csc_mask |= (reg & I365_CSC_STSCHG) ? SS_STSCHG : 0;
-	} else {
-		state->csc_mask |= (reg & I365_CSC_BVD1) ? SS_BATDEAD : 0;
-		state->csc_mask |= (reg & I365_CSC_BVD2) ? SS_BATWARN : 0;
-		state->csc_mask |= (reg & I365_CSC_READY) ? SS_READY : 0;
-	}
-
-	return 0;
-}
-
 static void yenta_set_power(struct yenta_socket *socket, socket_state_t *state)
 {
 	/* some birdges require to use the ExCA registers to power 16bit cards */
@@ -531,6 +448,9 @@ static irqreturn_t yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 
 	csc = exca_readb(socket, I365_CSC);
 
+	if (!(cb_event || csc))
+		return IRQ_NONE;
+
 	events = (cb_event & (CB_CD1EVENT | CB_CD2EVENT)) ? SS_DETECT : 0 ;
 	events |= (csc & I365_CSC_DETECT) ? SS_DETECT : 0;
 	if (exca_readb(socket, I365_INTCTL) & I365_PC_IOCARD) {
@@ -544,10 +464,7 @@ static irqreturn_t yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 	if (events)
 		pcmcia_parse_events(&socket->socket, events);
 
-	if (cb_event || csc)
-		return IRQ_HANDLED;
-
-	return IRQ_NONE;
+	return IRQ_HANDLED;
 }
 
 static void yenta_interrupt_wrapper(unsigned long data)
@@ -828,17 +745,24 @@ static struct pccard_operations yenta_socket_operations = {
 	.init			= yenta_sock_init,
 	.suspend		= yenta_sock_suspend,
 	.get_status		= yenta_get_status,
-	.get_socket		= yenta_get_socket,
 	.set_socket		= yenta_set_socket,
 	.set_io_map		= yenta_set_io_map,
 	.set_mem_map		= yenta_set_mem_map,
 };
 
 
+#ifdef CONFIG_YENTA_TI
 #include "ti113x.h"
+#endif
+#ifdef CONFIG_YENTA_RICOH
 #include "ricoh.h"
+#endif
+#ifdef CONFIG_YENTA_TOSHIBA
 #include "topic.h"
+#endif
+#ifdef CONFIG_YENTA_O2
 #include "o2micro.h"
+#endif
 
 enum {
 	CARDBUS_TYPE_DEFAULT = -1,
@@ -858,6 +782,7 @@ enum {
  * initialization sequences etc details. List them here..
  */
 static struct cardbus_type cardbus_type[] = {
+#ifdef CONFIG_YENTA_TI
 	[CARDBUS_TYPE_TI]	= {
 		.override	= ti_override,
 		.save_state	= ti_save_state,
@@ -882,27 +807,36 @@ static struct cardbus_type cardbus_type[] = {
 		.restore_state	= ti_restore_state,
 		.sock_init	= ti_init,
 	},
+#endif
+#ifdef CONFIG_YENTA_RICOH
 	[CARDBUS_TYPE_RICOH]	= {
 		.override	= ricoh_override,
 		.save_state	= ricoh_save_state,
 		.restore_state	= ricoh_restore_state,
 	},
+#endif
+#ifdef CONFIG_YENTA_TOSHIBA
 	[CARDBUS_TYPE_TOPIC95]	= {
 		.override	= topic95_override,
 	},
 	[CARDBUS_TYPE_TOPIC97]	= {
 		.override	= topic97_override,
 	},
+#endif
+#ifdef CONFIG_YENTA_O2
 	[CARDBUS_TYPE_O2MICRO]	= {
 		.override	= o2micro_override,
 		.restore_state	= o2micro_restore_state,
 	},
+#endif
+#ifdef CONFIG_YENTA_TI
 	[CARDBUS_TYPE_ENE]	= {
 		.override	= ene_override,
 		.save_state	= ti_save_state,
 		.restore_state	= ti_restore_state,
 		.sock_init	= ti_init,
 	},
+#endif
 };
 
 
@@ -948,6 +882,12 @@ static unsigned int yenta_probe_irq(struct yenta_socket *socket, u32 isa_irq_mas
 }
 
 
+/**
+ * yenta PCI irq probing.
+ * currently only used in the TI/EnE initialization code
+ */
+#ifdef CONFIG_YENTA_TI
+
 /* interrupt handler, only used during probing */
 static irqreturn_t yenta_probe_handler(int irq, void *dev_id, struct pt_regs *regs)
 {
@@ -1000,6 +940,7 @@ static int yenta_probe_cb_irq(struct yenta_socket *socket)
 	return (int) socket->probe_status;
 }
 
+#endif /* CONFIG_YENTA_TI */
 
 
 /*
@@ -1078,10 +1019,9 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i
 		return -ENODEV;
 	}
 
-	socket = kmalloc(sizeof(struct yenta_socket), GFP_KERNEL);
+	socket = kzalloc(sizeof(struct yenta_socket), GFP_KERNEL);
 	if (!socket)
 		return -ENOMEM;
-	memset(socket, 0, sizeof(*socket));
 
 	/* prepare pcmcia_socket */
 	socket->socket.ops = &yenta_socket_operations;
@@ -1263,6 +1203,7 @@ static struct pci_device_id yenta_table [] = {
 	 * advanced overrides instead.  (I can't get the
 	 * data sheets for these devices. --rmk)
 	 */
+#ifdef CONFIG_YENTA_TI
 	CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1210, TI),
 
 	CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1130, TI113X),
@@ -1305,18 +1246,25 @@ static struct pci_device_id yenta_table [] = {
 	CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1225, ENE),
 	CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1410, ENE),
 	CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1420, ENE),
+#endif /* CONFIG_YENTA_TI */
 
+#ifdef CONFIG_YENTA_RICOH
 	CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C465, RICOH),
 	CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C466, RICOH),
 	CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C475, RICOH),
 	CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C476, RICOH),
 	CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C478, RICOH),
+#endif
 
+#ifdef CONFIG_YENTA_TOSHIBA
 	CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC95, TOPIC95),
 	CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC97, TOPIC97),
 	CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC100, TOPIC97),
+#endif
 
+#ifdef CONFIG_YENTA_O2
 	CB_ID(PCI_VENDOR_ID_O2, PCI_ANY_ID, O2MICRO),
+#endif
 
 	/* match any cardbus bridge */
 	CB_ID(PCI_ANY_ID, PCI_ANY_ID, DEFAULT),
diff --git a/drivers/pnp/card.c b/drivers/pnp/card.c
index bd7c966ea2d7..0ecbe4edbec1 100644
--- a/drivers/pnp/card.c
+++ b/drivers/pnp/card.c
@@ -69,6 +69,7 @@ static int card_probe(struct pnp_card * card, struct pnp_card_driver * drv)
 			return 0;
 		clink->card = card;
 		clink->driver = drv;
+		clink->pm_state = PMSG_ON;
 		if (drv->probe) {
 			if (drv->probe(clink, id)>=0)
 				return 1;
@@ -333,6 +334,28 @@ void pnp_release_card_device(struct pnp_dev * dev)
 	up_write(&dev->dev.bus->subsys.rwsem);
 }
 
+/*
+ * suspend/resume callbacks
+ */
+static int card_suspend(struct pnp_dev *dev, pm_message_t state)
+{
+	struct pnp_card_link *link = dev->card_link;
+	if (link->pm_state.event == state.event)
+		return 0;
+	link->pm_state = state;
+	return link->driver->suspend(link, state);
+}
+
+static int card_resume(struct pnp_dev *dev)
+{
+	struct pnp_card_link *link = dev->card_link;
+	if (link->pm_state.event == PM_EVENT_ON)
+		return 0;
+	link->pm_state = PMSG_ON;
+	link->driver->resume(link);
+	return 0;
+}
+
 /**
  * pnp_register_card_driver - registers a PnP card driver with the PnP Layer
  * @drv: pointer to the driver to register
@@ -348,6 +371,8 @@ int pnp_register_card_driver(struct pnp_card_driver * drv)
 	drv->link.flags = drv->flags;
 	drv->link.probe = NULL;
 	drv->link.remove = &card_remove_first;
+	drv->link.suspend = drv->suspend ? card_suspend : NULL;
+	drv->link.resume = drv->resume ? card_resume : NULL;
 
 	spin_lock(&pnp_lock);
 	list_add_tail(&drv->global_list, &pnp_card_drivers);
diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c
index d3ccce706ab4..15fb758a9e52 100644
--- a/drivers/pnp/driver.c
+++ b/drivers/pnp/driver.c
@@ -146,10 +146,57 @@ static int pnp_bus_match(struct device *dev, struct device_driver *drv)
 	return 1;
 }
 
+static int pnp_bus_suspend(struct device *dev, pm_message_t state)
+{
+	struct pnp_dev * pnp_dev = to_pnp_dev(dev);
+	struct pnp_driver * pnp_drv = pnp_dev->driver;
+	int error;
+
+	if (!pnp_drv)
+		return 0;
+
+	if (pnp_drv->suspend) {
+		error = pnp_drv->suspend(pnp_dev, state);
+		if (error)
+			return error;
+	}
+
+	if (!(pnp_drv->flags & PNP_DRIVER_RES_DO_NOT_CHANGE) &&
+	    pnp_can_disable(pnp_dev)) {
+	    	error = pnp_stop_dev(pnp_dev);
+	    	if (error)
+	    		return error;
+	}
+
+	return 0;
+}
+
+static int pnp_bus_resume(struct device *dev)
+{
+	struct pnp_dev * pnp_dev = to_pnp_dev(dev);
+	struct pnp_driver * pnp_drv = pnp_dev->driver;
+	int error;
+
+	if (!pnp_drv)
+		return 0;
+
+	if (!(pnp_drv->flags & PNP_DRIVER_RES_DO_NOT_CHANGE)) {
+		error = pnp_start_dev(pnp_dev);
+		if (error)
+			return error;
+	}
+
+	if (pnp_drv->resume)
+		return pnp_drv->resume(pnp_dev);
+
+	return 0;
+}
 
 struct bus_type pnp_bus_type = {
 	.name	= "pnp",
 	.match	= pnp_bus_match,
+	.suspend = pnp_bus_suspend,
+	.resume = pnp_bus_resume,
 };
 
 
diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c
index 261668618b2d..c4256aa32bcb 100644
--- a/drivers/pnp/manager.c
+++ b/drivers/pnp/manager.c
@@ -470,6 +470,53 @@ int pnp_auto_config_dev(struct pnp_dev *dev)
 }
 
 /**
+ * pnp_start_dev - low-level start of the PnP device
+ * @dev: pointer to the desired device
+ *
+ * assumes that resources have alread been allocated
+ */
+
+int pnp_start_dev(struct pnp_dev *dev)
+{
+	if (!pnp_can_write(dev)) {
+		pnp_info("Device %s does not supported activation.", dev->dev.bus_id);
+		return -EINVAL;
+	}
+
+	if (dev->protocol->set(dev, &dev->res)<0) {
+		pnp_err("Failed to activate device %s.", dev->dev.bus_id);
+		return -EIO;
+	}
+
+	pnp_info("Device %s activated.", dev->dev.bus_id);
+
+	return 0;
+}
+
+/**
+ * pnp_stop_dev - low-level disable of the PnP device
+ * @dev: pointer to the desired device
+ *
+ * does not free resources
+ */
+
+int pnp_stop_dev(struct pnp_dev *dev)
+{
+	if (!pnp_can_disable(dev)) {
+		pnp_info("Device %s does not supported disabling.", dev->dev.bus_id);
+		return -EINVAL;
+	}
+	if (dev->protocol->disable(dev)<0) {
+		pnp_err("Failed to disable device %s.", dev->dev.bus_id);
+		return -EIO;
+	}
+
+	pnp_info("Device %s disabled.", dev->dev.bus_id);
+
+	return 0;
+}
+
+/**
  * pnp_activate_dev - activates a PnP device for use
  * @dev: pointer to the desired device
  *
@@ -477,6 +524,8 @@ int pnp_auto_config_dev(struct pnp_dev *dev)
  */
 int pnp_activate_dev(struct pnp_dev *dev)
 {
+	int error;
+
 	if (!dev)
 		return -EINVAL;
 	if (dev->active) {
@@ -487,18 +536,11 @@ int pnp_activate_dev(struct pnp_dev *dev)
 	if (pnp_auto_config_dev(dev))
 		return -EBUSY;
 
-	if (!pnp_can_write(dev)) {
-		pnp_info("Device %s does not supported activation.", dev->dev.bus_id);
-		return -EINVAL;
-	}
-
-	if (dev->protocol->set(dev, &dev->res)<0) {
-		pnp_err("Failed to activate device %s.", dev->dev.bus_id);
-		return -EIO;
-	}
+	error = pnp_start_dev(dev);
+	if (error)
+		return error;
 
 	dev->active = 1;
-	pnp_info("Device %s activated.", dev->dev.bus_id);
 
 	return 1;
 }
@@ -511,23 +553,19 @@ int pnp_activate_dev(struct pnp_dev *dev)
  */
 int pnp_disable_dev(struct pnp_dev *dev)
 {
+	int error;
+
         if (!dev)
                 return -EINVAL;
 	if (!dev->active) {
 		return 0; /* the device is already disabled */
 	}
 
-	if (!pnp_can_disable(dev)) {
-		pnp_info("Device %s does not supported disabling.", dev->dev.bus_id);
-		return -EINVAL;
-	}
-	if (dev->protocol->disable(dev)<0) {
-		pnp_err("Failed to disable device %s.", dev->dev.bus_id);
-		return -EIO;
-	}
+	error = pnp_stop_dev(dev);
+	if (error)
+		return error;
 
 	dev->active = 0;
-	pnp_info("Device %s disabled.", dev->dev.bus_id);
 
 	/* release the resources so that other devices can use them */
 	down(&pnp_res_mutex);
@@ -558,6 +596,8 @@ EXPORT_SYMBOL(pnp_manual_config_dev);
 #if 0
 EXPORT_SYMBOL(pnp_auto_config_dev);
 #endif
+EXPORT_SYMBOL(pnp_start_dev);
+EXPORT_SYMBOL(pnp_stop_dev);
 EXPORT_SYMBOL(pnp_activate_dev);
 EXPORT_SYMBOL(pnp_disable_dev);
 EXPORT_SYMBOL(pnp_resource_change);
diff --git a/drivers/pnp/pnpbios/bioscalls.c b/drivers/pnp/pnpbios/bioscalls.c
index 6b7583f497d0..a1f0b0ba2bfe 100644
--- a/drivers/pnp/pnpbios/bioscalls.c
+++ b/drivers/pnp/pnpbios/bioscalls.c
@@ -31,15 +31,6 @@ static struct {
 } pnp_bios_callpoint;
 
 
-/* The PnP BIOS entries in the GDT */
-#define PNP_GDT    (GDT_ENTRY_PNPBIOS_BASE * 8)
-
-#define PNP_CS32   (PNP_GDT+0x00)	/* segment for calling fn */
-#define PNP_CS16   (PNP_GDT+0x08)	/* code segment for BIOS */
-#define PNP_DS     (PNP_GDT+0x10)	/* data segment for BIOS */
-#define PNP_TS1    (PNP_GDT+0x18)	/* transfer data segment */
-#define PNP_TS2    (PNP_GDT+0x20)	/* another data segment */
-
 /*
  * These are some opcodes for a "static asmlinkage"
  * As this code is *not* executed inside the linux kernel segment, but in a
@@ -67,16 +58,11 @@ __asm__(
 	".previous		\n"
 );
 
-#define Q_SET_SEL(cpu, selname, address, size) \
-do { \
-set_base(per_cpu(cpu_gdt_table,cpu)[(selname) >> 3], __va((u32)(address))); \
-set_limit(per_cpu(cpu_gdt_table,cpu)[(selname) >> 3], size); \
-} while(0)
-
 #define Q2_SET_SEL(cpu, selname, address, size) \
 do { \
-set_base(per_cpu(cpu_gdt_table,cpu)[(selname) >> 3], (u32)(address)); \
-set_limit(per_cpu(cpu_gdt_table,cpu)[(selname) >> 3], size); \
+struct desc_struct *gdt = get_cpu_gdt_table((cpu)); \
+set_base(gdt[(selname) >> 3], (u32)(address)); \
+set_limit(gdt[(selname) >> 3], size); \
 } while(0)
 
 static struct desc_struct bad_bios_desc = { 0, 0x00409200 };
@@ -115,8 +101,8 @@ static inline u16 call_pnp_bios(u16 func, u16 arg1, u16 arg2, u16 arg3,
 		return PNP_FUNCTION_NOT_SUPPORTED;
 
 	cpu = get_cpu();
-	save_desc_40 = per_cpu(cpu_gdt_table,cpu)[0x40 / 8];
-	per_cpu(cpu_gdt_table,cpu)[0x40 / 8] = bad_bios_desc;
+	save_desc_40 = get_cpu_gdt_table(cpu)[0x40 / 8];
+	get_cpu_gdt_table(cpu)[0x40 / 8] = bad_bios_desc;
 
 	/* On some boxes IRQ's during PnP BIOS calls are deadly.  */
 	spin_lock_irqsave(&pnp_bios_lock, flags);
@@ -158,7 +144,7 @@ static inline u16 call_pnp_bios(u16 func, u16 arg1, u16 arg2, u16 arg3,
 	);
 	spin_unlock_irqrestore(&pnp_bios_lock, flags);
 
-	per_cpu(cpu_gdt_table,cpu)[0x40 / 8] = save_desc_40;
+	get_cpu_gdt_table(cpu)[0x40 / 8] = save_desc_40;
 	put_cpu();
 
 	/* If we get here and this is set then the PnP BIOS faulted on us. */
@@ -290,12 +276,15 @@ int pnp_bios_dev_node_info(struct pnp_dev_node_info *data)
 static int __pnp_bios_get_dev_node(u8 *nodenum, char boot, struct pnp_bios_node *data)
 {
 	u16 status;
+	u16 tmp_nodenum;
 	if (!pnp_bios_present())
 		return PNP_FUNCTION_NOT_SUPPORTED;
 	if ( !boot && pnpbios_dont_use_current_config )
 		return PNP_FUNCTION_NOT_SUPPORTED;
+	tmp_nodenum = *nodenum;
 	status = call_pnp_bios(PNP_GET_SYS_DEV_NODE, 0, PNP_TS1, 0, PNP_TS2, boot ? 2 : 1, PNP_DS, 0,
-			       nodenum, sizeof(char), data, 65536);
+			       &tmp_nodenum, sizeof(tmp_nodenum), data, 65536);
+	*nodenum = tmp_nodenum;
 	return status;
 }
 
@@ -535,10 +524,12 @@ void pnpbios_calls_init(union pnp_bios_install_struct *header)
 
 	set_base(bad_bios_desc, __va((unsigned long)0x40 << 4));
 	_set_limit((char *)&bad_bios_desc, 4095 - (0x40 << 4));
-	for(i=0; i < NR_CPUS; i++)
-	{
-		Q2_SET_SEL(i, PNP_CS32, &pnp_bios_callfunc, 64 * 1024);
-		Q_SET_SEL(i, PNP_CS16, header->fields.pm16cseg, 64 * 1024);
-		Q_SET_SEL(i, PNP_DS, header->fields.pm16dseg, 64 * 1024);
-	}
+ 	for (i = 0; i < NR_CPUS; i++) {
+  		struct desc_struct *gdt = get_cpu_gdt_table(i);
+  		if (!gdt)
+  			continue;
+ 		set_base(gdt[GDT_ENTRY_PNPBIOS_CS32], &pnp_bios_callfunc);
+ 		set_base(gdt[GDT_ENTRY_PNPBIOS_CS16], __va(header->fields.pm16cseg));
+ 		set_base(gdt[GDT_ENTRY_PNPBIOS_DS], __va(header->fields.pm16dseg));
+  	}
 }
diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c
index f49674f07949..b154b3f52cbe 100644
--- a/drivers/pnp/pnpbios/core.c
+++ b/drivers/pnp/pnpbios/core.c
@@ -56,7 +56,6 @@
 #include <linux/mm.h>
 #include <linux/smp.h>
 #include <linux/slab.h>
-#include <linux/kobject_uevent.h>
 #include <linux/completion.h>
 #include <linux/spinlock.h>
 #include <linux/dmi.h>
@@ -106,8 +105,6 @@ static int pnp_dock_event(int dock, struct pnp_docking_station_info *info)
 	char *argv [3], **envp, *buf, *scratch;
 	int i = 0, value;
 
-	if (!hotplug_path [0])
-		return -ENOENT;
 	if (!current->fs->root) {
 		return -EAGAIN;
 	}
@@ -119,8 +116,9 @@ static int pnp_dock_event(int dock, struct pnp_docking_station_info *info)
 		return -ENOMEM;
 	}
 
-	/* only one standardized param to hotplug command: type */
-	argv [0] = hotplug_path;
+	/* FIXME: if there are actual users of this, it should be integrated into
+	 * the driver core and use the usual infrastructure like sysfs and uevents */
+	argv [0] = "/sbin/pnpbios";
 	argv [1] = "dock";
 	argv [2] = NULL;
 
diff --git a/drivers/s390/Makefile b/drivers/s390/Makefile
index c99a2fe92fb0..9803c9352d78 100644
--- a/drivers/s390/Makefile
+++ b/drivers/s390/Makefile
@@ -2,7 +2,7 @@
 # Makefile for the S/390 specific device drivers
 #
 
-obj-y += s390mach.o sysinfo.o
+obj-y += s390mach.o sysinfo.o s390_rdev.o
 obj-y += cio/ block/ char/ crypto/ net/ scsi/
 
 drivers-y += drivers/s390/built-in.o
diff --git a/drivers/s390/block/Kconfig b/drivers/s390/block/Kconfig
index 6e7d7b06421d..6f50cc9323d9 100644
--- a/drivers/s390/block/Kconfig
+++ b/drivers/s390/block/Kconfig
@@ -1,11 +1,11 @@
-if ARCH_S390
+if S390
 
 comment "S/390 block device drivers"
-	depends on ARCH_S390
+	depends on S390
 
 config BLK_DEV_XPRAM
 	tristate "XPRAM disk support"
-	depends on ARCH_S390
+	depends on S390
 	help
 	  Select this option if you want to use your expanded storage on S/390
 	  or zSeries as a disk.  This is useful as a _fast_ swap device if you
@@ -49,7 +49,7 @@ config DASD_FBA
 
 config DASD_DIAG
 	tristate "Support for DIAG access to Disks"
-	depends on DASD && ( ARCH_S390X = 'n' || EXPERIMENTAL)
+	depends on DASD && ( 64BIT = 'n' || EXPERIMENTAL)
 	help
 	  Select this option if you want to use Diagnose250 command to access
 	  Disks under VM.  If you are not running under VM or unsure what it is,
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 7008d32433bf..f779f674dfa0 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -7,7 +7,7 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
  *
- * $Revision: 1.167 $
+ * $Revision: 1.172 $
  */
 
 #include <linux/config.h>
@@ -604,7 +604,7 @@ dasd_smalloc_request(char *magic, int cplength, int datasize,
 void
 dasd_kfree_request(struct dasd_ccw_req * cqr, struct dasd_device * device)
 {
-#ifdef CONFIG_ARCH_S390X
+#ifdef CONFIG_64BIT
 	struct ccw1 *ccw;
 
 	/* Clear any idals used for the request. */
@@ -1035,7 +1035,7 @@ dasd_end_request(struct request *req, int uptodate)
 	if (end_that_request_first(req, uptodate, req->hard_nr_sectors))
 		BUG();
 	add_disk_randomness(req->rq_disk);
-	end_that_request_last(req);
+	end_that_request_last(req, uptodate);
 }
 
 /*
@@ -1224,6 +1224,12 @@ __dasd_start_head(struct dasd_device * device)
 	if (list_empty(&device->ccw_queue))
 		return;
 	cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, list);
+        /* check FAILFAST */
+	if (device->stopped & ~DASD_STOPPED_PENDING &&
+	    test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags)) {
+		cqr->status = DASD_CQR_FAILED;
+		dasd_schedule_bh(device);
+	}
 	if ((cqr->status == DASD_CQR_QUEUED) &&
 	    (!device->stopped)) {
 		/* try to start the first I/O that can be started */
@@ -1323,7 +1329,7 @@ void
 dasd_schedule_bh(struct dasd_device * device)
 {
 	/* Protect against rescheduling. */
-	if (atomic_compare_and_swap (0, 1, &device->tasklet_scheduled))
+	if (atomic_cmpxchg (&device->tasklet_scheduled, 0, 1) != 0)
 		return;
 	dasd_get_device(device);
 	tasklet_hi_schedule(&device->tasklet);
@@ -1750,8 +1756,10 @@ dasd_exit(void)
  * SECTION: common functions for ccw_driver use
  */
 
-/* initial attempt at a probe function. this can be simplified once
- * the other detection code is gone */
+/*
+ * Initial attempt at a probe function. this can be simplified once
+ * the other detection code is gone.
+ */
 int
 dasd_generic_probe (struct ccw_device *cdev,
 		    struct dasd_discipline *discipline)
@@ -1770,8 +1778,10 @@ dasd_generic_probe (struct ccw_device *cdev,
 	return ret;
 }
 
-/* this will one day be called from a global not_oper handler.
- * It is also used by driver_unregister during module unload */
+/*
+ * This will one day be called from a global not_oper handler.
+ * It is also used by driver_unregister during module unload.
+ */
 void
 dasd_generic_remove (struct ccw_device *cdev)
 {
@@ -1798,9 +1808,11 @@ dasd_generic_remove (struct ccw_device *cdev)
 	dasd_delete_device(device);
 }
 
-/* activate a device. This is called from dasd_{eckd,fba}_probe() when either
+/*
+ * Activate a device. This is called from dasd_{eckd,fba}_probe() when either
  * the device is detected for the first time and is supposed to be used
- * or the user has started activation through sysfs */
+ * or the user has started activation through sysfs.
+ */
 int
 dasd_generic_set_online (struct ccw_device *cdev,
 			 struct dasd_discipline *discipline)
@@ -1917,7 +1929,6 @@ dasd_generic_notify(struct ccw_device *cdev, int event)
 				if (cqr->status == DASD_CQR_IN_IO)
 					cqr->status = DASD_CQR_FAILED;
 			device->stopped |= DASD_STOPPED_DC_EIO;
-			dasd_schedule_bh(device);
 		} else {
 			list_for_each_entry(cqr, &device->ccw_queue, list)
 				if (cqr->status == DASD_CQR_IN_IO) {
@@ -1927,6 +1938,7 @@ dasd_generic_notify(struct ccw_device *cdev, int event)
 			device->stopped |= DASD_STOPPED_DC_WAIT;
 			dasd_set_timer(device, 0);
 		}
+		dasd_schedule_bh(device);
 		ret = 1;
 		break;
 	case CIO_OPER:
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c
index ab8754e566bc..ba80fdea7ebf 100644
--- a/drivers/s390/block/dasd_diag.c
+++ b/drivers/s390/block/dasd_diag.c
@@ -6,7 +6,7 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
  *
- * $Revision: 1.51 $
+ * $Revision: 1.53 $
  */
 
 #include <linux/config.h>
@@ -25,6 +25,7 @@
 #include <asm/io.h>
 #include <asm/s390_ext.h>
 #include <asm/todclk.h>
+#include <asm/vtoc.h>
 
 #include "dasd_int.h"
 #include "dasd_diag.h"
@@ -74,7 +75,7 @@ dia250(void *iob, int cmd)
 	int rc;
 
 	__asm__ __volatile__(
-#ifdef CONFIG_ARCH_S390X
+#ifdef CONFIG_64BIT
 		"	lghi	%0,3\n"
 		"	lgr	0,%3\n"
 		"	diag	0,%2,0x250\n"
@@ -329,7 +330,7 @@ dasd_diag_check_device(struct dasd_device *device)
 	struct dasd_diag_private *private;
 	struct dasd_diag_characteristics *rdc_data;
 	struct dasd_diag_bio bio;
-	struct dasd_diag_cms_label *label;
+	struct vtoc_cms_label *label;
 	blocknum_t end_block;
 	unsigned int sb, bsize;
 	int rc;
@@ -380,7 +381,7 @@ dasd_diag_check_device(struct dasd_device *device)
 	mdsk_term_io(device);
 
 	/* figure out blocksize of device */
-	label = (struct dasd_diag_cms_label *) get_zeroed_page(GFP_KERNEL);
+	label = (struct vtoc_cms_label *) get_zeroed_page(GFP_KERNEL);
 	if (label == NULL)  {
 		DEV_MESSAGE(KERN_WARNING, device, "%s",
 			    "No memory to allocate initialization request");
@@ -548,6 +549,8 @@ dasd_diag_build_cp(struct dasd_device * device, struct request *req)
 	}
 	cqr->retries = DIAG_MAX_RETRIES;
 	cqr->buildclk = get_clock();
+	if (req->flags & REQ_FAILFAST)
+		set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
 	cqr->device = device;
 	cqr->expires = DIAG_TIMEOUT;
 	cqr->status = DASD_CQR_FILLED;
diff --git a/drivers/s390/block/dasd_diag.h b/drivers/s390/block/dasd_diag.h
index df31484d73a7..a4f80bd735f1 100644
--- a/drivers/s390/block/dasd_diag.h
+++ b/drivers/s390/block/dasd_diag.h
@@ -6,7 +6,7 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
  *
- * $Revision: 1.8 $
+ * $Revision: 1.9 $
  */
 
 #define MDSK_WRITE_REQ 0x01
@@ -44,29 +44,8 @@ struct dasd_diag_characteristics {
 	u8 rdev_features;
 } __attribute__ ((packed, aligned(4)));
 
-struct dasd_diag_cms_label {
-	u8 label_id[4];
-	u8 vol_id[6];
-	u16 version_id;
-	u32 block_size;
-	u32 origin_ptr;
-	u32 usable_count;
-	u32 formatted_count;
-	u32 block_count;
-	u32 used_count;
-	u32 fst_size;
-	u32 fst_count;
-	u8 format_date[6];
-	u8 reserved1[2];
-	u32 disk_offset;
-	u32 map_block;
-	u32 hblk_disp;
-	u32 user_disp;
-	u8 reserved2[4];
-	u8 segment_name[8];
-} __attribute__ ((packed));
-
-#ifdef CONFIG_ARCH_S390X
+
+#ifdef CONFIG_64BIT
 #define DASD_DIAG_FLAGA_DEFAULT		DASD_DIAG_FLAGA_FORMAT_64BIT
 
 typedef u64 blocknum_t;
@@ -107,7 +86,7 @@ struct dasd_diag_rw_io {
 	struct dasd_diag_bio *bio_list;
 	u8  spare4[8];
 } __attribute__ ((packed, aligned(8)));
-#else /* CONFIG_ARCH_S390X */
+#else /* CONFIG_64BIT */
 #define DASD_DIAG_FLAGA_DEFAULT		0x0
 
 typedef u32 blocknum_t;
@@ -146,4 +125,4 @@ struct dasd_diag_rw_io {
 	u32 interrupt_params;
 	u8 spare3[20];
 } __attribute__ ((packed, aligned(8)));
-#endif /* CONFIG_ARCH_S390X */
+#endif /* CONFIG_64BIT */
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 811060e10c00..96eb48258580 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -7,7 +7,7 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
  *
- * $Revision: 1.71 $
+ * $Revision: 1.74 $
  */
 
 #include <linux/config.h>
@@ -1041,7 +1041,7 @@ dasd_eckd_build_cp(struct dasd_device * device, struct request *req)
 				/* Eckd can only do full blocks. */
 				return ERR_PTR(-EINVAL);
 			count += bv->bv_len >> (device->s2b_shift + 9);
-#if defined(CONFIG_ARCH_S390X)
+#if defined(CONFIG_64BIT)
 			if (idal_is_needed (page_address(bv->bv_page),
 					    bv->bv_len))
 				cidaw += bv->bv_len >> (device->s2b_shift + 9);
@@ -1136,6 +1136,8 @@ dasd_eckd_build_cp(struct dasd_device * device, struct request *req)
 			recid++;
 		}
 	}
+	if (req->flags & REQ_FAILFAST)
+		set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
 	cqr->device = device;
 	cqr->expires = 5 * 60 * HZ;	/* 5 minutes */
 	cqr->lpm = private->path_data.ppm;
@@ -1252,6 +1254,7 @@ dasd_eckd_release(struct block_device *bdev, int no, long args)
 	cqr->cpaddr->cda = (__u32)(addr_t) cqr->data;
 	cqr->device = device;
 	clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
+	set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
 	cqr->retries = 0;
 	cqr->expires = 2 * HZ;
 	cqr->buildclk = get_clock();
@@ -1296,6 +1299,7 @@ dasd_eckd_reserve(struct block_device *bdev, int no, long args)
 	cqr->cpaddr->cda = (__u32)(addr_t) cqr->data;
 	cqr->device = device;
 	clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
+	set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
 	cqr->retries = 0;
 	cqr->expires = 2 * HZ;
 	cqr->buildclk = get_clock();
@@ -1339,6 +1343,7 @@ dasd_eckd_steal_lock(struct block_device *bdev, int no, long args)
 	cqr->cpaddr->cda = (__u32)(addr_t) cqr->data;
 	cqr->device = device;
 	clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
+	set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
 	cqr->retries = 0;
 	cqr->expires = 2 * HZ;
 	cqr->buildclk = get_clock();
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c
index 28cb4613b7f5..8ec75dc08e2c 100644
--- a/drivers/s390/block/dasd_fba.c
+++ b/drivers/s390/block/dasd_fba.c
@@ -4,7 +4,7 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
  *
- * $Revision: 1.40 $
+ * $Revision: 1.41 $
  */
 
 #include <linux/config.h>
@@ -271,7 +271,7 @@ dasd_fba_build_cp(struct dasd_device * device, struct request *req)
 				/* Fba can only do full blocks. */
 				return ERR_PTR(-EINVAL);
 			count += bv->bv_len >> (device->s2b_shift + 9);
-#if defined(CONFIG_ARCH_S390X)
+#if defined(CONFIG_64BIT)
 			if (idal_is_needed (page_address(bv->bv_page),
 					    bv->bv_len))
 				cidaw += bv->bv_len / blksize;
@@ -352,6 +352,8 @@ dasd_fba_build_cp(struct dasd_device * device, struct request *req)
 			recid++;
 		}
 	}
+	if (req->flags & REQ_FAILFAST)
+		set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
 	cqr->device = device;
 	cqr->expires = 5 * 60 * HZ;	/* 5 minutes */
 	cqr->retries = 32;
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index 9fab04f3056d..2fb05c4a528c 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -6,7 +6,7 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
  *
- * $Revision: 1.65 $
+ * $Revision: 1.68 $
  */
 
 #ifndef DASD_INT_H
@@ -208,6 +208,7 @@ struct dasd_ccw_req {
 
 /* per dasd_ccw_req flags */
 #define DASD_CQR_FLAGS_USE_ERP   0	/* use ERP for this request */
+#define DASD_CQR_FLAGS_FAILFAST  1	/* FAILFAST */
 
 /* Signature for error recovery functions. */
 typedef struct dasd_ccw_req *(*dasd_erp_fn_t) (struct dasd_ccw_req *);
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
index 789595b3fa09..044b75371990 100644
--- a/drivers/s390/block/dasd_ioctl.c
+++ b/drivers/s390/block/dasd_ioctl.c
@@ -7,7 +7,7 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
  *
- * $Revision: 1.47 $
+ * $Revision: 1.50 $
  *
  * i/o controls for the dasd driver.
  */
@@ -352,6 +352,9 @@ dasd_ioctl_read_profile(struct block_device *bdev, int no, long args)
 	if (device == NULL)
 		return -ENODEV;
 
+	if (dasd_profile_level == DASD_PROFILE_OFF)
+		return -EIO;
+
 	if (copy_to_user((long __user *) args, (long *) &device->profile,
 			 sizeof (struct dasd_profile_info_t)))
 		return -EFAULT;
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c
index 4fde41188996..2e727f49ad19 100644
--- a/drivers/s390/block/dcssblk.c
+++ b/drivers/s390/block/dcssblk.c
@@ -15,7 +15,7 @@
 #include <asm/io.h>
 #include <linux/completion.h>
 #include <linux/interrupt.h>
-#include <asm/ccwdev.h> 	// for s390_root_dev_(un)register()
+#include <asm/s390_rdev.h>
 
 //#define DCSSBLK_DEBUG		/* Debug messages on/off */
 #define DCSSBLK_NAME "dcssblk"
diff --git a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c
index d428c909b8a0..bf3a67c3cc5e 100644
--- a/drivers/s390/block/xpram.c
+++ b/drivers/s390/block/xpram.c
@@ -160,7 +160,7 @@ static int xpram_page_in (unsigned long page_addr, unsigned int xpage_index)
                 "0: ipm   %0\n"
 		"   srl   %0,28\n"
 		"1:\n"
-#ifndef CONFIG_ARCH_S390X
+#ifndef CONFIG_64BIT
 		".section __ex_table,\"a\"\n"
 		"   .align 4\n"
 		"   .long  0b,1b\n"
@@ -208,7 +208,7 @@ static long xpram_page_out (unsigned long page_addr, unsigned int xpage_index)
                 "0: ipm   %0\n"
 		"   srl   %0,28\n"
 		"1:\n"
-#ifndef CONFIG_ARCH_S390X
+#ifndef CONFIG_64BIT
 		".section __ex_table,\"a\"\n"
 		"   .align 4\n"
 		"   .long  0b,1b\n"
diff --git a/drivers/s390/char/sclp_cpi.c b/drivers/s390/char/sclp_cpi.c
index 5a6cef2dfa13..80f7f31310e6 100644
--- a/drivers/s390/char/sclp_cpi.c
+++ b/drivers/s390/char/sclp_cpi.c
@@ -204,7 +204,7 @@ cpi_module_init(void)
 		printk(KERN_WARNING "cpi: no control program identification "
 		       "support\n");
 		sclp_unregister(&sclp_cpi_event);
-		return -ENOTSUPP;
+		return -EOPNOTSUPP;
 	}
 
 	req = cpi_prepare_req();
diff --git a/drivers/s390/char/sclp_quiesce.c b/drivers/s390/char/sclp_quiesce.c
index 83f75774df60..56fa69168898 100644
--- a/drivers/s390/char/sclp_quiesce.c
+++ b/drivers/s390/char/sclp_quiesce.c
@@ -32,7 +32,7 @@ do_load_quiesce_psw(void * __unused)
 	psw_t quiesce_psw;
 	int cpu;
 
-	if (atomic_compare_and_swap(-1, smp_processor_id(), &cpuid))
+	if (atomic_cmpxchg(&cpuid, -1, smp_processor_id()) != -1)
 		signal_processor(smp_processor_id(), sigp_stop);
 	/* Wait for all other cpus to enter stopped state */
 	for_each_online_cpu(cpu) {
diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c
index 1efc9f21229e..5ced2725d6c7 100644
--- a/drivers/s390/char/tape_block.c
+++ b/drivers/s390/char/tape_block.c
@@ -65,7 +65,7 @@ static void
 tapeblock_trigger_requeue(struct tape_device *device)
 {
 	/* Protect against rescheduling. */
-	if (atomic_compare_and_swap(0, 1, &device->blk_data.requeue_scheduled))
+	if (atomic_cmpxchg(&device->blk_data.requeue_scheduled, 0, 1) != 0)
 		return;
 	schedule_work(&device->blk_data.requeue_task);
 }
@@ -78,7 +78,7 @@ tapeblock_end_request(struct request *req, int uptodate)
 {
 	if (end_that_request_first(req, uptodate, req->hard_nr_sectors))
 		BUG();
-	end_that_request_last(req);
+	end_that_request_last(req, uptodate);
 }
 
 static void
diff --git a/drivers/s390/char/vmwatchdog.c b/drivers/s390/char/vmwatchdog.c
index 5473c23fcb52..5acc0ace3d7d 100644
--- a/drivers/s390/char/vmwatchdog.c
+++ b/drivers/s390/char/vmwatchdog.c
@@ -66,7 +66,7 @@ static int __diag288(enum vmwdt_func func, unsigned int timeout,
 	__cmdl = len;
 	err = 0;
 	asm volatile (
-#ifdef __s390x__
+#ifdef CONFIG_64BIT
 		       "diag %2,%4,0x288\n"
 		"1:	\n"
 		".section .fixup,\"ax\"\n"
diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c
index a1c52a682191..daf21e03b21d 100644
--- a/drivers/s390/cio/blacklist.c
+++ b/drivers/s390/cio/blacklist.c
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/blacklist.c
  *   S/390 common I/O routines -- blacklisting of specific devices
- *   $Revision: 1.35 $
+ *   $Revision: 1.39 $
  *
  *    Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
  *			      IBM Corporation
@@ -15,6 +15,7 @@
 #include <linux/vmalloc.h>
 #include <linux/slab.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/ctype.h>
 #include <linux/device.h>
 
@@ -34,10 +35,10 @@
  * These can be single devices or ranges of devices
  */
 
-/* 65536 bits to indicate if a devno is blacklisted or not */
-#define __BL_DEV_WORDS ((__MAX_SUBCHANNELS + (8*sizeof(long) - 1)) / \
+/* 65536 bits for each set to indicate if a devno is blacklisted or not */
+#define __BL_DEV_WORDS ((__MAX_SUBCHANNEL + (8*sizeof(long) - 1)) / \
 			 (8*sizeof(long)))
-static unsigned long bl_dev[__BL_DEV_WORDS];
+static unsigned long bl_dev[__MAX_SSID + 1][__BL_DEV_WORDS];
 typedef enum {add, free} range_action;
 
 /*
@@ -45,21 +46,23 @@ typedef enum {add, free} range_action;
  * (Un-)blacklist the devices from-to
  */
 static inline void
-blacklist_range (range_action action, unsigned int from, unsigned int to)
+blacklist_range (range_action action, unsigned int from, unsigned int to,
+		 unsigned int ssid)
 {
 	if (!to)
 		to = from;
 
-	if (from > to || to > __MAX_SUBCHANNELS) {
+	if (from > to || to > __MAX_SUBCHANNEL || ssid > __MAX_SSID) {
 		printk (KERN_WARNING "Invalid blacklist range "
-			"0x%04x to 0x%04x, skipping\n", from, to);
+			"0.%x.%04x to 0.%x.%04x, skipping\n",
+			ssid, from, ssid, to);
 		return;
 	}
 	for (; from <= to; from++) {
 		if (action == add)
-			set_bit (from, bl_dev);
+			set_bit (from, bl_dev[ssid]);
 		else
-			clear_bit (from, bl_dev);
+			clear_bit (from, bl_dev[ssid]);
 	}
 }
 
@@ -69,7 +72,7 @@ blacklist_range (range_action action, unsigned int from, unsigned int to)
  * Shamelessly grabbed from dasd_devmap.c.
  */
 static inline int
-blacklist_busid(char **str, int *id0, int *id1, int *devno)
+blacklist_busid(char **str, int *id0, int *ssid, int *devno)
 {
 	int val, old_style;
 	char *sav;
@@ -86,7 +89,7 @@ blacklist_busid(char **str, int *id0, int *id1, int *devno)
 		goto confused;
 	val = simple_strtoul(*str, str, 16);
 	if (old_style || (*str)[0] != '.') {
-		*id0 = *id1 = 0;
+		*id0 = *ssid = 0;
 		if (val < 0 || val > 0xffff)
 			goto confused;
 		*devno = val;
@@ -105,7 +108,7 @@ blacklist_busid(char **str, int *id0, int *id1, int *devno)
 	val = simple_strtoul(*str, str, 16);
 	if (val < 0 || val > 0xff || (*str)++[0] != '.')
 		goto confused;
-	*id1 = val;
+	*ssid = val;
 	if (!isxdigit((*str)[0]))	/* We require at least one hex digit */
 		goto confused;
 	val = simple_strtoul(*str, str, 16);
@@ -125,7 +128,7 @@ confused:
 static inline int
 blacklist_parse_parameters (char *str, range_action action)
 {
-	unsigned int from, to, from_id0, to_id0, from_id1, to_id1;
+	unsigned int from, to, from_id0, to_id0, from_ssid, to_ssid;
 
 	while (*str != 0 && *str != '\n') {
 		range_action ra = action;
@@ -142,23 +145,25 @@ blacklist_parse_parameters (char *str, range_action action)
 		 */
 		if (strncmp(str,"all,",4) == 0 || strcmp(str,"all") == 0 ||
 		    strncmp(str,"all\n",4) == 0 || strncmp(str,"all ",4) == 0) {
-			from = 0;
-			to = __MAX_SUBCHANNELS;
+			int j;
+
 			str += 3;
+			for (j=0; j <= __MAX_SSID; j++)
+				blacklist_range(ra, 0, __MAX_SUBCHANNEL, j);
 		} else {
 			int rc;
 
 			rc = blacklist_busid(&str, &from_id0,
-					     &from_id1, &from);
+					     &from_ssid, &from);
 			if (rc)
 				continue;
 			to = from;
 			to_id0 = from_id0;
-			to_id1 = from_id1;
+			to_ssid = from_ssid;
 			if (*str == '-') {
 				str++;
 				rc = blacklist_busid(&str, &to_id0,
-						     &to_id1, &to);
+						     &to_ssid, &to);
 				if (rc)
 					continue;
 			}
@@ -168,18 +173,19 @@ blacklist_parse_parameters (char *str, range_action action)
 					strsep(&str, ",\n"));
 				continue;
 			}
-			if ((from_id0 != to_id0) || (from_id1 != to_id1)) {
+			if ((from_id0 != to_id0) ||
+			    (from_ssid != to_ssid)) {
 				printk(KERN_WARNING "invalid cio_ignore range "
 					"%x.%x.%04x-%x.%x.%04x\n",
-					from_id0, from_id1, from,
-					to_id0, to_id1, to);
+					from_id0, from_ssid, from,
+					to_id0, to_ssid, to);
 				continue;
 			}
+			pr_debug("blacklist_setup: adding range "
+				 "from %x.%x.%04x to %x.%x.%04x\n",
+				 from_id0, from_ssid, from, to_id0, to_ssid, to);
+			blacklist_range (ra, from, to, to_ssid);
 		}
-		/* FIXME: ignoring id0 and id1 here. */
-		pr_debug("blacklist_setup: adding range "
-			 "from 0.0.%04x to 0.0.%04x\n", from, to);
-		blacklist_range (ra, from, to);
 	}
 	return 1;
 }
@@ -213,12 +219,33 @@ __setup ("cio_ignore=", blacklist_setup);
  * Used by validate_subchannel()
  */
 int
-is_blacklisted (int devno)
+is_blacklisted (int ssid, int devno)
 {
-	return test_bit (devno, bl_dev);
+	return test_bit (devno, bl_dev[ssid]);
 }
 
 #ifdef CONFIG_PROC_FS
+static int
+__s390_redo_validation(struct subchannel_id schid, void *data)
+{
+	int ret;
+	struct subchannel *sch;
+
+	sch = get_subchannel_by_schid(schid);
+	if (sch) {
+		/* Already known. */
+		put_device(&sch->dev);
+		return 0;
+	}
+	ret = css_probe_device(schid);
+	if (ret == -ENXIO)
+		return ret; /* We're through. */
+	if (ret == -ENOMEM)
+		/* Stop validation for now. Bad, but no need for a panic. */
+		return ret;
+	return 0;
+}
+
 /*
  * Function: s390_redo_validation
  * Look for no longer blacklisted devices
@@ -226,29 +253,9 @@ is_blacklisted (int devno)
 static inline void
 s390_redo_validation (void)
 {
-	unsigned int irq;
-
 	CIO_TRACE_EVENT (0, "redoval");
-	for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) {
-		int ret;
-		struct subchannel *sch;
-
-		sch = get_subchannel_by_schid(irq);
-		if (sch) {
-			/* Already known. */
-			put_device(&sch->dev);
-			continue;
-		}
-		ret = css_probe_device(irq);
-		if (ret == -ENXIO)
-			break; /* We're through. */
-		if (ret == -ENOMEM)
-			/*
-			 * Stop validation for now. Bad, but no need for a
-			 * panic.
-			 */
-			break;
-	}
+
+	for_each_subchannel(__s390_redo_validation, NULL);
 }
 
 /*
@@ -278,41 +285,90 @@ blacklist_parse_proc_parameters (char *buf)
 	s390_redo_validation ();
 }
 
-/* FIXME: These should be real bus ids and not home-grown ones! */
-static int cio_ignore_read (char *page, char **start, off_t off,
-			    int count, int *eof, void *data)
+/* Iterator struct for all devices. */
+struct ccwdev_iter {
+	int devno;
+	int ssid;
+	int in_range;
+};
+
+static void *
+cio_ignore_proc_seq_start(struct seq_file *s, loff_t *offset)
 {
-	const unsigned int entry_size = 18; /* "0.0.ABCD-0.0.EFGH\n" */
-	long devno;
-	int len;
-
-	len = 0;
-	for (devno = off; /* abuse the page variable
-			   * as counter, see fs/proc/generic.c */
-	     devno < __MAX_SUBCHANNELS && len + entry_size < count; devno++) {
-		if (!test_bit(devno, bl_dev))
-			continue;
-		len += sprintf(page + len, "0.0.%04lx", devno);
-		if (test_bit(devno + 1, bl_dev)) { /* print range */
-			while (++devno < __MAX_SUBCHANNELS)
-				if (!test_bit(devno, bl_dev))
-					break;
-			len += sprintf(page + len, "-0.0.%04lx", --devno);
-		}
-		len += sprintf(page + len, "\n");
-	}
+	struct ccwdev_iter *iter;
+
+	if (*offset >= (__MAX_SUBCHANNEL + 1) * (__MAX_SSID + 1))
+		return NULL;
+	iter = kzalloc(sizeof(struct ccwdev_iter), GFP_KERNEL);
+	if (!iter)
+		return ERR_PTR(-ENOMEM);
+	iter->ssid = *offset / (__MAX_SUBCHANNEL + 1);
+	iter->devno = *offset % (__MAX_SUBCHANNEL + 1);
+	return iter;
+}
+
+static void
+cio_ignore_proc_seq_stop(struct seq_file *s, void *it)
+{
+	if (!IS_ERR(it))
+		kfree(it);
+}
+
+static void *
+cio_ignore_proc_seq_next(struct seq_file *s, void *it, loff_t *offset)
+{
+	struct ccwdev_iter *iter;
+
+	if (*offset >= (__MAX_SUBCHANNEL + 1) * (__MAX_SSID + 1))
+		return NULL;
+	iter = it;
+	if (iter->devno == __MAX_SUBCHANNEL) {
+		iter->devno = 0;
+		iter->ssid++;
+		if (iter->ssid > __MAX_SSID)
+			return NULL;
+	} else
+		iter->devno++;
+	(*offset)++;
+	return iter;
+}
 
-	if (devno < __MAX_SUBCHANNELS)
-		*eof = 1;
-	*start = (char *) (devno - off); /* number of checked entries */
-	return len;
+static int
+cio_ignore_proc_seq_show(struct seq_file *s, void *it)
+{
+	struct ccwdev_iter *iter;
+
+	iter = it;
+	if (!is_blacklisted(iter->ssid, iter->devno))
+		/* Not blacklisted, nothing to output. */
+		return 0;
+	if (!iter->in_range) {
+		/* First device in range. */
+		if ((iter->devno == __MAX_SUBCHANNEL) ||
+		    !is_blacklisted(iter->ssid, iter->devno + 1))
+			/* Singular device. */
+			return seq_printf(s, "0.%x.%04x\n",
+					  iter->ssid, iter->devno);
+		iter->in_range = 1;
+		return seq_printf(s, "0.%x.%04x-", iter->ssid, iter->devno);
+	}
+	if ((iter->devno == __MAX_SUBCHANNEL) ||
+	    !is_blacklisted(iter->ssid, iter->devno + 1)) {
+		/* Last device in range. */
+		iter->in_range = 0;
+		return seq_printf(s, "0.%x.%04x\n", iter->ssid, iter->devno);
+	}
+	return 0;
 }
 
-static int cio_ignore_write(struct file *file, const char __user *user_buf,
-			     unsigned long user_len, void *data)
+static ssize_t
+cio_ignore_write(struct file *file, const char __user *user_buf,
+		 size_t user_len, loff_t *offset)
 {
 	char *buf;
 
+	if (*offset)
+		return -EINVAL;
 	if (user_len > 65536)
 		user_len = 65536;
 	buf = vmalloc (user_len + 1); /* maybe better use the stack? */
@@ -330,6 +386,27 @@ static int cio_ignore_write(struct file *file, const char __user *user_buf,
 	return user_len;
 }
 
+static struct seq_operations cio_ignore_proc_seq_ops = {
+	.start = cio_ignore_proc_seq_start,
+	.stop  = cio_ignore_proc_seq_stop,
+	.next  = cio_ignore_proc_seq_next,
+	.show  = cio_ignore_proc_seq_show,
+};
+
+static int
+cio_ignore_proc_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &cio_ignore_proc_seq_ops);
+}
+
+static struct file_operations cio_ignore_proc_fops = {
+	.open    = cio_ignore_proc_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = seq_release,
+	.write   = cio_ignore_write,
+};
+
 static int
 cio_ignore_proc_init (void)
 {
@@ -340,8 +417,7 @@ cio_ignore_proc_init (void)
 	if (!entry)
 		return 0;
 
-	entry->read_proc  = cio_ignore_read;
-	entry->write_proc = cio_ignore_write;
+	entry->proc_fops = &cio_ignore_proc_fops;
 
 	return 1;
 }
diff --git a/drivers/s390/cio/blacklist.h b/drivers/s390/cio/blacklist.h
index fb42cafbe57c..95e25c1df922 100644
--- a/drivers/s390/cio/blacklist.h
+++ b/drivers/s390/cio/blacklist.h
@@ -1,6 +1,6 @@
 #ifndef S390_BLACKLIST_H
 #define S390_BLACKLIST_H
 
-extern int is_blacklisted (int devno);
+extern int is_blacklisted (int ssid, int devno);
 
 #endif
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
index e7bd7f37f080..e849289d4f3c 100644
--- a/drivers/s390/cio/ccwgroup.c
+++ b/drivers/s390/cio/ccwgroup.c
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/ccwgroup.c
  *  bus driver for ccwgroup
- *   $Revision: 1.32 $
+ *   $Revision: 1.33 $
  *
  *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
  *                       IBM Corporation
@@ -45,7 +45,7 @@ ccwgroup_bus_match (struct device * dev, struct device_driver * drv)
 	return 0;
 }
 static int
-ccwgroup_hotplug (struct device *dev, char **envp, int num_envp, char *buffer,
+ccwgroup_uevent (struct device *dev, char **envp, int num_envp, char *buffer,
 		  int buffer_size)
 {
 	/* TODO */
@@ -55,7 +55,7 @@ ccwgroup_hotplug (struct device *dev, char **envp, int num_envp, char *buffer,
 static struct bus_type ccwgroup_bus_type = {
 	.name    = "ccwgroup",
 	.match   = ccwgroup_bus_match,
-	.hotplug = ccwgroup_hotplug,
+	.uevent = ccwgroup_uevent,
 };
 
 static inline void
@@ -263,7 +263,7 @@ ccwgroup_set_online(struct ccwgroup_device *gdev)
 	struct ccwgroup_driver *gdrv;
 	int ret;
 
-	if (atomic_compare_and_swap(0, 1, &gdev->onoff))
+	if (atomic_cmpxchg(&gdev->onoff, 0, 1) != 0)
 		return -EAGAIN;
 	if (gdev->state == CCWGROUP_ONLINE) {
 		ret = 0;
@@ -289,7 +289,7 @@ ccwgroup_set_offline(struct ccwgroup_device *gdev)
 	struct ccwgroup_driver *gdrv;
 	int ret;
 
-	if (atomic_compare_and_swap(0, 1, &gdev->onoff))
+	if (atomic_cmpxchg(&gdev->onoff, 0, 1) != 0)
 		return -EAGAIN;
 	if (gdev->state == CCWGROUP_OFFLINE) {
 		ret = 0;
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index fa3c23b80e3a..7270808c02d1 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/chsc.c
  *   S/390 common I/O routines -- channel subsystem call
- *   $Revision: 1.120 $
+ *   $Revision: 1.126 $
  *
  *    Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
  *			      IBM Corporation
@@ -24,8 +24,6 @@
 #include "ioasm.h"
 #include "chsc.h"
 
-static struct channel_path *chps[NR_CHPIDS];
-
 static void *sei_page;
 
 static int new_channel_path(int chpid);
@@ -33,13 +31,13 @@ static int new_channel_path(int chpid);
 static inline void
 set_chp_logically_online(int chp, int onoff)
 {
-	chps[chp]->state = onoff;
+	css[0]->chps[chp]->state = onoff;
 }
 
 static int
 get_chp_status(int chp)
 {
-	return (chps[chp] ? chps[chp]->state : -ENODEV);
+	return (css[0]->chps[chp] ? css[0]->chps[chp]->state : -ENODEV);
 }
 
 void
@@ -77,7 +75,9 @@ chsc_get_sch_desc_irq(struct subchannel *sch, void *page)
 
 	struct {
 		struct chsc_header request;
-		u16 reserved1;
+		u16 reserved1a:10;
+		u16 ssid:2;
+		u16 reserved1b:4;
 		u16 f_sch;	  /* first subchannel */
 		u16 reserved2;
 		u16 l_sch;	  /* last subchannel */
@@ -104,8 +104,9 @@ chsc_get_sch_desc_irq(struct subchannel *sch, void *page)
 		.code   = 0x0004,
 	};
 
-	ssd_area->f_sch = sch->irq;
-	ssd_area->l_sch = sch->irq;
+	ssd_area->ssid = sch->schid.ssid;
+	ssd_area->f_sch = sch->schid.sch_no;
+	ssd_area->l_sch = sch->schid.sch_no;
 
 	ccode = chsc(ssd_area);
 	if (ccode > 0) {
@@ -147,7 +148,8 @@ chsc_get_sch_desc_irq(struct subchannel *sch, void *page)
 	 */
 	if (ssd_area->st > 3) { /* uhm, that looks strange... */
 		CIO_CRW_EVENT(0, "Strange subchannel type %d"
-			      " for sch %04x\n", ssd_area->st, sch->irq);
+			      " for sch 0.%x.%04x\n", ssd_area->st,
+			      sch->schid.ssid, sch->schid.sch_no);
 		/*
 		 * There may have been a new subchannel type defined in the
 		 * time since this code was written; since we don't know which
@@ -156,8 +158,9 @@ chsc_get_sch_desc_irq(struct subchannel *sch, void *page)
 		return 0;
 	} else {
 		const char *type[4] = {"I/O", "chsc", "message", "ADM"};
-		CIO_CRW_EVENT(6, "ssd: sch %04x is %s subchannel\n",
-			      sch->irq, type[ssd_area->st]);
+		CIO_CRW_EVENT(6, "ssd: sch 0.%x.%04x is %s subchannel\n",
+			      sch->schid.ssid, sch->schid.sch_no,
+			      type[ssd_area->st]);
 
 		sch->ssd_info.valid = 1;
 		sch->ssd_info.type = ssd_area->st;
@@ -218,13 +221,13 @@ s390_subchannel_remove_chpid(struct device *dev, void *data)
 	int j;
 	int mask;
 	struct subchannel *sch;
-	__u8 *chpid;
+	struct channel_path *chpid;
 	struct schib schib;
 
 	sch = to_subchannel(dev);
 	chpid = data;
 	for (j = 0; j < 8; j++)
-		if (sch->schib.pmcw.chpid[j] == *chpid)
+		if (sch->schib.pmcw.chpid[j] == chpid->id)
 			break;
 	if (j >= 8)
 		return 0;
@@ -232,7 +235,7 @@ s390_subchannel_remove_chpid(struct device *dev, void *data)
 	mask = 0x80 >> j;
 	spin_lock(&sch->lock);
 
-	stsch(sch->irq, &schib);
+	stsch(sch->schid, &schib);
 	if (!schib.pmcw.dnv)
 		goto out_unreg;
 	memcpy(&sch->schib, &schib, sizeof(struct schib));
@@ -284,7 +287,7 @@ out_unlock:
 out_unreg:
 	spin_unlock(&sch->lock);
 	sch->lpm = 0;
-	if (css_enqueue_subchannel_slow(sch->irq)) {
+	if (css_enqueue_subchannel_slow(sch->schid)) {
 		css_clear_subchannel_slow_list();
 		need_rescan = 1;
 	}
@@ -295,23 +298,30 @@ static inline void
 s390_set_chpid_offline( __u8 chpid)
 {
 	char dbf_txt[15];
+	struct device *dev;
 
 	sprintf(dbf_txt, "chpr%x", chpid);
 	CIO_TRACE_EVENT(2, dbf_txt);
 
 	if (get_chp_status(chpid) <= 0)
 		return;
-
-	bus_for_each_dev(&css_bus_type, NULL, &chpid,
+	dev = get_device(&css[0]->chps[chpid]->dev);
+	bus_for_each_dev(&css_bus_type, NULL, to_channelpath(dev),
 			 s390_subchannel_remove_chpid);
 
 	if (need_rescan || css_slow_subchannels_exist())
 		queue_work(slow_path_wq, &slow_path_work);
+	put_device(dev);
 }
 
+struct res_acc_data {
+	struct channel_path *chp;
+	u32 fla_mask;
+	u16 fla;
+};
+
 static int
-s390_process_res_acc_sch(u8 chpid, __u16 fla, u32 fla_mask,
-			 struct subchannel *sch)
+s390_process_res_acc_sch(struct res_acc_data *res_data, struct subchannel *sch)
 {
 	int found;
 	int chp;
@@ -323,8 +333,9 @@ s390_process_res_acc_sch(u8 chpid, __u16 fla, u32 fla_mask,
 		 * check if chpid is in information updated by ssd
 		 */
 		if (sch->ssd_info.valid &&
-		    sch->ssd_info.chpid[chp] == chpid &&
-		    (sch->ssd_info.fla[chp] & fla_mask) == fla) {
+		    sch->ssd_info.chpid[chp] == res_data->chp->id &&
+		    (sch->ssd_info.fla[chp] & res_data->fla_mask)
+		    == res_data->fla) {
 			found = 1;
 			break;
 		}
@@ -337,24 +348,87 @@ s390_process_res_acc_sch(u8 chpid, __u16 fla, u32 fla_mask,
 	 * new path information and eventually check for logically
 	 * offline chpids.
 	 */
-	ccode = stsch(sch->irq, &sch->schib);
+	ccode = stsch(sch->schid, &sch->schib);
 	if (ccode > 0)
 		return 0;
 
 	return 0x80 >> chp;
 }
 
+static inline int
+s390_process_res_acc_new_sch(struct subchannel_id schid)
+{
+	struct schib schib;
+	int ret;
+	/*
+	 * We don't know the device yet, but since a path
+	 * may be available now to the device we'll have
+	 * to do recognition again.
+	 * Since we don't have any idea about which chpid
+	 * that beast may be on we'll have to do a stsch
+	 * on all devices, grr...
+	 */
+	if (stsch_err(schid, &schib))
+		/* We're through */
+		return need_rescan ? -EAGAIN : -ENXIO;
+
+	/* Put it on the slow path. */
+	ret = css_enqueue_subchannel_slow(schid);
+	if (ret) {
+		css_clear_subchannel_slow_list();
+		need_rescan = 1;
+		return -EAGAIN;
+	}
+	return 0;
+}
+
 static int
-s390_process_res_acc (u8 chpid, __u16 fla, u32 fla_mask)
+__s390_process_res_acc(struct subchannel_id schid, void *data)
 {
+	int chp_mask, old_lpm;
+	struct res_acc_data *res_data;
 	struct subchannel *sch;
-	int irq, rc;
+
+	res_data = (struct res_acc_data *)data;
+	sch = get_subchannel_by_schid(schid);
+	if (!sch)
+		/* Check if a subchannel is newly available. */
+		return s390_process_res_acc_new_sch(schid);
+
+	spin_lock_irq(&sch->lock);
+
+	chp_mask = s390_process_res_acc_sch(res_data, sch);
+
+	if (chp_mask == 0) {
+		spin_unlock_irq(&sch->lock);
+		return 0;
+	}
+	old_lpm = sch->lpm;
+	sch->lpm = ((sch->schib.pmcw.pim &
+		     sch->schib.pmcw.pam &
+		     sch->schib.pmcw.pom)
+		    | chp_mask) & sch->opm;
+	if (!old_lpm && sch->lpm)
+		device_trigger_reprobe(sch);
+	else if (sch->driver && sch->driver->verify)
+		sch->driver->verify(&sch->dev);
+
+	spin_unlock_irq(&sch->lock);
+	put_device(&sch->dev);
+	return (res_data->fla_mask == 0xffff) ? -ENODEV : 0;
+}
+
+
+static int
+s390_process_res_acc (struct res_acc_data *res_data)
+{
+	int rc;
 	char dbf_txt[15];
 
-	sprintf(dbf_txt, "accpr%x", chpid);
+	sprintf(dbf_txt, "accpr%x", res_data->chp->id);
 	CIO_TRACE_EVENT( 2, dbf_txt);
-	if (fla != 0) {
-		sprintf(dbf_txt, "fla%x", fla);
+	if (res_data->fla != 0) {
+		sprintf(dbf_txt, "fla%x", res_data->fla);
 		CIO_TRACE_EVENT( 2, dbf_txt);
 	}
 
@@ -365,70 +439,11 @@ s390_process_res_acc (u8 chpid, __u16 fla, u32 fla_mask)
 	 * The more information we have (info), the less scanning
 	 * will we have to do.
 	 */
-
-	if (!get_chp_status(chpid))
-		return 0; /* no need to do the rest */
-
-	rc = 0;
-	for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) {
-		int chp_mask, old_lpm;
-
-		sch = get_subchannel_by_schid(irq);
-		if (!sch) {
-			struct schib schib;
-			int ret;
-			/*
-			 * We don't know the device yet, but since a path
-			 * may be available now to the device we'll have
-			 * to do recognition again.
-			 * Since we don't have any idea about which chpid
-			 * that beast may be on we'll have to do a stsch
-			 * on all devices, grr...
-			 */
-			if (stsch(irq, &schib)) {
-				/* We're through */
-				if (need_rescan)
-					rc = -EAGAIN;
-				break;
-			}
-			if (need_rescan) {
-				rc = -EAGAIN;
-				continue;
-			}
-			/* Put it on the slow path. */
-			ret = css_enqueue_subchannel_slow(irq);
-			if (ret) {
-				css_clear_subchannel_slow_list();
-				need_rescan = 1;
-			}
-			rc = -EAGAIN;
-			continue;
-		}
-	
-		spin_lock_irq(&sch->lock);
-
-		chp_mask = s390_process_res_acc_sch(chpid, fla, fla_mask, sch);
-
-		if (chp_mask == 0) {
-
-			spin_unlock_irq(&sch->lock);
-			continue;
-		}
-		old_lpm = sch->lpm;
-		sch->lpm = ((sch->schib.pmcw.pim &
-			     sch->schib.pmcw.pam &
-			     sch->schib.pmcw.pom)
-			    | chp_mask) & sch->opm;
-		if (!old_lpm && sch->lpm)
-			device_trigger_reprobe(sch);
-		else if (sch->driver && sch->driver->verify)
-			sch->driver->verify(&sch->dev);
-
-		spin_unlock_irq(&sch->lock);
-		put_device(&sch->dev);
-		if (fla_mask == 0xffff)
-			break;
-	}
+	rc = for_each_subchannel(__s390_process_res_acc, res_data);
+	if (css_slow_subchannels_exist())
+		rc = -EAGAIN;
+	else if (rc != -EAGAIN)
+		rc = 0;
 	return rc;
 }
 
@@ -466,6 +481,7 @@ int
 chsc_process_crw(void)
 {
 	int chpid, ret;
+	struct res_acc_data res_data;
 	struct {
 		struct chsc_header request;
 		u32 reserved1;
@@ -499,8 +515,9 @@ chsc_process_crw(void)
 	ret = 0;
 	do {
 		int ccode, status;
+		struct device *dev;
 		memset(sei_area, 0, sizeof(*sei_area));
-
+		memset(&res_data, 0, sizeof(struct res_acc_data));
 		sei_area->request = (struct chsc_header) {
 			.length = 0x0010,
 			.code   = 0x000e,
@@ -573,26 +590,25 @@ chsc_process_crw(void)
 			if (status < 0)
 				new_channel_path(sei_area->rsid);
 			else if (!status)
-				return 0;
-			if ((sei_area->vf & 0x80) == 0) {
-				pr_debug("chpid: %x\n", sei_area->rsid);
-				ret = s390_process_res_acc(sei_area->rsid,
-							   0, 0);
-			} else if ((sei_area->vf & 0xc0) == 0x80) {
-				pr_debug("chpid: %x link addr: %x\n",
-					 sei_area->rsid, sei_area->fla);
-				ret = s390_process_res_acc(sei_area->rsid,
-							   sei_area->fla,
-							   0xff00);
-			} else if ((sei_area->vf & 0xc0) == 0xc0) {
-				pr_debug("chpid: %x full link addr: %x\n",
-					 sei_area->rsid, sei_area->fla);
-				ret = s390_process_res_acc(sei_area->rsid,
-							   sei_area->fla,
-							   0xffff);
+				break;
+			dev = get_device(&css[0]->chps[sei_area->rsid]->dev);
+			res_data.chp = to_channelpath(dev);
+			pr_debug("chpid: %x", sei_area->rsid);
+			if ((sei_area->vf & 0xc0) != 0) {
+				res_data.fla = sei_area->fla;
+				if ((sei_area->vf & 0xc0) == 0xc0) {
+					pr_debug(" full link addr: %x",
+						 sei_area->fla);
+					res_data.fla_mask = 0xffff;
+				} else {
+					pr_debug(" link addr: %x",
+						 sei_area->fla);
+					res_data.fla_mask = 0xff00;
+				}
 			}
-			pr_debug("\n");
-			
+			ret = s390_process_res_acc(&res_data);
+			pr_debug("\n\n");
+			put_device(dev);
 			break;
 			
 		default: /* other stuff */
@@ -604,12 +620,72 @@ chsc_process_crw(void)
 	return ret;
 }
 
+static inline int
+__chp_add_new_sch(struct subchannel_id schid)
+{
+	struct schib schib;
+	int ret;
+
+	if (stsch(schid, &schib))
+		/* We're through */
+		return need_rescan ? -EAGAIN : -ENXIO;
+
+	/* Put it on the slow path. */
+	ret = css_enqueue_subchannel_slow(schid);
+	if (ret) {
+		css_clear_subchannel_slow_list();
+		need_rescan = 1;
+		return -EAGAIN;
+	}
+	return 0;
+}
+
+
 static int
-chp_add(int chpid)
+__chp_add(struct subchannel_id schid, void *data)
 {
+	int i;
+	struct channel_path *chp;
 	struct subchannel *sch;
-	int irq, ret, rc;
+
+	chp = (struct channel_path *)data;
+	sch = get_subchannel_by_schid(schid);
+	if (!sch)
+		/* Check if the subchannel is now available. */
+		return __chp_add_new_sch(schid);
+	spin_lock(&sch->lock);
+	for (i=0; i<8; i++)
+		if (sch->schib.pmcw.chpid[i] == chp->id) {
+			if (stsch(sch->schid, &sch->schib) != 0) {
+				/* Endgame. */
+				spin_unlock(&sch->lock);
+				return -ENXIO;
+			}
+			break;
+		}
+	if (i==8) {
+		spin_unlock(&sch->lock);
+		return 0;
+	}
+	sch->lpm = ((sch->schib.pmcw.pim &
+		     sch->schib.pmcw.pam &
+		     sch->schib.pmcw.pom)
+		    | 0x80 >> i) & sch->opm;
+
+	if (sch->driver && sch->driver->verify)
+		sch->driver->verify(&sch->dev);
+
+	spin_unlock(&sch->lock);
+	put_device(&sch->dev);
+	return 0;
+}
+
+static int
+chp_add(int chpid)
+{
+	int rc;
 	char dbf_txt[15];
+	struct device *dev;
 
 	if (!get_chp_status(chpid))
 		return 0; /* no need to do the rest */
@@ -617,59 +693,13 @@ chp_add(int chpid)
 	sprintf(dbf_txt, "cadd%x", chpid);
 	CIO_TRACE_EVENT(2, dbf_txt);
 
-	rc = 0;
-	for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) {
-		int i;
-
-		sch = get_subchannel_by_schid(irq);
-		if (!sch) {
-			struct schib schib;
-
-			if (stsch(irq, &schib)) {
-				/* We're through */
-				if (need_rescan)
-					rc = -EAGAIN;
-				break;
-			}
-			if (need_rescan) {
-				rc = -EAGAIN;
-				continue;
-			}
-			/* Put it on the slow path. */
-			ret = css_enqueue_subchannel_slow(irq);
-			if (ret) {
-				css_clear_subchannel_slow_list();
-				need_rescan = 1;
-			}
-			rc = -EAGAIN;
-			continue;
-		}
-	
-		spin_lock(&sch->lock);
-		for (i=0; i<8; i++)
-			if (sch->schib.pmcw.chpid[i] == chpid) {
-				if (stsch(sch->irq, &sch->schib) != 0) {
-					/* Endgame. */
-					spin_unlock(&sch->lock);
-					return rc;
-				}
-				break;
-			}
-		if (i==8) {
-			spin_unlock(&sch->lock);
-			return rc;
-		}
-		sch->lpm = ((sch->schib.pmcw.pim &
-			     sch->schib.pmcw.pam &
-			     sch->schib.pmcw.pom)
-			    | 0x80 >> i) & sch->opm;
-
-		if (sch->driver && sch->driver->verify)
-			sch->driver->verify(&sch->dev);
-
-		spin_unlock(&sch->lock);
-		put_device(&sch->dev);
-	}
+	dev = get_device(&css[0]->chps[chpid]->dev);
+	rc = for_each_subchannel(__chp_add, to_channelpath(dev));
+	if (css_slow_subchannels_exist())
+		rc = -EAGAIN;
+	if (rc != -EAGAIN)
+		rc = 0;
+	put_device(dev);
 	return rc;
 }
 
@@ -702,7 +732,7 @@ __check_for_io_and_kill(struct subchannel *sch, int index)
 	if (!device_is_online(sch))
 		/* cio could be doing I/O. */
 		return 0;
-	cc = stsch(sch->irq, &sch->schib);
+	cc = stsch(sch->schid, &sch->schib);
 	if (cc)
 		return 0;
 	if (sch->schib.scsw.actl && sch->schib.pmcw.lpum == (0x80 >> index)) {
@@ -743,7 +773,7 @@ __s390_subchannel_vary_chpid(struct subchannel *sch, __u8 chpid, int on)
 			 * just varied off path. Then kill it.
 			 */
 			if (!__check_for_io_and_kill(sch, chp) && !sch->lpm) {
-				if (css_enqueue_subchannel_slow(sch->irq)) {
+				if (css_enqueue_subchannel_slow(sch->schid)) {
 					css_clear_subchannel_slow_list();
 					need_rescan = 1;
 				}
@@ -781,6 +811,29 @@ s390_subchannel_vary_chpid_on(struct device *dev, void *data)
 	return 0;
 }
 
+static int
+__s390_vary_chpid_on(struct subchannel_id schid, void *data)
+{
+	struct schib schib;
+	struct subchannel *sch;
+
+	sch = get_subchannel_by_schid(schid);
+	if (sch) {
+		put_device(&sch->dev);
+		return 0;
+	}
+	if (stsch_err(schid, &schib))
+		/* We're through */
+		return -ENXIO;
+	/* Put it on the slow path. */
+	if (css_enqueue_subchannel_slow(schid)) {
+		css_clear_subchannel_slow_list();
+		need_rescan = 1;
+		return -EAGAIN;
+	}
+	return 0;
+}
+
 /*
  * Function: s390_vary_chpid
  * Varies the specified chpid online or offline
@@ -789,8 +842,7 @@ static int
 s390_vary_chpid( __u8 chpid, int on)
 {
 	char dbf_text[15];
-	int status, irq, ret;
-	struct subchannel *sch;
+	int status;
 
 	sprintf(dbf_text, on?"varyon%x":"varyoff%x", chpid);
 	CIO_TRACE_EVENT( 2, dbf_text);
@@ -815,30 +867,9 @@ s390_vary_chpid( __u8 chpid, int on)
 	bus_for_each_dev(&css_bus_type, NULL, &chpid, on ?
 			 s390_subchannel_vary_chpid_on :
 			 s390_subchannel_vary_chpid_off);
-	if (!on)
-		goto out;
-	/* Scan for new devices on varied on path. */
-	for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) {
-		struct schib schib;
-
-		if (need_rescan)
-			break;
-		sch = get_subchannel_by_schid(irq);
-		if (sch) {
-			put_device(&sch->dev);
-			continue;
-		}
-		if (stsch(irq, &schib))
-			/* We're through */
-			break;
-		/* Put it on the slow path. */
-		ret = css_enqueue_subchannel_slow(irq);
-		if (ret) {
-			css_clear_subchannel_slow_list();
-			need_rescan = 1;
-		}
-	}
-out:
+	if (on)
+		/* Scan for new devices on varied on path. */
+		for_each_subchannel(__s390_vary_chpid_on, NULL);
 	if (need_rescan || css_slow_subchannels_exist())
 		queue_work(slow_path_wq, &slow_path_work);
 	return 0;
@@ -995,7 +1026,7 @@ new_channel_path(int chpid)
 	chp->id = chpid;
 	chp->state = 1;
 	chp->dev = (struct device) {
-		.parent  = &css_bus_device,
+		.parent  = &css[0]->device,
 		.release = chp_release,
 	};
 	snprintf(chp->dev.bus_id, BUS_ID_SIZE, "chp0.%x", chpid);
@@ -1017,7 +1048,7 @@ new_channel_path(int chpid)
 		device_unregister(&chp->dev);
 		goto out_free;
 	} else
-		chps[chpid] = chp;
+		css[0]->chps[chpid] = chp;
 	return ret;
 out_free:
 	kfree(chp);
@@ -1030,7 +1061,7 @@ chsc_get_chp_desc(struct subchannel *sch, int chp_no)
 	struct channel_path *chp;
 	struct channel_path_desc *desc;
 
-	chp = chps[sch->schib.pmcw.chpid[chp_no]];
+	chp = css[0]->chps[sch->schib.pmcw.chpid[chp_no]];
 	if (!chp)
 		return NULL;
 	desc = kmalloc(sizeof(struct channel_path_desc), GFP_KERNEL);
@@ -1051,6 +1082,54 @@ chsc_alloc_sei_area(void)
 	return (sei_page ? 0 : -ENOMEM);
 }
 
+int __init
+chsc_enable_facility(int operation_code)
+{
+	int ret;
+	struct {
+		struct chsc_header request;
+		u8 reserved1:4;
+		u8 format:4;
+		u8 reserved2;
+		u16 operation_code;
+		u32 reserved3;
+		u32 reserved4;
+		u32 operation_data_area[252];
+		struct chsc_header response;
+		u32 reserved5:4;
+		u32 format2:4;
+		u32 reserved6:24;
+	} *sda_area;
+
+	sda_area = (void *)get_zeroed_page(GFP_KERNEL|GFP_DMA);
+	if (!sda_area)
+		return -ENOMEM;
+	sda_area->request = (struct chsc_header) {
+		.length = 0x0400,
+		.code = 0x0031,
+	};
+	sda_area->operation_code = operation_code;
+
+	ret = chsc(sda_area);
+	if (ret > 0) {
+		ret = (ret == 3) ? -ENODEV : -EBUSY;
+		goto out;
+	}
+	switch (sda_area->response.code) {
+	case 0x0003: /* invalid request block */
+	case 0x0007:
+		ret = -EINVAL;
+		break;
+	case 0x0004: /* command not provided */
+	case 0x0101: /* facility not provided */
+		ret = -EOPNOTSUPP;
+		break;
+	}
+ out:
+	free_page((unsigned long)sda_area);
+	return ret;
+}
+
 subsys_initcall(chsc_alloc_sei_area);
 
 struct css_general_char css_general_characteristics;
diff --git a/drivers/s390/cio/chsc.h b/drivers/s390/cio/chsc.h
index be20da49d147..44e4b4bb1c5a 100644
--- a/drivers/s390/cio/chsc.h
+++ b/drivers/s390/cio/chsc.h
@@ -1,12 +1,12 @@
 #ifndef S390_CHSC_H
 #define S390_CHSC_H
 
-#define NR_CHPIDS 256
-
 #define CHSC_SEI_ACC_CHPID        1
 #define CHSC_SEI_ACC_LINKADDR     2
 #define CHSC_SEI_ACC_FULLLINKADDR 3
 
+#define CHSC_SDA_OC_MSS   0x2
+
 struct chsc_header {
 	u16 length;
 	u16 code;
@@ -43,7 +43,9 @@ struct css_general_char {
 	u32 ext_mb : 1;  /* bit 48 */
 	u32 : 7;
 	u32 aif_tdd : 1; /* bit 56 */
-	u32 : 10;
+	u32 : 1;
+	u32 qebsm : 1;   /* bit 58 */
+	u32 : 8;
 	u32 aif_osa : 1; /* bit 67 */
 	u32 : 28;
 }__attribute__((packed));
@@ -63,4 +65,9 @@ extern int chsc_determine_css_characteristics(void);
 extern int css_characteristics_avail;
 
 extern void *chsc_get_chp_desc(struct subchannel*, int);
+
+extern int chsc_enable_facility(int);
+
+#define to_channelpath(dev) container_of(dev, struct channel_path, dev)
+
 #endif
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 185bc73c3ecd..7376bc87206d 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/cio.c
  *   S/390 common I/O routines -- low level i/o calls
- *   $Revision: 1.135 $
+ *   $Revision: 1.138 $
  *
  *    Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
  *			      IBM Corporation
@@ -135,7 +135,7 @@ cio_tpi(void)
 		return 0;
 	irb = (struct irb *) __LC_IRB;
 	/* Store interrupt response block to lowcore. */
-	if (tsch (tpi_info->irq, irb) != 0)
+	if (tsch (tpi_info->schid, irb) != 0)
 		/* Not status pending or not operational. */
 		return 1;
 	sch = (struct subchannel *)(unsigned long)tpi_info->intparm;
@@ -163,10 +163,11 @@ cio_start_handle_notoper(struct subchannel *sch, __u8 lpm)
 	else
 		sch->lpm = 0;
 
-	stsch (sch->irq, &sch->schib);
+	stsch (sch->schid, &sch->schib);
 
 	CIO_MSG_EVENT(0, "cio_start: 'not oper' status for "
-		      "subchannel %04x!\n", sch->irq);
+		      "subchannel 0.%x.%04x!\n", sch->schid.ssid,
+		      sch->schid.sch_no);
 	sprintf(dbf_text, "no%s", sch->dev.bus_id);
 	CIO_TRACE_EVENT(0, dbf_text);
 	CIO_HEX_EVENT(0, &sch->schib, sizeof (struct schib));
@@ -194,7 +195,7 @@ cio_start_key (struct subchannel *sch,	/* subchannel structure */
 	sch->orb.spnd = sch->options.suspend;
 	sch->orb.ssic = sch->options.suspend && sch->options.inter;
 	sch->orb.lpm = (lpm != 0) ? (lpm & sch->opm) : sch->lpm;
-#ifdef CONFIG_ARCH_S390X
+#ifdef CONFIG_64BIT
 	/*
 	 * for 64 bit we always support 64 bit IDAWs with 4k page size only
 	 */
@@ -204,7 +205,7 @@ cio_start_key (struct subchannel *sch,	/* subchannel structure */
 	sch->orb.key = key >> 4;
 	/* issue "Start Subchannel" */
 	sch->orb.cpa = (__u32) __pa (cpa);
-	ccode = ssch (sch->irq, &sch->orb);
+	ccode = ssch (sch->schid, &sch->orb);
 
 	/* process condition code */
 	sprintf (dbf_txt, "ccode:%d", ccode);
@@ -243,7 +244,7 @@ cio_resume (struct subchannel *sch)
 	CIO_TRACE_EVENT (4, "resIO");
 	CIO_TRACE_EVENT (4, sch->dev.bus_id);
 
-	ccode = rsch (sch->irq);
+	ccode = rsch (sch->schid);
 
 	sprintf (dbf_txt, "ccode:%d", ccode);
 	CIO_TRACE_EVENT (4, dbf_txt);
@@ -283,7 +284,7 @@ cio_halt(struct subchannel *sch)
 	/*
 	 * Issue "Halt subchannel" and process condition code
 	 */
-	ccode = hsch (sch->irq);
+	ccode = hsch (sch->schid);
 
 	sprintf (dbf_txt, "ccode:%d", ccode);
 	CIO_TRACE_EVENT (2, dbf_txt);
@@ -318,7 +319,7 @@ cio_clear(struct subchannel *sch)
 	/*
 	 * Issue "Clear subchannel" and process condition code
 	 */
-	ccode = csch (sch->irq);
+	ccode = csch (sch->schid);
 
 	sprintf (dbf_txt, "ccode:%d", ccode);
 	CIO_TRACE_EVENT (2, dbf_txt);
@@ -351,7 +352,7 @@ cio_cancel (struct subchannel *sch)
 	CIO_TRACE_EVENT (2, "cancelIO");
 	CIO_TRACE_EVENT (2, sch->dev.bus_id);
 
-	ccode = xsch (sch->irq);
+	ccode = xsch (sch->schid);
 
 	sprintf (dbf_txt, "ccode:%d", ccode);
 	CIO_TRACE_EVENT (2, dbf_txt);
@@ -359,7 +360,7 @@ cio_cancel (struct subchannel *sch)
 	switch (ccode) {
 	case 0:		/* success */
 		/* Update information in scsw. */
-		stsch (sch->irq, &sch->schib);
+		stsch (sch->schid, &sch->schib);
 		return 0;
 	case 1:		/* status pending */
 		return -EBUSY;
@@ -381,7 +382,7 @@ cio_modify (struct subchannel *sch)
 
 	ret = 0;
 	for (retry = 0; retry < 5; retry++) {
-		ccode = msch_err (sch->irq, &sch->schib);
+		ccode = msch_err (sch->schid, &sch->schib);
 		if (ccode < 0)	/* -EIO if msch gets a program check. */
 			return ccode;
 		switch (ccode) {
@@ -414,7 +415,7 @@ cio_enable_subchannel (struct subchannel *sch, unsigned int isc)
 	CIO_TRACE_EVENT (2, "ensch");
 	CIO_TRACE_EVENT (2, sch->dev.bus_id);
 
-	ccode = stsch (sch->irq, &sch->schib);
+	ccode = stsch (sch->schid, &sch->schib);
 	if (ccode)
 		return -ENODEV;
 
@@ -432,13 +433,13 @@ cio_enable_subchannel (struct subchannel *sch, unsigned int isc)
 			 */
 			sch->schib.pmcw.csense = 0;
 		if (ret == 0) {
-			stsch (sch->irq, &sch->schib);
+			stsch (sch->schid, &sch->schib);
 			if (sch->schib.pmcw.ena)
 				break;
 		}
 		if (ret == -EBUSY) {
 			struct irb irb;
-			if (tsch(sch->irq, &irb) != 0)
+			if (tsch(sch->schid, &irb) != 0)
 				break;
 		}
 	}
@@ -461,7 +462,7 @@ cio_disable_subchannel (struct subchannel *sch)
 	CIO_TRACE_EVENT (2, "dissch");
 	CIO_TRACE_EVENT (2, sch->dev.bus_id);
 
-	ccode = stsch (sch->irq, &sch->schib);
+	ccode = stsch (sch->schid, &sch->schib);
 	if (ccode == 3)		/* Not operational. */
 		return -ENODEV;
 
@@ -485,7 +486,7 @@ cio_disable_subchannel (struct subchannel *sch)
 			 */
 			break;
 		if (ret == 0) {
-			stsch (sch->irq, &sch->schib);
+			stsch (sch->schid, &sch->schib);
 			if (!sch->schib.pmcw.ena)
 				break;
 		}
@@ -508,12 +509,12 @@ cio_disable_subchannel (struct subchannel *sch)
  *   -ENODEV for subchannels with invalid device number or blacklisted devices
  */
 int
-cio_validate_subchannel (struct subchannel *sch, unsigned int irq)
+cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
 {
 	char dbf_txt[15];
 	int ccode;
 
-	sprintf (dbf_txt, "valsch%x", irq);
+	sprintf (dbf_txt, "valsch%x", schid.sch_no);
 	CIO_TRACE_EVENT (4, dbf_txt);
 
 	/* Nuke all fields. */
@@ -522,17 +523,20 @@ cio_validate_subchannel (struct subchannel *sch, unsigned int irq)
 	spin_lock_init(&sch->lock);
 
 	/* Set a name for the subchannel */
-	snprintf (sch->dev.bus_id, BUS_ID_SIZE, "0.0.%04x", irq);
+	snprintf (sch->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x", schid.ssid,
+		  schid.sch_no);
 
 	/*
 	 * The first subchannel that is not-operational (ccode==3)
 	 *  indicates that there aren't any more devices available.
+	 * If stsch gets an exception, it means the current subchannel set
+	 *  is not valid.
 	 */
-	sch->irq = irq;
-	ccode = stsch (irq, &sch->schib);
+	ccode = stsch_err (schid, &sch->schib);
 	if (ccode)
-		return -ENXIO;
+		return (ccode == 3) ? -ENXIO : ccode;
 
+	sch->schid = schid;
 	/* Copy subchannel type from path management control word. */
 	sch->st = sch->schib.pmcw.st;
 
@@ -541,9 +545,9 @@ cio_validate_subchannel (struct subchannel *sch, unsigned int irq)
 	 */
 	if (sch->st != 0) {
 		CIO_DEBUG(KERN_INFO, 0,
-			  "Subchannel %04X reports "
+			  "Subchannel 0.%x.%04x reports "
 			  "non-I/O subchannel type %04X\n",
-			  sch->irq, sch->st);
+			  sch->schid.ssid, sch->schid.sch_no, sch->st);
 		/* We stop here for non-io subchannels. */
 		return sch->st;
 	}
@@ -554,26 +558,29 @@ cio_validate_subchannel (struct subchannel *sch, unsigned int irq)
 		return -ENODEV;
 
 	/* Devno is valid. */
-	if (is_blacklisted (sch->schib.pmcw.dev)) {
+	if (is_blacklisted (sch->schid.ssid, sch->schib.pmcw.dev)) {
 		/*
 		 * This device must not be known to Linux. So we simply
 		 * say that there is no device and return ENODEV.
 		 */
 		CIO_MSG_EVENT(0, "Blacklisted device detected "
-			      "at devno %04X\n", sch->schib.pmcw.dev);
+			      "at devno %04X, subchannel set %x\n",
+			      sch->schib.pmcw.dev, sch->schid.ssid);
 		return -ENODEV;
 	}
 	sch->opm = 0xff;
-	chsc_validate_chpids(sch);
+	if (!cio_is_console(sch->schid))
+		chsc_validate_chpids(sch);
 	sch->lpm = sch->schib.pmcw.pim &
 		sch->schib.pmcw.pam &
 		sch->schib.pmcw.pom &
 		sch->opm;
 
 	CIO_DEBUG(KERN_INFO, 0,
-		  "Detected device %04X on subchannel %04X"
+		  "Detected device %04x on subchannel 0.%x.%04X"
 		  " - PIM = %02X, PAM = %02X, POM = %02X\n",
-		  sch->schib.pmcw.dev, sch->irq, sch->schib.pmcw.pim,
+		  sch->schib.pmcw.dev, sch->schid.ssid,
+		  sch->schid.sch_no, sch->schib.pmcw.pim,
 		  sch->schib.pmcw.pam, sch->schib.pmcw.pom);
 
 	/*
@@ -632,7 +639,7 @@ do_IRQ (struct pt_regs *regs)
 		if (sch)
 			spin_lock(&sch->lock);
 		/* Store interrupt response block to lowcore. */
-		if (tsch (tpi_info->irq, irb) == 0 && sch) {
+		if (tsch (tpi_info->schid, irb) == 0 && sch) {
 			/* Keep subchannel information word up to date. */
 			memcpy (&sch->schib.scsw, &irb->scsw,
 				sizeof (irb->scsw));
@@ -691,28 +698,36 @@ wait_cons_dev (void)
 }
 
 static int
-cio_console_irq(void)
+cio_test_for_console(struct subchannel_id schid, void *data)
 {
-	int irq;
+	if (stsch_err(schid, &console_subchannel.schib) != 0)
+		return -ENXIO;
+	if (console_subchannel.schib.pmcw.dnv &&
+	    console_subchannel.schib.pmcw.dev ==
+	    console_devno) {
+		console_irq = schid.sch_no;
+		return 1; /* found */
+	}
+	return 0;
+}
+
+
+static int
+cio_get_console_sch_no(void)
+{
+	struct subchannel_id schid;
 	
+	init_subchannel_id(&schid);
 	if (console_irq != -1) {
 		/* VM provided us with the irq number of the console. */
-		if (stsch(console_irq, &console_subchannel.schib) != 0 ||
+		schid.sch_no = console_irq;
+		if (stsch(schid, &console_subchannel.schib) != 0 ||
 		    !console_subchannel.schib.pmcw.dnv)
 			return -1;
 		console_devno = console_subchannel.schib.pmcw.dev;
 	} else if (console_devno != -1) {
 		/* At least the console device number is known. */
-		for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) {
-			if (stsch(irq, &console_subchannel.schib) != 0)
-				break;
-			if (console_subchannel.schib.pmcw.dnv &&
-			    console_subchannel.schib.pmcw.dev ==
-			    console_devno) {
-				console_irq = irq;
-				break;
-			}
-		}
+		for_each_subchannel(cio_test_for_console, NULL);
 		if (console_irq == -1)
 			return -1;
 	} else {
@@ -728,17 +743,20 @@ cio_console_irq(void)
 struct subchannel *
 cio_probe_console(void)
 {
-	int irq, ret;
+	int sch_no, ret;
+	struct subchannel_id schid;
 
 	if (xchg(&console_subchannel_in_use, 1) != 0)
 		return ERR_PTR(-EBUSY);
-	irq = cio_console_irq();
-	if (irq == -1) {
+	sch_no = cio_get_console_sch_no();
+	if (sch_no == -1) {
 		console_subchannel_in_use = 0;
 		return ERR_PTR(-ENODEV);
 	}
 	memset(&console_subchannel, 0, sizeof(struct subchannel));
-	ret = cio_validate_subchannel(&console_subchannel, irq);
+	init_subchannel_id(&schid);
+	schid.sch_no = sch_no;
+	ret = cio_validate_subchannel(&console_subchannel, schid);
 	if (ret) {
 		console_subchannel_in_use = 0;
 		return ERR_PTR(-ENODEV);
@@ -770,11 +788,11 @@ cio_release_console(void)
 
 /* Bah... hack to catch console special sausages. */
 int
-cio_is_console(int irq)
+cio_is_console(struct subchannel_id schid)
 {
 	if (!console_subchannel_in_use)
 		return 0;
-	return (irq == console_subchannel.irq);
+	return schid_equal(&schid, &console_subchannel.schid);
 }
 
 struct subchannel *
@@ -787,7 +805,7 @@ cio_get_console_subchannel(void)
 
 #endif
 static inline int
-__disable_subchannel_easy(unsigned int schid, struct schib *schib)
+__disable_subchannel_easy(struct subchannel_id schid, struct schib *schib)
 {
 	int retry, cc;
 
@@ -805,7 +823,7 @@ __disable_subchannel_easy(unsigned int schid, struct schib *schib)
 }
 
 static inline int
-__clear_subchannel_easy(unsigned int schid)
+__clear_subchannel_easy(struct subchannel_id schid)
 {
 	int retry;
 
@@ -815,8 +833,8 @@ __clear_subchannel_easy(unsigned int schid)
 		struct tpi_info ti;
 
 		if (tpi(&ti)) {
-			tsch(ti.irq, (struct irb *)__LC_IRB);
-			if (ti.irq == schid)
+			tsch(ti.schid, (struct irb *)__LC_IRB);
+			if (schid_equal(&ti.schid, &schid))
 				return 0;
 		}
 		udelay(100);
@@ -825,31 +843,33 @@ __clear_subchannel_easy(unsigned int schid)
 }
 
 extern void do_reipl(unsigned long devno);
+static int
+__shutdown_subchannel_easy(struct subchannel_id schid, void *data)
+{
+	struct schib schib;
+
+	if (stsch_err(schid, &schib))
+		return -ENXIO;
+	if (!schib.pmcw.ena)
+		return 0;
+	switch(__disable_subchannel_easy(schid, &schib)) {
+	case 0:
+	case -ENODEV:
+		break;
+	default: /* -EBUSY */
+		if (__clear_subchannel_easy(schid))
+			break; /* give up... */
+		stsch(schid, &schib);
+		__disable_subchannel_easy(schid, &schib);
+	}
+	return 0;
+}
 
-/* Clear all subchannels. */
 void
 clear_all_subchannels(void)
 {
-	unsigned int schid;
-
 	local_irq_disable();
-	for (schid=0;schid<=highest_subchannel;schid++) {
-		struct schib schib;
-		if (stsch(schid, &schib))
-			break; /* break out of the loop */
-		if (!schib.pmcw.ena)
-			continue;
-		switch(__disable_subchannel_easy(schid, &schib)) {
-		case 0:
-		case -ENODEV:
-			break;
-		default: /* -EBUSY */
-			if (__clear_subchannel_easy(schid))
-				break; /* give up... jump out of switch */
-			stsch(schid, &schib);
-			__disable_subchannel_easy(schid, &schib);
-		}
-	}
+	for_each_subchannel(__shutdown_subchannel_easy, NULL);
 }
 
 /* Make sure all subchannels are quiet before we re-ipl an lpar. */
diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h
index c50a9da420a9..0ca987344e07 100644
--- a/drivers/s390/cio/cio.h
+++ b/drivers/s390/cio/cio.h
@@ -1,6 +1,8 @@
 #ifndef S390_CIO_H
 #define S390_CIO_H
 
+#include "schid.h"
+
 /*
  * where we put the ssd info
  */
@@ -83,7 +85,7 @@ struct orb {
 
 /* subchannel data structure used by I/O subroutines */
 struct subchannel {
-	unsigned int irq;	/* aka. subchannel number */
+	struct subchannel_id schid;
 	spinlock_t lock;	/* subchannel lock */
 
 	enum {
@@ -114,7 +116,7 @@ struct subchannel {
 
 #define to_subchannel(n) container_of(n, struct subchannel, dev)
 
-extern int cio_validate_subchannel (struct subchannel *, unsigned int);
+extern int cio_validate_subchannel (struct subchannel *, struct subchannel_id);
 extern int cio_enable_subchannel (struct subchannel *, unsigned int);
 extern int cio_disable_subchannel (struct subchannel *);
 extern int cio_cancel (struct subchannel *);
@@ -127,14 +129,15 @@ extern int cio_cancel (struct subchannel *);
 extern int cio_set_options (struct subchannel *, int);
 extern int cio_get_options (struct subchannel *);
 extern int cio_modify (struct subchannel *);
+
 /* Use with care. */
 #ifdef CONFIG_CCW_CONSOLE
 extern struct subchannel *cio_probe_console(void);
 extern void cio_release_console(void);
-extern int cio_is_console(int irq);
+extern int cio_is_console(struct subchannel_id);
 extern struct subchannel *cio_get_console_subchannel(void);
 #else
-#define cio_is_console(irq) 0
+#define cio_is_console(schid) 0
 #define cio_get_console_subchannel() NULL
 #endif
 
diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c
index b978f7fe8327..0b03714e696a 100644
--- a/drivers/s390/cio/cmf.c
+++ b/drivers/s390/cio/cmf.c
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/s390/cio/cmf.c ($Revision: 1.16 $)
+ * linux/drivers/s390/cio/cmf.c ($Revision: 1.19 $)
  *
  * Linux on zSeries Channel Measurement Facility support
  *
@@ -178,7 +178,7 @@ set_schib(struct ccw_device *cdev, u32 mme, int mbfc, unsigned long address)
 	/* msch can silently fail, so do it again if necessary */
 	for (retry = 0; retry < 3; retry++) {
 		/* prepare schib */
-		stsch(sch->irq, schib);
+		stsch(sch->schid, schib);
 		schib->pmcw.mme  = mme;
 		schib->pmcw.mbfc = mbfc;
 		/* address can be either a block address or a block index */
@@ -188,7 +188,7 @@ set_schib(struct ccw_device *cdev, u32 mme, int mbfc, unsigned long address)
 			schib->pmcw.mbi = address;
 
 		/* try to submit it */
-		switch(ret = msch_err(sch->irq, schib)) {
+		switch(ret = msch_err(sch->schid, schib)) {
 			case 0:
 				break;
 			case 1:
@@ -202,7 +202,7 @@ set_schib(struct ccw_device *cdev, u32 mme, int mbfc, unsigned long address)
 				ret = -EINVAL;
 				break;
 		}
-		stsch(sch->irq, schib); /* restore the schib */
+		stsch(sch->schid, schib); /* restore the schib */
 
 		if (ret)
 			break;
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 555119cacc27..e565193650c7 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/css.c
  *  driver for channel subsystem
- *   $Revision: 1.85 $
+ *   $Revision: 1.93 $
  *
  *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
  *			 IBM Corporation
@@ -21,19 +21,35 @@
 #include "ioasm.h"
 #include "chsc.h"
 
-unsigned int highest_subchannel;
 int need_rescan = 0;
 int css_init_done = 0;
+static int max_ssid = 0;
+
+struct channel_subsystem *css[__MAX_CSSID + 1];
 
-struct pgid global_pgid;
 int css_characteristics_avail = 0;
 
-struct device css_bus_device = {
-	.bus_id = "css0",
-};
+inline int
+for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *data)
+{
+	struct subchannel_id schid;
+	int ret;
+
+	init_subchannel_id(&schid);
+	ret = -ENODEV;
+	do {
+		do {
+			ret = fn(schid, data);
+			if (ret)
+				break;
+		} while (schid.sch_no++ < __MAX_SUBCHANNEL);
+		schid.sch_no = 0;
+	} while (schid.ssid++ < max_ssid);
+	return ret;
+}
 
 static struct subchannel *
-css_alloc_subchannel(int irq)
+css_alloc_subchannel(struct subchannel_id schid)
 {
 	struct subchannel *sch;
 	int ret;
@@ -41,13 +57,11 @@ css_alloc_subchannel(int irq)
 	sch = kmalloc (sizeof (*sch), GFP_KERNEL | GFP_DMA);
 	if (sch == NULL)
 		return ERR_PTR(-ENOMEM);
-	ret = cio_validate_subchannel (sch, irq);
+	ret = cio_validate_subchannel (sch, schid);
 	if (ret < 0) {
 		kfree(sch);
 		return ERR_PTR(ret);
 	}
-	if (irq > highest_subchannel)
-		highest_subchannel = irq;
 
 	if (sch->st != SUBCHANNEL_TYPE_IO) {
 		/* For now we ignore all non-io subchannels. */
@@ -87,7 +101,7 @@ css_subchannel_release(struct device *dev)
 	struct subchannel *sch;
 
 	sch = to_subchannel(dev);
-	if (!cio_is_console(sch->irq))
+	if (!cio_is_console(sch->schid))
 		kfree(sch);
 }
 
@@ -99,7 +113,7 @@ css_register_subchannel(struct subchannel *sch)
 	int ret;
 
 	/* Initialize the subchannel structure */
-	sch->dev.parent = &css_bus_device;
+	sch->dev.parent = &css[0]->device;
 	sch->dev.bus = &css_bus_type;
 	sch->dev.release = &css_subchannel_release;
 	
@@ -114,12 +128,12 @@ css_register_subchannel(struct subchannel *sch)
 }
 
 int
-css_probe_device(int irq)
+css_probe_device(struct subchannel_id schid)
 {
 	int ret;
 	struct subchannel *sch;
 
-	sch = css_alloc_subchannel(irq);
+	sch = css_alloc_subchannel(schid);
 	if (IS_ERR(sch))
 		return PTR_ERR(sch);
 	ret = css_register_subchannel(sch);
@@ -132,26 +146,26 @@ static int
 check_subchannel(struct device * dev, void * data)
 {
 	struct subchannel *sch;
-	int irq = (unsigned long)data;
+	struct subchannel_id *schid = data;
 
 	sch = to_subchannel(dev);
-	return (sch->irq == irq);
+	return schid_equal(&sch->schid, schid);
 }
 
 struct subchannel *
-get_subchannel_by_schid(int irq)
+get_subchannel_by_schid(struct subchannel_id schid)
 {
 	struct device *dev;
 
 	dev = bus_find_device(&css_bus_type, NULL,
-			      (void *)(unsigned long)irq, check_subchannel);
+			      (void *)&schid, check_subchannel);
 
 	return dev ? to_subchannel(dev) : NULL;
 }
 
 
 static inline int
-css_get_subchannel_status(struct subchannel *sch, int schid)
+css_get_subchannel_status(struct subchannel *sch, struct subchannel_id schid)
 {
 	struct schib schib;
 	int cc;
@@ -170,13 +184,13 @@ css_get_subchannel_status(struct subchannel *sch, int schid)
 }
 	
 static int
-css_evaluate_subchannel(int irq, int slow)
+css_evaluate_subchannel(struct subchannel_id schid, int slow)
 {
 	int event, ret, disc;
 	struct subchannel *sch;
 	unsigned long flags;
 
-	sch = get_subchannel_by_schid(irq);
+	sch = get_subchannel_by_schid(schid);
 	disc = sch ? device_is_disconnected(sch) : 0;
 	if (disc && slow) {
 		if (sch)
@@ -194,9 +208,10 @@ css_evaluate_subchannel(int irq, int slow)
 			put_device(&sch->dev);
 		return -EAGAIN; /* Will be done on the slow path. */
 	}
-	event = css_get_subchannel_status(sch, irq);
-	CIO_MSG_EVENT(4, "Evaluating schid %04x, event %d, %s, %s path.\n",
-		      irq, event, sch?(disc?"disconnected":"normal"):"unknown",
+	event = css_get_subchannel_status(sch, schid);
+	CIO_MSG_EVENT(4, "Evaluating schid 0.%x.%04x, event %d, %s, %s path.\n",
+		      schid.ssid, schid.sch_no, event,
+		      sch?(disc?"disconnected":"normal"):"unknown",
 		      slow?"slow":"fast");
 	switch (event) {
 	case CIO_NO_PATH:
@@ -253,7 +268,7 @@ css_evaluate_subchannel(int irq, int slow)
 			sch->schib.pmcw.intparm = 0;
 			cio_modify(sch);
 			put_device(&sch->dev);
-			ret = css_probe_device(irq);
+			ret = css_probe_device(schid);
 		} else {
 			/*
 			 * We can't immediately deregister the disconnected
@@ -272,7 +287,7 @@ css_evaluate_subchannel(int irq, int slow)
 			device_trigger_reprobe(sch);
 			spin_unlock_irqrestore(&sch->lock, flags);
 		}
-		ret = sch ? 0 : css_probe_device(irq);
+		ret = sch ? 0 : css_probe_device(schid);
 		break;
 	default:
 		BUG();
@@ -281,28 +296,15 @@ css_evaluate_subchannel(int irq, int slow)
 	return ret;
 }
 
-static void
-css_rescan_devices(void)
+static int
+css_rescan_devices(struct subchannel_id schid, void *data)
 {
-	int irq, ret;
-
-	for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) {
-		ret = css_evaluate_subchannel(irq, 1);
-		/* No more memory. It doesn't make sense to continue. No
-		 * panic because this can happen in midflight and just
-		 * because we can't use a new device is no reason to crash
-		 * the system. */
-		if (ret == -ENOMEM)
-			break;
-		/* -ENXIO indicates that there are no more subchannels. */
-		if (ret == -ENXIO)
-			break;
-	}
+	return css_evaluate_subchannel(schid, 1);
 }
 
 struct slow_subchannel {
 	struct list_head slow_list;
-	unsigned long schid;
+	struct subchannel_id schid;
 };
 
 static LIST_HEAD(slow_subchannels_head);
@@ -315,7 +317,7 @@ css_trigger_slow_path(void)
 
 	if (need_rescan) {
 		need_rescan = 0;
-		css_rescan_devices();
+		for_each_subchannel(css_rescan_devices, NULL);
 		return;
 	}
 
@@ -354,23 +356,31 @@ css_reiterate_subchannels(void)
  * Called from the machine check handler for subchannel report words.
  */
 int
-css_process_crw(int irq)
+css_process_crw(int rsid1, int rsid2)
 {
 	int ret;
+	struct subchannel_id mchk_schid;
 
-	CIO_CRW_EVENT(2, "source is subchannel %04X\n", irq);
+	CIO_CRW_EVENT(2, "source is subchannel %04X, subsystem id %x\n",
+		      rsid1, rsid2);
 
 	if (need_rescan)
 		/* We need to iterate all subchannels anyway. */
 		return -EAGAIN;
+
+	init_subchannel_id(&mchk_schid);
+	mchk_schid.sch_no = rsid1;
+	if (rsid2 != 0)
+		mchk_schid.ssid = (rsid2 >> 8) & 3;
+
 	/* 
 	 * Since we are always presented with IPI in the CRW, we have to
 	 * use stsch() to find out if the subchannel in question has come
 	 * or gone.
 	 */
-	ret = css_evaluate_subchannel(irq, 0);
+	ret = css_evaluate_subchannel(mchk_schid, 0);
 	if (ret == -EAGAIN) {
-		if (css_enqueue_subchannel_slow(irq)) {
+		if (css_enqueue_subchannel_slow(mchk_schid)) {
 			css_clear_subchannel_slow_list();
 			need_rescan = 1;
 		}
@@ -378,22 +388,83 @@ css_process_crw(int irq)
 	return ret;
 }
 
-static void __init
-css_generate_pgid(void)
+static int __init
+__init_channel_subsystem(struct subchannel_id schid, void *data)
 {
-	/* Let's build our path group ID here. */
-	if (css_characteristics_avail && css_general_characteristics.mcss)
-		global_pgid.cpu_addr = 0x8000;
+	struct subchannel *sch;
+	int ret;
+
+	if (cio_is_console(schid))
+		sch = cio_get_console_subchannel();
 	else {
+		sch = css_alloc_subchannel(schid);
+		if (IS_ERR(sch))
+			ret = PTR_ERR(sch);
+		else
+			ret = 0;
+		switch (ret) {
+		case 0:
+			break;
+		case -ENOMEM:
+			panic("Out of memory in init_channel_subsystem\n");
+		/* -ENXIO: no more subchannels. */
+		case -ENXIO:
+			return ret;
+		default:
+			return 0;
+		}
+	}
+	/*
+	 * We register ALL valid subchannels in ioinfo, even those
+	 * that have been present before init_channel_subsystem.
+	 * These subchannels can't have been registered yet (kmalloc
+	 * not working) so we do it now. This is true e.g. for the
+	 * console subchannel.
+	 */
+	css_register_subchannel(sch);
+	return 0;
+}
+
+static void __init
+css_generate_pgid(struct channel_subsystem *css, u32 tod_high)
+{
+	if (css_characteristics_avail && css_general_characteristics.mcss) {
+		css->global_pgid.pgid_high.ext_cssid.version = 0x80;
+		css->global_pgid.pgid_high.ext_cssid.cssid = css->cssid;
+	} else {
 #ifdef CONFIG_SMP
-		global_pgid.cpu_addr = hard_smp_processor_id();
+		css->global_pgid.pgid_high.cpu_addr = hard_smp_processor_id();
 #else
-		global_pgid.cpu_addr = 0;
+		css->global_pgid.pgid_high.cpu_addr = 0;
 #endif
 	}
-	global_pgid.cpu_id = ((cpuid_t *) __LC_CPUID)->ident;
-	global_pgid.cpu_model = ((cpuid_t *) __LC_CPUID)->machine;
-	global_pgid.tod_high = (__u32) (get_clock() >> 32);
+	css->global_pgid.cpu_id = ((cpuid_t *) __LC_CPUID)->ident;
+	css->global_pgid.cpu_model = ((cpuid_t *) __LC_CPUID)->machine;
+	css->global_pgid.tod_high = tod_high;
+
+}
+
+static void
+channel_subsystem_release(struct device *dev)
+{
+	struct channel_subsystem *css;
+
+	css = to_css(dev);
+	kfree(css);
+}
+
+static inline void __init
+setup_css(int nr)
+{
+	u32 tod_high;
+
+	memset(css[nr], 0, sizeof(struct channel_subsystem));
+	css[nr]->valid = 1;
+	css[nr]->cssid = nr;
+	sprintf(css[nr]->device.bus_id, "css%x", nr);
+	css[nr]->device.release = channel_subsystem_release;
+	tod_high = (u32) (get_clock() >> 32);
+	css_generate_pgid(css[nr], tod_high);
 }
 
 /*
@@ -404,53 +475,50 @@ css_generate_pgid(void)
 static int __init
 init_channel_subsystem (void)
 {
-	int ret, irq;
+	int ret, i;
 
 	if (chsc_determine_css_characteristics() == 0)
 		css_characteristics_avail = 1;
 
-	css_generate_pgid();
-
 	if ((ret = bus_register(&css_bus_type)))
 		goto out;
-	if ((ret = device_register (&css_bus_device)))
-		goto out_bus;
 
+	/* Try to enable MSS. */
+	ret = chsc_enable_facility(CHSC_SDA_OC_MSS);
+	switch (ret) {
+	case 0: /* Success. */
+		max_ssid = __MAX_SSID;
+		break;
+	case -ENOMEM:
+		goto out_bus;
+	default:
+		max_ssid = 0;
+	}
+	/* Setup css structure. */
+	for (i = 0; i <= __MAX_CSSID; i++) {
+		css[i] = kmalloc(sizeof(struct channel_subsystem), GFP_KERNEL);
+		if (!css[i]) {
+			ret = -ENOMEM;
+			goto out_unregister;
+		}
+		setup_css(i);
+		ret = device_register(&css[i]->device);
+		if (ret)
+			goto out_free;
+	}
 	css_init_done = 1;
 
 	ctl_set_bit(6, 28);
 
-	for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) {
-		struct subchannel *sch;
-
-		if (cio_is_console(irq))
-			sch = cio_get_console_subchannel();
-		else {
-			sch = css_alloc_subchannel(irq);
-			if (IS_ERR(sch))
-				ret = PTR_ERR(sch);
-			else
-				ret = 0;
-			if (ret == -ENOMEM)
-				panic("Out of memory in "
-				      "init_channel_subsystem\n");
-			/* -ENXIO: no more subchannels. */
-			if (ret == -ENXIO)
-				break;
-			if (ret)
-				continue;
-		}
-		/*
-		 * We register ALL valid subchannels in ioinfo, even those
-		 * that have been present before init_channel_subsystem.
-		 * These subchannels can't have been registered yet (kmalloc
-		 * not working) so we do it now. This is true e.g. for the
-		 * console subchannel.
-		 */
-		css_register_subchannel(sch);
-	}
+	for_each_subchannel(__init_channel_subsystem, NULL);
 	return 0;
-
+out_free:
+	kfree(css[i]);
+out_unregister:
+	while (i > 0) {
+		i--;
+		device_unregister(&css[i]->device);
+	}
 out_bus:
 	bus_unregister(&css_bus_type);
 out:
@@ -481,47 +549,8 @@ struct bus_type css_bus_type = {
 
 subsys_initcall(init_channel_subsystem);
 
-/*
- * Register root devices for some drivers. The release function must not be
- * in the device drivers, so we do it here.
- */
-static void
-s390_root_dev_release(struct device *dev)
-{
-	kfree(dev);
-}
-
-struct device *
-s390_root_dev_register(const char *name)
-{
-	struct device *dev;
-	int ret;
-
-	if (!strlen(name))
-		return ERR_PTR(-EINVAL);
-	dev = kmalloc(sizeof(struct device), GFP_KERNEL);
-	if (!dev)
-		return ERR_PTR(-ENOMEM);
-	memset(dev, 0, sizeof(struct device));
-	strncpy(dev->bus_id, name, min(strlen(name), (size_t)BUS_ID_SIZE));
-	dev->release = s390_root_dev_release;
-	ret = device_register(dev);
-	if (ret) {
-		kfree(dev);
-		return ERR_PTR(ret);
-	}
-	return dev;
-}
-
-void
-s390_root_dev_unregister(struct device *dev)
-{
-	if (dev)
-		device_unregister(dev);
-}
-
 int
-css_enqueue_subchannel_slow(unsigned long schid)
+css_enqueue_subchannel_slow(struct subchannel_id schid)
 {
 	struct slow_subchannel *new_slow_sch;
 	unsigned long flags;
@@ -564,6 +593,4 @@ css_slow_subchannels_exist(void)
 
 MODULE_LICENSE("GPL");
 EXPORT_SYMBOL(css_bus_type);
-EXPORT_SYMBOL(s390_root_dev_register);
-EXPORT_SYMBOL(s390_root_dev_unregister);
 EXPORT_SYMBOL_GPL(css_characteristics_avail);
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h
index 2004a6c49388..251ebd7a7d3a 100644
--- a/drivers/s390/cio/css.h
+++ b/drivers/s390/cio/css.h
@@ -6,6 +6,8 @@
 
 #include <asm/cio.h>
 
+#include "schid.h"
+
 /*
  * path grouping stuff
  */
@@ -33,19 +35,25 @@ struct path_state {
 	__u8  resvd  : 3;	/* reserved */
 } __attribute__ ((packed));
 
+struct extended_cssid {
+	u8 version;
+	u8 cssid;
+} __attribute__ ((packed));
+
 struct pgid {
 	union {
 		__u8 fc;   	/* SPID function code */
 		struct path_state ps;	/* SNID path state */
 	} inf;
-	__u32 cpu_addr	: 16;	/* CPU address */
+	union {
+		__u32 cpu_addr	: 16;	/* CPU address */
+		struct extended_cssid ext_cssid;
+	} pgid_high;
 	__u32 cpu_id	: 24;	/* CPU identification */
 	__u32 cpu_model : 16;	/* CPU model */
 	__u32 tod_high;		/* high word TOD clock */
 } __attribute__ ((packed));
 
-extern struct pgid global_pgid;
-
 #define MAX_CIWS 8
 
 /*
@@ -68,7 +76,8 @@ struct ccw_device_private {
 	atomic_t onoff;
 	unsigned long registered;
 	__u16 devno;		/* device number */
-	__u16 irq;		/* subchannel number */
+	__u16 sch_no;		/* subchannel number */
+	__u8 ssid;              /* subchannel set id */
 	__u8 imask;		/* lpm mask for SNID/SID/SPGID */
 	int iretry;		/* retry counter SNID/SID/SPGID */
 	struct {
@@ -121,15 +130,27 @@ struct css_driver {
 extern struct bus_type css_bus_type;
 extern struct css_driver io_subchannel_driver;
 
-int css_probe_device(int irq);
-extern struct subchannel * get_subchannel_by_schid(int irq);
-extern unsigned int highest_subchannel;
+extern int css_probe_device(struct subchannel_id);
+extern struct subchannel * get_subchannel_by_schid(struct subchannel_id);
 extern int css_init_done;
-
-#define __MAX_SUBCHANNELS 65536
+extern int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *);
+
+#define __MAX_SUBCHANNEL 65535
+#define __MAX_SSID 3
+#define __MAX_CHPID 255
+#define __MAX_CSSID 0
+
+struct channel_subsystem {
+	u8 cssid;
+	int valid;
+	struct channel_path *chps[__MAX_CHPID];
+	struct device device;
+	struct pgid global_pgid;
+};
+#define to_css(dev) container_of(dev, struct channel_subsystem, device)
 
 extern struct bus_type css_bus_type;
-extern struct device css_bus_device;
+extern struct channel_subsystem *css[];
 
 /* Some helper functions for disconnected state. */
 int device_is_disconnected(struct subchannel *);
@@ -144,7 +165,7 @@ void device_set_waiting(struct subchannel *);
 void device_kill_pending_timer(struct subchannel *);
 
 /* Helper functions to build lists for the slow path. */
-int css_enqueue_subchannel_slow(unsigned long schid);
+extern int css_enqueue_subchannel_slow(struct subchannel_id schid);
 void css_walk_subchannel_slow_list(void (*fn)(unsigned long));
 void css_clear_subchannel_slow_list(void);
 int css_slow_subchannels_exist(void);
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 811c9d150637..fa3e4c0a2536 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/device.c
  *  bus driver for ccw devices
- *   $Revision: 1.131 $
+ *   $Revision: 1.137 $
  *
  *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
  *			 IBM Corporation
@@ -59,7 +59,7 @@ ccw_bus_match (struct device * dev, struct device_driver * drv)
  * Heavily modeled on pci and usb hotplug.
  */
 static int
-ccw_hotplug (struct device *dev, char **envp, int num_envp,
+ccw_uevent (struct device *dev, char **envp, int num_envp,
 	     char *buffer, int buffer_size)
 {
 	struct ccw_device *cdev = to_ccwdev(dev);
@@ -110,7 +110,7 @@ ccw_hotplug (struct device *dev, char **envp, int num_envp,
 struct bus_type ccw_bus_type = {
 	.name  = "ccw",
 	.match = &ccw_bus_match,
-	.hotplug = &ccw_hotplug,
+	.uevent = &ccw_uevent,
 };
 
 static int io_subchannel_probe (struct device *);
@@ -374,7 +374,7 @@ online_store (struct device *dev, struct device_attribute *attr, const char *buf
 	int i, force, ret;
 	char *tmp;
 
-	if (atomic_compare_and_swap(0, 1, &cdev->private->onoff))
+	if (atomic_cmpxchg(&cdev->private->onoff, 0, 1) != 0)
 		return -EAGAIN;
 
 	if (cdev->drv && !try_module_get(cdev->drv->owner)) {
@@ -535,7 +535,8 @@ ccw_device_register(struct ccw_device *cdev)
 }
 
 struct match_data {
-	unsigned int  devno;
+	unsigned int devno;
+	unsigned int ssid;
 	struct ccw_device * sibling;
 };
 
@@ -548,6 +549,7 @@ match_devno(struct device * dev, void * data)
 	cdev = to_ccwdev(dev);
 	if ((cdev->private->state == DEV_STATE_DISCONNECTED) &&
 	    (cdev->private->devno == d->devno) &&
+	    (cdev->private->ssid == d->ssid) &&
 	    (cdev != d->sibling)) {
 		cdev->private->state = DEV_STATE_NOT_OPER;
 		return 1;
@@ -556,11 +558,13 @@ match_devno(struct device * dev, void * data)
 }
 
 static struct ccw_device *
-get_disc_ccwdev_by_devno(unsigned int devno, struct ccw_device *sibling)
+get_disc_ccwdev_by_devno(unsigned int devno, unsigned int ssid,
+			 struct ccw_device *sibling)
 {
 	struct device *dev;
 	struct match_data data = {
-		.devno  = devno,
+		.devno   = devno,
+		.ssid    = ssid,
 		.sibling = sibling,
 	};
 
@@ -616,13 +620,13 @@ ccw_device_do_unreg_rereg(void *data)
 
 		need_rename = 1;
 		other_cdev = get_disc_ccwdev_by_devno(sch->schib.pmcw.dev,
-						      cdev);
+						      sch->schid.ssid, cdev);
 		if (other_cdev) {
 			struct subchannel *other_sch;
 
 			other_sch = to_subchannel(other_cdev->dev.parent);
 			if (get_device(&other_sch->dev)) {
-				stsch(other_sch->irq, &other_sch->schib);
+				stsch(other_sch->schid, &other_sch->schib);
 				if (other_sch->schib.pmcw.dnv) {
 					other_sch->schib.pmcw.intparm = 0;
 					cio_modify(other_sch);
@@ -639,8 +643,8 @@ ccw_device_do_unreg_rereg(void *data)
 	if (test_and_clear_bit(1, &cdev->private->registered))
 		device_del(&cdev->dev);
 	if (need_rename)
-		snprintf (cdev->dev.bus_id, BUS_ID_SIZE, "0.0.%04x",
-			  sch->schib.pmcw.dev);
+		snprintf (cdev->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x",
+			  sch->schid.ssid, sch->schib.pmcw.dev);
 	PREPARE_WORK(&cdev->private->kick_work,
 		     ccw_device_add_changed, (void *)cdev);
 	queue_work(ccw_device_work, &cdev->private->kick_work);
@@ -769,18 +773,20 @@ io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch)
 	sch->dev.driver_data = cdev;
 	sch->driver = &io_subchannel_driver;
 	cdev->ccwlock = &sch->lock;
+
 	/* Init private data. */
 	priv = cdev->private;
 	priv->devno = sch->schib.pmcw.dev;
-	priv->irq = sch->irq;
+	priv->ssid = sch->schid.ssid;
+	priv->sch_no = sch->schid.sch_no;
 	priv->state = DEV_STATE_NOT_OPER;
 	INIT_LIST_HEAD(&priv->cmb_list);
 	init_waitqueue_head(&priv->wait_q);
 	init_timer(&priv->timer);
 
 	/* Set an initial name for the device. */
-	snprintf (cdev->dev.bus_id, BUS_ID_SIZE, "0.0.%04x",
-		  sch->schib.pmcw.dev);
+	snprintf (cdev->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x",
+		  sch->schid.ssid, sch->schib.pmcw.dev);
 
 	/* Increase counter of devices currently in recognition. */
 	atomic_inc(&ccw_device_init_count);
@@ -951,7 +957,7 @@ io_subchannel_shutdown(struct device *dev)
 	sch = to_subchannel(dev);
 	cdev = dev->driver_data;
 
-	if (cio_is_console(sch->irq))
+	if (cio_is_console(sch->schid))
 		return;
 	if (!sch->schib.pmcw.ena)
 		/* Nothing to do. */
@@ -986,10 +992,6 @@ ccw_device_console_enable (struct ccw_device *cdev, struct subchannel *sch)
 	cdev->dev = (struct device) {
 		.parent = &sch->dev,
 	};
-	/* Initialize the subchannel structure */
-	sch->dev.parent = &css_bus_device;
-	sch->dev.bus = &css_bus_type;
-
 	rc = io_subchannel_recog(cdev, sch);
 	if (rc)
 		return rc;
@@ -1146,6 +1148,16 @@ ccw_driver_unregister (struct ccw_driver *cdriver)
 	driver_unregister(&cdriver->driver);
 }
 
+/* Helper func for qdio. */
+struct subchannel_id
+ccw_device_get_subchannel_id(struct ccw_device *cdev)
+{
+	struct subchannel *sch;
+
+	sch = to_subchannel(cdev->dev.parent);
+	return sch->schid;
+}
+
 MODULE_LICENSE("GPL");
 EXPORT_SYMBOL(ccw_device_set_online);
 EXPORT_SYMBOL(ccw_device_set_offline);
@@ -1155,3 +1167,4 @@ EXPORT_SYMBOL(get_ccwdev_by_busid);
 EXPORT_SYMBOL(ccw_bus_type);
 EXPORT_SYMBOL(ccw_device_work);
 EXPORT_SYMBOL(ccw_device_notify_work);
+EXPORT_SYMBOL_GPL(ccw_device_get_subchannel_id);
diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h
index a3aa056d7245..11587ebb7289 100644
--- a/drivers/s390/cio/device.h
+++ b/drivers/s390/cio/device.h
@@ -110,6 +110,7 @@ int ccw_device_stlck(struct ccw_device *);
 
 /* qdio needs this. */
 void ccw_device_set_timeout(struct ccw_device *, int);
+extern struct subchannel_id ccw_device_get_subchannel_id(struct ccw_device *);
 
 void retry_set_schib(struct ccw_device *cdev);
 #endif
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index c1c89f4fd4e3..23d12b65e5fa 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -133,7 +133,7 @@ ccw_device_cancel_halt_clear(struct ccw_device *cdev)
 	int ret;
 
 	sch = to_subchannel(cdev->dev.parent);
-	ret = stsch(sch->irq, &sch->schib);
+	ret = stsch(sch->schid, &sch->schib);
 	if (ret || !sch->schib.pmcw.dnv)
 		return -ENODEV; 
 	if (!sch->schib.pmcw.ena || sch->schib.scsw.actl == 0)
@@ -231,7 +231,7 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
 	 * through ssch() and the path information is up to date.
 	 */
 	old_lpm = sch->lpm;
-	stsch(sch->irq, &sch->schib);
+	stsch(sch->schid, &sch->schib);
 	sch->lpm = sch->schib.pmcw.pim &
 		sch->schib.pmcw.pam &
 		sch->schib.pmcw.pom &
@@ -257,8 +257,9 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
 	switch (state) {
 	case DEV_STATE_NOT_OPER:
 		CIO_DEBUG(KERN_WARNING, 2,
-			  "SenseID : unknown device %04x on subchannel %04x\n",
-			  cdev->private->devno, sch->irq);
+			  "SenseID : unknown device %04x on subchannel "
+			  "0.%x.%04x\n", cdev->private->devno,
+			  sch->schid.ssid, sch->schid.sch_no);
 		break;
 	case DEV_STATE_OFFLINE:
 		if (cdev->private->state == DEV_STATE_DISCONNECTED_SENSE_ID) {
@@ -282,16 +283,18 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
 			return;
 		}
 		/* Issue device info message. */
-		CIO_DEBUG(KERN_INFO, 2, "SenseID : device %04x reports: "
+		CIO_DEBUG(KERN_INFO, 2, "SenseID : device 0.%x.%04x reports: "
 			  "CU  Type/Mod = %04X/%02X, Dev Type/Mod = "
-			  "%04X/%02X\n", cdev->private->devno,
+			  "%04X/%02X\n",
+			  cdev->private->ssid, cdev->private->devno,
 			  cdev->id.cu_type, cdev->id.cu_model,
 			  cdev->id.dev_type, cdev->id.dev_model);
 		break;
 	case DEV_STATE_BOXED:
 		CIO_DEBUG(KERN_WARNING, 2,
-			  "SenseID : boxed device %04x on subchannel %04x\n",
-			  cdev->private->devno, sch->irq);
+			  "SenseID : boxed device %04x on subchannel "
+			  "0.%x.%04x\n", cdev->private->devno,
+			  sch->schid.ssid, sch->schid.sch_no);
 		break;
 	}
 	cdev->private->state = state;
@@ -359,7 +362,7 @@ ccw_device_done(struct ccw_device *cdev, int state)
 	if (state == DEV_STATE_BOXED)
 		CIO_DEBUG(KERN_WARNING, 2,
 			  "Boxed device %04x on subchannel %04x\n",
-			  cdev->private->devno, sch->irq);
+			  cdev->private->devno, sch->schid.sch_no);
 
 	if (cdev->private->flags.donotify) {
 		cdev->private->flags.donotify = 0;
@@ -592,7 +595,7 @@ ccw_device_offline(struct ccw_device *cdev)
 	struct subchannel *sch;
 
 	sch = to_subchannel(cdev->dev.parent);
-	if (stsch(sch->irq, &sch->schib) || !sch->schib.pmcw.dnv)
+	if (stsch(sch->schid, &sch->schib) || !sch->schib.pmcw.dnv)
 		return -ENODEV;
 	if (cdev->private->state != DEV_STATE_ONLINE) {
 		if (sch->schib.scsw.actl != 0)
@@ -711,7 +714,7 @@ ccw_device_online_verify(struct ccw_device *cdev, enum dev_event dev_event)
 	 * Since we might not just be coming from an interrupt from the
 	 * subchannel we have to update the schib.
 	 */
-	stsch(sch->irq, &sch->schib);
+	stsch(sch->schid, &sch->schib);
 
 	if (sch->schib.scsw.actl != 0 ||
 	    (cdev->private->irb.scsw.stctl & SCSW_STCTL_STATUS_PEND)) {
@@ -923,7 +926,7 @@ ccw_device_wait4io_irq(struct ccw_device *cdev, enum dev_event dev_event)
 
 	/* Iff device is idle, reset timeout. */
 	sch = to_subchannel(cdev->dev.parent);
-	if (!stsch(sch->irq, &sch->schib))
+	if (!stsch(sch->schid, &sch->schib))
 		if (sch->schib.scsw.actl == 0)
 			ccw_device_set_timeout(cdev, 0);
 	/* Call the handler. */
@@ -1035,7 +1038,7 @@ device_trigger_reprobe(struct subchannel *sch)
 		return;
 
 	/* Update some values. */
-	if (stsch(sch->irq, &sch->schib))
+	if (stsch(sch->schid, &sch->schib))
 		return;
 
 	/*
diff --git a/drivers/s390/cio/device_id.c b/drivers/s390/cio/device_id.c
index 0e68fb511dc9..04ceba343db8 100644
--- a/drivers/s390/cio/device_id.c
+++ b/drivers/s390/cio/device_id.c
@@ -27,7 +27,7 @@
 /*
  * diag210 is used under VM to get information about a virtual device
  */
-#ifdef CONFIG_ARCH_S390X
+#ifdef CONFIG_64BIT
 int
 diag210(struct diag210 * addr)
 {
@@ -256,16 +256,17 @@ ccw_device_check_sense_id(struct ccw_device *cdev)
 		 *     sense id information. So, for intervention required,
 		 *     we use the "whack it until it talks" strategy...
 		 */
-		CIO_MSG_EVENT(2, "SenseID : device %04x on Subchannel %04x "
-			      "reports cmd reject\n",
-			      cdev->private->devno, sch->irq);
+		CIO_MSG_EVENT(2, "SenseID : device %04x on Subchannel "
+			      "0.%x.%04x reports cmd reject\n",
+			      cdev->private->devno, sch->schid.ssid,
+			      sch->schid.sch_no);
 		return -EOPNOTSUPP;
 	}
 	if (irb->esw.esw0.erw.cons) {
-		CIO_MSG_EVENT(2, "SenseID : UC on dev %04x, "
+		CIO_MSG_EVENT(2, "SenseID : UC on dev 0.%x.%04x, "
 			      "lpum %02X, cnt %02d, sns :"
 			      " %02X%02X%02X%02X %02X%02X%02X%02X ...\n",
-			      cdev->private->devno,
+			      cdev->private->ssid, cdev->private->devno,
 			      irb->esw.esw0.sublog.lpum,
 			      irb->esw.esw0.erw.scnt,
 			      irb->ecw[0], irb->ecw[1],
@@ -277,16 +278,17 @@ ccw_device_check_sense_id(struct ccw_device *cdev)
 	if (irb->scsw.cc == 3) {
 		if ((sch->orb.lpm &
 		     sch->schib.pmcw.pim & sch->schib.pmcw.pam) != 0)
-			CIO_MSG_EVENT(2, "SenseID : path %02X for device %04x on"
-				      " subchannel %04x is 'not operational'\n",
-				      sch->orb.lpm, cdev->private->devno,
-				      sch->irq);
+			CIO_MSG_EVENT(2, "SenseID : path %02X for device %04x "
+				      "on subchannel 0.%x.%04x is "
+				      "'not operational'\n", sch->orb.lpm,
+				      cdev->private->devno, sch->schid.ssid,
+				      sch->schid.sch_no);
 		return -EACCES;
 	}
 	/* Hmm, whatever happened, try again. */
 	CIO_MSG_EVENT(2, "SenseID : start_IO() for device %04x on "
-		      "subchannel %04x returns status %02X%02X\n",
-		      cdev->private->devno, sch->irq,
+		      "subchannel 0.%x.%04x returns status %02X%02X\n",
+		      cdev->private->devno, sch->schid.ssid, sch->schid.sch_no,
 		      irb->scsw.dstat, irb->scsw.cstat);
 	return -EAGAIN;
 }
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
index 85a3026e6900..143b6c25a4e6 100644
--- a/drivers/s390/cio/device_ops.c
+++ b/drivers/s390/cio/device_ops.c
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/device_ops.c
  *
- *   $Revision: 1.57 $
+ *   $Revision: 1.58 $
  *
  *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
  *			 IBM Corporation
@@ -570,7 +570,7 @@ ccw_device_get_chp_desc(struct ccw_device *cdev, int chp_no)
 int
 _ccw_device_get_subchannel_number(struct ccw_device *cdev)
 {
-	return cdev->private->irq;
+	return cdev->private->sch_no;
 }
 
 int
diff --git a/drivers/s390/cio/device_pgid.c b/drivers/s390/cio/device_pgid.c
index 0adac8a67331..052832d03d38 100644
--- a/drivers/s390/cio/device_pgid.c
+++ b/drivers/s390/cio/device_pgid.c
@@ -22,6 +22,7 @@
 #include "cio_debug.h"
 #include "css.h"
 #include "device.h"
+#include "ioasm.h"
 
 /*
  * Start Sense Path Group ID helper function. Used in ccw_device_recog
@@ -56,10 +57,10 @@ __ccw_device_sense_pgid_start(struct ccw_device *cdev)
 			if (ret != -EACCES)
 				return ret;
 			CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel "
-				      "%04x, lpm %02X, became 'not "
+				      "0.%x.%04x, lpm %02X, became 'not "
 				      "operational'\n",
-				      cdev->private->devno, sch->irq,
-				      cdev->private->imask);
+				      cdev->private->devno, sch->schid.ssid,
+				      sch->schid.sch_no, cdev->private->imask);
 
 		}
 		cdev->private->imask >>= 1;
@@ -105,10 +106,10 @@ __ccw_device_check_sense_pgid(struct ccw_device *cdev)
 		return -EOPNOTSUPP;
 	}
 	if (irb->esw.esw0.erw.cons) {
-		CIO_MSG_EVENT(2, "SNID - device %04x, unit check, "
+		CIO_MSG_EVENT(2, "SNID - device 0.%x.%04x, unit check, "
 			      "lpum %02X, cnt %02d, sns : "
 			      "%02X%02X%02X%02X %02X%02X%02X%02X ...\n",
-			      cdev->private->devno,
+			      cdev->private->ssid, cdev->private->devno,
 			      irb->esw.esw0.sublog.lpum,
 			      irb->esw.esw0.erw.scnt,
 			      irb->ecw[0], irb->ecw[1],
@@ -118,15 +119,17 @@ __ccw_device_check_sense_pgid(struct ccw_device *cdev)
 		return -EAGAIN;
 	}
 	if (irb->scsw.cc == 3) {
-		CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel "
-			      "%04x, lpm %02X, became 'not operational'\n",
-			      cdev->private->devno, sch->irq, sch->orb.lpm);
+		CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel 0.%x.%04x,"
+			      " lpm %02X, became 'not operational'\n",
+			      cdev->private->devno, sch->schid.ssid,
+			      sch->schid.sch_no, sch->orb.lpm);
 		return -EACCES;
 	}
 	if (cdev->private->pgid.inf.ps.state2 == SNID_STATE2_RESVD_ELSE) {
-		CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel %04x "
+		CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel 0.%x.%04x "
 			      "is reserved by someone else\n",
-			      cdev->private->devno, sch->irq);
+			      cdev->private->devno, sch->schid.ssid,
+			      sch->schid.sch_no);
 		return -EUSERS;
 	}
 	return 0;
@@ -162,7 +165,7 @@ ccw_device_sense_pgid_irq(struct ccw_device *cdev, enum dev_event dev_event)
 	/* 0, -ETIME, -EOPNOTSUPP, -EAGAIN, -EACCES or -EUSERS */
 	case 0:			/* Sense Path Group ID successful. */
 		if (cdev->private->pgid.inf.ps.state1 == SNID_STATE1_RESET)
-			memcpy(&cdev->private->pgid, &global_pgid,
+			memcpy(&cdev->private->pgid, &css[0]->global_pgid,
 			       sizeof(struct pgid));
 		ccw_device_sense_pgid_done(cdev, 0);
 		break;
@@ -235,8 +238,9 @@ __ccw_device_do_pgid(struct ccw_device *cdev, __u8 func)
 	sch->lpm &= ~cdev->private->imask;
 	sch->vpm &= ~cdev->private->imask;
 	CIO_MSG_EVENT(2, "SPID - Device %04x on Subchannel "
-		      "%04x, lpm %02X, became 'not operational'\n",
-		      cdev->private->devno, sch->irq, cdev->private->imask);
+		      "0.%x.%04x, lpm %02X, became 'not operational'\n",
+		      cdev->private->devno, sch->schid.ssid,
+		      sch->schid.sch_no, cdev->private->imask);
 	return ret;
 }
 
@@ -258,8 +262,10 @@ __ccw_device_check_pgid(struct ccw_device *cdev)
 		if (irb->ecw[0] & SNS0_CMD_REJECT)
 			return -EOPNOTSUPP;
 		/* Hmm, whatever happened, try again. */
-		CIO_MSG_EVENT(2, "SPID - device %04x, unit check, cnt %02d, "
+		CIO_MSG_EVENT(2, "SPID - device 0.%x.%04x, unit check, "
+			      "cnt %02d, "
 			      "sns : %02X%02X%02X%02X %02X%02X%02X%02X ...\n",
+			      cdev->private->ssid,
 			      cdev->private->devno, irb->esw.esw0.erw.scnt,
 			      irb->ecw[0], irb->ecw[1],
 			      irb->ecw[2], irb->ecw[3],
@@ -268,10 +274,10 @@ __ccw_device_check_pgid(struct ccw_device *cdev)
 		return -EAGAIN;
 	}
 	if (irb->scsw.cc == 3) {
-		CIO_MSG_EVENT(2, "SPID - Device %04x on Subchannel "
-			      "%04x, lpm %02X, became 'not operational'\n",
-			      cdev->private->devno, sch->irq,
-			      cdev->private->imask);
+		CIO_MSG_EVENT(2, "SPID - Device %04x on Subchannel 0.%x.%04x,"
+			      " lpm %02X, became 'not operational'\n",
+			      cdev->private->devno, sch->schid.ssid,
+			      sch->schid.sch_no, cdev->private->imask);
 		return -EACCES;
 	}
 	return 0;
@@ -364,8 +370,22 @@ ccw_device_verify_irq(struct ccw_device *cdev, enum dev_event dev_event)
 void
 ccw_device_verify_start(struct ccw_device *cdev)
 {
+	struct subchannel *sch = to_subchannel(cdev->dev.parent);
+
 	cdev->private->flags.pgid_single = 0;
 	cdev->private->iretry = 5;
+	/*
+	 * Update sch->lpm with current values to catch paths becoming
+	 * available again.
+	 */
+	if (stsch(sch->schid, &sch->schib)) {
+		ccw_device_verify_done(cdev, -ENODEV);
+		return;
+	}
+	sch->lpm = sch->schib.pmcw.pim &
+		sch->schib.pmcw.pam &
+		sch->schib.pmcw.pom &
+		sch->opm;
 	__ccw_device_verify_start(cdev);
 }
 
diff --git a/drivers/s390/cio/device_status.c b/drivers/s390/cio/device_status.c
index 12a24d4331a2..db09c209098b 100644
--- a/drivers/s390/cio/device_status.c
+++ b/drivers/s390/cio/device_status.c
@@ -36,15 +36,16 @@ ccw_device_msg_control_check(struct ccw_device *cdev, struct irb *irb)
 		
 	CIO_MSG_EVENT(0, "Channel-Check or Interface-Control-Check "
 		      "received"
-		      " ... device %04X on subchannel %04X, dev_stat "
+		      " ... device %04x on subchannel 0.%x.%04x, dev_stat "
 		      ": %02X sch_stat : %02X\n",
-		      cdev->private->devno, cdev->private->irq,
+		      cdev->private->devno, cdev->private->ssid,
+		      cdev->private->sch_no,
 		      irb->scsw.dstat, irb->scsw.cstat);
 
 	if (irb->scsw.cc != 3) {
 		char dbf_text[15];
 
-		sprintf(dbf_text, "chk%x", cdev->private->irq);
+		sprintf(dbf_text, "chk%x", cdev->private->sch_no);
 		CIO_TRACE_EVENT(0, dbf_text);
 		CIO_HEX_EVENT(0, irb, sizeof (struct irb));
 	}
@@ -59,10 +60,11 @@ ccw_device_path_notoper(struct ccw_device *cdev)
 	struct subchannel *sch;
 
 	sch = to_subchannel(cdev->dev.parent);
-	stsch (sch->irq, &sch->schib);
+	stsch (sch->schid, &sch->schib);
 
-	CIO_MSG_EVENT(0, "%s(%04x) - path(s) %02x are "
-		      "not operational \n", __FUNCTION__, sch->irq,
+	CIO_MSG_EVENT(0, "%s(0.%x.%04x) - path(s) %02x are "
+		      "not operational \n", __FUNCTION__,
+		      sch->schid.ssid, sch->schid.sch_no,
 		      sch->schib.pmcw.pnom);
 
 	sch->lpm &= ~sch->schib.pmcw.pnom;
diff --git a/drivers/s390/cio/ioasm.h b/drivers/s390/cio/ioasm.h
index 45480a2bc4c0..95a9462f9a91 100644
--- a/drivers/s390/cio/ioasm.h
+++ b/drivers/s390/cio/ioasm.h
@@ -1,12 +1,13 @@
 #ifndef S390_CIO_IOASM_H
 #define S390_CIO_IOASM_H
 
+#include "schid.h"
+
 /*
  * TPI info structure
  */
 struct tpi_info {
-	__u32 reserved1	 : 16;	 /* reserved 0x00000001 */
-	__u32 irq	 : 16;	 /* aka. subchannel number */
+	struct subchannel_id schid;
 	__u32 intparm;		 /* interruption parameter */
 	__u32 adapter_IO : 1;
 	__u32 reserved2	 : 1;
@@ -21,7 +22,8 @@ struct tpi_info {
  * Some S390 specific IO instructions as inline
  */
 
-static inline int stsch(int irq, volatile struct schib *addr)
+static inline int stsch(struct subchannel_id schid,
+			    volatile struct schib *addr)
 {
 	int ccode;
 
@@ -31,12 +33,42 @@ static inline int stsch(int irq, volatile struct schib *addr)
 		"   ipm	  %0\n"
 		"   srl	  %0,28"
 		: "=d" (ccode)
-		: "d" (irq | 0x10000), "a" (addr)
+		: "d" (schid), "a" (addr), "m" (*addr)
+		: "cc", "1" );
+	return ccode;
+}
+
+static inline int stsch_err(struct subchannel_id schid,
+				volatile struct schib *addr)
+{
+	int ccode;
+
+	__asm__ __volatile__(
+		"    lhi  %0,%3\n"
+		"    lr	  1,%1\n"
+		"    stsch 0(%2)\n"
+		"0:  ipm  %0\n"
+		"    srl  %0,28\n"
+		"1:\n"
+#ifdef CONFIG_64BIT
+		".section __ex_table,\"a\"\n"
+		"   .align 8\n"
+		"   .quad 0b,1b\n"
+		".previous"
+#else
+		".section __ex_table,\"a\"\n"
+		"   .align 4\n"
+		"   .long 0b,1b\n"
+		".previous"
+#endif
+		: "=&d" (ccode)
+		: "d" (schid), "a" (addr), "K" (-EIO), "m" (*addr)
 		: "cc", "1" );
 	return ccode;
 }
 
-static inline int msch(int irq, volatile struct schib *addr)
+static inline int msch(struct subchannel_id schid,
+			   volatile struct schib *addr)
 {
 	int ccode;
 
@@ -46,12 +78,13 @@ static inline int msch(int irq, volatile struct schib *addr)
 		"   ipm	  %0\n"
 		"   srl	  %0,28"
 		: "=d" (ccode)
-		: "d" (irq | 0x10000L), "a" (addr)
+		: "d" (schid), "a" (addr), "m" (*addr)
 		: "cc", "1" );
 	return ccode;
 }
 
-static inline int msch_err(int irq, volatile struct schib *addr)
+static inline int msch_err(struct subchannel_id schid,
+			       volatile struct schib *addr)
 {
 	int ccode;
 
@@ -62,7 +95,7 @@ static inline int msch_err(int irq, volatile struct schib *addr)
 		"0:  ipm  %0\n"
 		"    srl  %0,28\n"
 		"1:\n"
-#ifdef CONFIG_ARCH_S390X
+#ifdef CONFIG_64BIT
 		".section __ex_table,\"a\"\n"
 		"   .align 8\n"
 		"   .quad 0b,1b\n"
@@ -74,12 +107,13 @@ static inline int msch_err(int irq, volatile struct schib *addr)
 		".previous"
 #endif
 		: "=&d" (ccode)
-		: "d" (irq | 0x10000L), "a" (addr), "K" (-EIO)
+		: "d" (schid), "a" (addr), "K" (-EIO), "m" (*addr)
 		: "cc", "1" );
 	return ccode;
 }
 
-static inline int tsch(int irq, volatile struct irb *addr)
+static inline int tsch(struct subchannel_id schid,
+			   volatile struct irb *addr)
 {
 	int ccode;
 
@@ -89,7 +123,7 @@ static inline int tsch(int irq, volatile struct irb *addr)
 		"   ipm	  %0\n"
 		"   srl	  %0,28"
 		: "=d" (ccode)
-		: "d" (irq | 0x10000L), "a" (addr)
+		: "d" (schid), "a" (addr), "m" (*addr)
 		: "cc", "1" );
 	return ccode;
 }
@@ -103,12 +137,13 @@ static inline int tpi( volatile struct tpi_info *addr)
 		"   ipm	  %0\n"
 		"   srl	  %0,28"
 		: "=d" (ccode)
-		: "a" (addr)
+		: "a" (addr), "m" (*addr)
 		: "cc", "1" );
 	return ccode;
 }
 
-static inline int ssch(int irq, volatile struct orb *addr)
+static inline int ssch(struct subchannel_id schid,
+			   volatile struct orb *addr)
 {
 	int ccode;
 
@@ -118,12 +153,12 @@ static inline int ssch(int irq, volatile struct orb *addr)
 		"   ipm	  %0\n"
 		"   srl	  %0,28"
 		: "=d" (ccode)
-		: "d" (irq | 0x10000L), "a" (addr)
+		: "d" (schid), "a" (addr), "m" (*addr)
 		: "cc", "1" );
 	return ccode;
 }
 
-static inline int rsch(int irq)
+static inline int rsch(struct subchannel_id schid)
 {
 	int ccode;
 
@@ -133,12 +168,12 @@ static inline int rsch(int irq)
 		"   ipm	  %0\n"
 		"   srl	  %0,28"
 		: "=d" (ccode)
-		: "d" (irq | 0x10000L)
+		: "d" (schid)
 		: "cc", "1" );
 	return ccode;
 }
 
-static inline int csch(int irq)
+static inline int csch(struct subchannel_id schid)
 {
 	int ccode;
 
@@ -148,12 +183,12 @@ static inline int csch(int irq)
 		"   ipm	  %0\n"
 		"   srl	  %0,28"
 		: "=d" (ccode)
-		: "d" (irq | 0x10000L)
+		: "d" (schid)
 		: "cc", "1" );
 	return ccode;
 }
 
-static inline int hsch(int irq)
+static inline int hsch(struct subchannel_id schid)
 {
 	int ccode;
 
@@ -163,12 +198,12 @@ static inline int hsch(int irq)
 		"   ipm	  %0\n"
 		"   srl	  %0,28"
 		: "=d" (ccode)
-		: "d" (irq | 0x10000L)
+		: "d" (schid)
 		: "cc", "1" );
 	return ccode;
 }
 
-static inline int xsch(int irq)
+static inline int xsch(struct subchannel_id schid)
 {
 	int ccode;
 
@@ -178,21 +213,22 @@ static inline int xsch(int irq)
 		"   ipm	  %0\n"
 		"   srl	  %0,28"
 		: "=d" (ccode)
-		: "d" (irq | 0x10000L)
+		: "d" (schid)
 		: "cc", "1" );
 	return ccode;
 }
 
 static inline int chsc(void *chsc_area)
 {
+	typedef struct { char _[4096]; } addr_type;
 	int cc;
 
 	__asm__ __volatile__ (
-		".insn	rre,0xb25f0000,%1,0	\n\t"
+		".insn	rre,0xb25f0000,%2,0	\n\t"
 		"ipm	%0	\n\t"
 		"srl	%0,28	\n\t"
-		: "=d" (cc)
-		: "d" (chsc_area)
+		: "=d" (cc), "=m" (*(addr_type *) chsc_area)
+		: "d" (chsc_area), "m" (*(addr_type *) chsc_area)
 		: "cc" );
 
 	return cc;
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
index eb39218b925e..30a836ffc31f 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -56,7 +56,7 @@
 #include "ioasm.h"
 #include "chsc.h"
 
-#define VERSION_QDIO_C "$Revision: 1.108 $"
+#define VERSION_QDIO_C "$Revision: 1.114 $"
 
 /****************** MODULE PARAMETER VARIABLES ********************/
 MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>");
@@ -76,6 +76,7 @@ static struct qdio_perf_stats perf_stats;
 #endif /* QDIO_PERFORMANCE_STATS */
 
 static int hydra_thinints;
+static int is_passthrough = 0;
 static int omit_svs;
 
 static int indicator_used[INDICATORS_PER_CACHELINE];
@@ -136,12 +137,126 @@ qdio_release_q(struct qdio_q *q)
 	atomic_dec(&q->use_count);
 }
 
-static volatile inline void 
-qdio_set_slsb(volatile char *slsb, unsigned char value)
+/*check ccq  */
+static inline int
+qdio_check_ccq(struct qdio_q *q, unsigned int ccq)
+{
+	char dbf_text[15];
+
+	if (ccq == 0 || ccq == 32 || ccq == 96)
+		return 0;
+	if (ccq == 97)
+		return 1;
+	/*notify devices immediately*/
+	sprintf(dbf_text,"%d", ccq);
+	QDIO_DBF_TEXT2(1,trace,dbf_text);
+	return -EIO;
+}
+/* EQBS: extract buffer states */
+static inline int
+qdio_do_eqbs(struct qdio_q *q, unsigned char *state,
+	     unsigned int *start, unsigned int *cnt)
+{
+	struct qdio_irq *irq;
+	unsigned int tmp_cnt, q_no, ccq;
+	int rc ;
+	char dbf_text[15];
+
+	ccq = 0;
+	tmp_cnt = *cnt;
+	irq = (struct qdio_irq*)q->irq_ptr;
+	q_no = q->q_no;
+	if(!q->is_input_q)
+		q_no += irq->no_input_qs;
+	ccq = do_eqbs(irq->sch_token, state, q_no, start, cnt);
+	rc = qdio_check_ccq(q, ccq);
+	if (rc < 0) {
+                QDIO_DBF_TEXT2(1,trace,"eqberr");
+                sprintf(dbf_text,"%2x,%2x,%d,%d",tmp_cnt, *cnt, ccq, q_no);
+                QDIO_DBF_TEXT2(1,trace,dbf_text);
+		q->handler(q->cdev,QDIO_STATUS_ACTIVATE_CHECK_CONDITION|
+				QDIO_STATUS_LOOK_FOR_ERROR,
+				0, 0, 0, -1, -1, q->int_parm);
+		return 0;
+	}
+	return (tmp_cnt - *cnt);
+}
+
+/* SQBS: set buffer states */
+static inline int
+qdio_do_sqbs(struct qdio_q *q, unsigned char state,
+	     unsigned int *start, unsigned int *cnt)
 {
-	xchg((char*)slsb,value);
+	struct qdio_irq *irq;
+	unsigned int tmp_cnt, q_no, ccq;
+	int rc;
+	char dbf_text[15];
+
+	ccq = 0;
+	tmp_cnt = *cnt;
+	irq = (struct qdio_irq*)q->irq_ptr;
+	q_no = q->q_no;
+	if(!q->is_input_q)
+		q_no += irq->no_input_qs;
+	ccq = do_sqbs(irq->sch_token, state, q_no, start, cnt);
+	rc = qdio_check_ccq(q, ccq);
+	if (rc < 0) {
+                QDIO_DBF_TEXT3(1,trace,"sqberr");
+                sprintf(dbf_text,"%2x,%2x,%d,%d",tmp_cnt,*cnt,ccq,q_no);
+                QDIO_DBF_TEXT3(1,trace,dbf_text);
+		q->handler(q->cdev,QDIO_STATUS_ACTIVATE_CHECK_CONDITION|
+				QDIO_STATUS_LOOK_FOR_ERROR,
+				0, 0, 0, -1, -1, q->int_parm);
+		return 0;
+	}
+	return (tmp_cnt - *cnt);
 }
 
+static inline int
+qdio_set_slsb(struct qdio_q *q, unsigned int *bufno,
+	      unsigned char state, unsigned int *count)
+{
+	volatile char *slsb;
+	struct qdio_irq *irq;
+
+	irq = (struct qdio_irq*)q->irq_ptr;
+	if (!irq->is_qebsm) {
+		slsb = (char *)&q->slsb.acc.val[(*bufno)];
+		xchg(slsb, state);
+		return 1;
+	}
+	return qdio_do_sqbs(q, state, bufno, count);
+}
+
+#ifdef CONFIG_QDIO_DEBUG
+static inline void
+qdio_trace_slsb(struct qdio_q *q)
+{
+	if (q->queue_type==QDIO_TRACE_QTYPE) {
+		if (q->is_input_q)
+			QDIO_DBF_HEX2(0,slsb_in,&q->slsb,
+				      QDIO_MAX_BUFFERS_PER_Q);
+		else
+			QDIO_DBF_HEX2(0,slsb_out,&q->slsb,
+				      QDIO_MAX_BUFFERS_PER_Q);
+	}
+}
+#endif
+
+static inline int
+set_slsb(struct qdio_q *q, unsigned int *bufno,
+	 unsigned char state, unsigned int *count)
+{
+	int rc;
+#ifdef CONFIG_QDIO_DEBUG
+	qdio_trace_slsb(q);
+#endif
+	rc = qdio_set_slsb(q, bufno, state, count);
+#ifdef CONFIG_QDIO_DEBUG
+	qdio_trace_slsb(q);
+#endif
+	return rc;
+}
 static inline int 
 qdio_siga_sync(struct qdio_q *q, unsigned int gpr2,
 	       unsigned int gpr3)
@@ -155,7 +270,7 @@ qdio_siga_sync(struct qdio_q *q, unsigned int gpr2,
 	perf_stats.siga_syncs++;
 #endif /* QDIO_PERFORMANCE_STATS */
 
-	cc = do_siga_sync(q->irq, gpr2, gpr3);
+	cc = do_siga_sync(q->schid, gpr2, gpr3);
 	if (cc)
 		QDIO_DBF_HEX3(0,trace,&cc,sizeof(int*));
 
@@ -170,6 +285,23 @@ qdio_siga_sync_q(struct qdio_q *q)
 	return qdio_siga_sync(q, q->mask, 0);
 }
 
+static int
+__do_siga_output(struct qdio_q *q, unsigned int *busy_bit)
+{
+       struct qdio_irq *irq;
+       unsigned int fc = 0;
+       unsigned long schid;
+
+       irq = (struct qdio_irq *) q->irq_ptr;
+       if (!irq->is_qebsm)
+	       schid = *((u32 *)&q->schid);
+       else {
+	       schid = irq->sch_token;
+	       fc |= 0x80;
+       }
+       return do_siga_output(schid, q->mask, busy_bit, fc);
+}
+
 /* 
  * returns QDIO_SIGA_ERROR_ACCESS_EXCEPTION as cc, when SIGA returns
  * an access exception 
@@ -189,7 +321,7 @@ qdio_siga_output(struct qdio_q *q)
 	QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
 
 	for (;;) {
-		cc = do_siga_output(q->irq, q->mask, &busy_bit);
+		cc = __do_siga_output(q, &busy_bit);
 //QDIO_PRINT_ERR("cc=%x, busy=%x\n",cc,busy_bit);
 		if ((cc==2) && (busy_bit) && (q->is_iqdio_q)) {
 			if (!start_time) 
@@ -221,7 +353,7 @@ qdio_siga_input(struct qdio_q *q)
 	perf_stats.siga_ins++;
 #endif /* QDIO_PERFORMANCE_STATS */
 
-	cc = do_siga_input(q->irq, q->mask);
+	cc = do_siga_input(q->schid, q->mask);
 	
 	if (cc)
 		QDIO_DBF_HEX3(0,trace,&cc,sizeof(int*));
@@ -230,7 +362,7 @@ qdio_siga_input(struct qdio_q *q)
 }
 
 /* locked by the locks in qdio_activate and qdio_cleanup */
-static __u32 volatile *
+static __u32 *
 qdio_get_indicator(void)
 {
 	int i;
@@ -258,7 +390,7 @@ qdio_put_indicator(__u32 *addr)
 		atomic_dec(&spare_indicator_usecount);
 }
 
-static inline volatile void 
+static inline void
 tiqdio_clear_summary_bit(__u32 *location)
 {
 	QDIO_DBF_TEXT5(0,trace,"clrsummb");
@@ -267,7 +399,7 @@ tiqdio_clear_summary_bit(__u32 *location)
 	xchg(location,0);
 }
 
-static inline volatile void
+static inline  void
 tiqdio_set_summary_bit(__u32 *location)
 {
 	QDIO_DBF_TEXT5(0,trace,"setsummb");
@@ -336,7 +468,9 @@ static inline int
 qdio_stop_polling(struct qdio_q *q)
 {
 #ifdef QDIO_USE_PROCESSING_STATE
-	int gsf;
+       unsigned int tmp, gsf, count = 1;
+       unsigned char state = 0;
+       struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr;
 
 	if (!atomic_swap(&q->polling,0)) 
 		return 1;
@@ -348,17 +482,22 @@ qdio_stop_polling(struct qdio_q *q)
 	if (!q->is_input_q)
 		return 1;
 
-	gsf=GET_SAVED_FRONTIER(q);
-	set_slsb(&q->slsb.acc.val[(gsf+QDIO_MAX_BUFFERS_PER_Q-1)&
-				  (QDIO_MAX_BUFFERS_PER_Q-1)],
-		 SLSB_P_INPUT_NOT_INIT);
+       tmp = gsf = GET_SAVED_FRONTIER(q);
+       tmp = ((tmp + QDIO_MAX_BUFFERS_PER_Q-1) & (QDIO_MAX_BUFFERS_PER_Q-1) );
+       set_slsb(q, &tmp, SLSB_P_INPUT_NOT_INIT, &count);
+
 	/* 
 	 * we don't issue this SYNC_MEMORY, as we trust Rick T and
 	 * moreover will not use the PROCESSING state under VM, so
 	 * q->polling was 0 anyway
 	 */
 	/*SYNC_MEMORY;*/
-	if (q->slsb.acc.val[gsf]!=SLSB_P_INPUT_PRIMED)
+       if (irq->is_qebsm) {
+               count = 1;
+               qdio_do_eqbs(q, &state, &gsf, &count);
+       } else
+               state = q->slsb.acc.val[gsf];
+       if (state != SLSB_P_INPUT_PRIMED)
 		return 1;
 	/* 
 	 * set our summary bit again, as otherwise there is a
@@ -431,18 +570,136 @@ tiqdio_clear_global_summary(void)
 
 
 /************************* OUTBOUND ROUTINES *******************************/
+static int
+qdio_qebsm_get_outbound_buffer_frontier(struct qdio_q *q)
+{
+        struct qdio_irq *irq;
+        unsigned char state;
+        unsigned int cnt, count, ftc;
+
+        irq = (struct qdio_irq *) q->irq_ptr;
+        if ((!q->is_iqdio_q) && (!q->hydra_gives_outbound_pcis))
+                SYNC_MEMORY;
+
+        ftc = q->first_to_check;
+        count = qdio_min(atomic_read(&q->number_of_buffers_used),
+                        (QDIO_MAX_BUFFERS_PER_Q-1));
+        if (count == 0)
+                return q->first_to_check;
+        cnt = qdio_do_eqbs(q, &state, &ftc, &count);
+        if (cnt == 0)
+                return q->first_to_check;
+        switch (state) {
+        case SLSB_P_OUTPUT_ERROR:
+                QDIO_DBF_TEXT3(0,trace,"outperr");
+                atomic_sub(cnt , &q->number_of_buffers_used);
+                if (q->qdio_error)
+                        q->error_status_flags |=
+                                QDIO_STATUS_MORE_THAN_ONE_QDIO_ERROR;
+                q->qdio_error = SLSB_P_OUTPUT_ERROR;
+                q->error_status_flags |= QDIO_STATUS_LOOK_FOR_ERROR;
+                q->first_to_check = ftc;
+                break;
+        case SLSB_P_OUTPUT_EMPTY:
+                QDIO_DBF_TEXT5(0,trace,"outpempt");
+                atomic_sub(cnt, &q->number_of_buffers_used);
+                q->first_to_check = ftc;
+                break;
+        case SLSB_CU_OUTPUT_PRIMED:
+                /* all buffers primed */
+                QDIO_DBF_TEXT5(0,trace,"outpprim");
+                break;
+        default:
+                break;
+        }
+        QDIO_DBF_HEX4(0,trace,&q->first_to_check,sizeof(int));
+        return q->first_to_check;
+}
+
+static int
+qdio_qebsm_get_inbound_buffer_frontier(struct qdio_q *q)
+{
+        struct qdio_irq *irq;
+        unsigned char state;
+        int tmp, ftc, count, cnt;
+        char dbf_text[15];
+
+
+        irq = (struct qdio_irq *) q->irq_ptr;
+        ftc = q->first_to_check;
+        count = qdio_min(atomic_read(&q->number_of_buffers_used),
+                        (QDIO_MAX_BUFFERS_PER_Q-1));
+        if (count == 0)
+                 return q->first_to_check;
+        cnt = qdio_do_eqbs(q, &state, &ftc, &count);
+        if (cnt == 0)
+                 return q->first_to_check;
+        switch (state) {
+        case SLSB_P_INPUT_ERROR :
+#ifdef CONFIG_QDIO_DEBUG
+                QDIO_DBF_TEXT3(1,trace,"inperr");
+                sprintf(dbf_text,"%2x,%2x",ftc,count);
+                QDIO_DBF_TEXT3(1,trace,dbf_text);
+#endif /* CONFIG_QDIO_DEBUG */
+                if (q->qdio_error)
+                        q->error_status_flags |=
+                                QDIO_STATUS_MORE_THAN_ONE_QDIO_ERROR;
+                q->qdio_error = SLSB_P_INPUT_ERROR;
+                q->error_status_flags |= QDIO_STATUS_LOOK_FOR_ERROR;
+                atomic_sub(cnt, &q->number_of_buffers_used);
+                q->first_to_check = ftc;
+                break;
+        case SLSB_P_INPUT_PRIMED :
+                QDIO_DBF_TEXT3(0,trace,"inptprim");
+                sprintf(dbf_text,"%2x,%2x",ftc,count);
+                QDIO_DBF_TEXT3(1,trace,dbf_text);
+                tmp = 0;
+                ftc = q->first_to_check;
+#ifdef QDIO_USE_PROCESSING_STATE
+		if (cnt > 1) {
+			cnt -= 1;
+			tmp = set_slsb(q, &ftc, SLSB_P_INPUT_NOT_INIT, &cnt);
+			if (!tmp)
+				break;
+		}
+		cnt = 1;
+		tmp += set_slsb(q, &ftc,
+			       SLSB_P_INPUT_PROCESSING, &cnt);
+		atomic_set(&q->polling, 1);
+#else
+                tmp = set_slsb(q, &ftc, SLSB_P_INPUT_NOT_INIT, &cnt);
+#endif
+                atomic_sub(tmp, &q->number_of_buffers_used);
+                q->first_to_check = ftc;
+                break;
+        case SLSB_CU_INPUT_EMPTY:
+        case SLSB_P_INPUT_NOT_INIT:
+        case SLSB_P_INPUT_PROCESSING:
+                QDIO_DBF_TEXT5(0,trace,"inpnipro");
+                break;
+        default:
+                break;
+        }
+        QDIO_DBF_HEX4(0,trace,&q->first_to_check,sizeof(int));
+        return q->first_to_check;
+}
 
 static inline int
 qdio_get_outbound_buffer_frontier(struct qdio_q *q)
 {
-	int f,f_mod_no;
-	volatile char *slsb;
-	int first_not_to_check;
+	struct qdio_irq *irq;
+        volatile char *slsb;
+        unsigned int count = 1;
+        int first_not_to_check, f, f_mod_no;
 	char dbf_text[15];
 
 	QDIO_DBF_TEXT4(0,trace,"getobfro");
 	QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
 
+	irq = (struct qdio_irq *) q->irq_ptr;
+	if (irq->is_qebsm)
+		return qdio_qebsm_get_outbound_buffer_frontier(q);
+
 	slsb=&q->slsb.acc.val[0];
 	f_mod_no=f=q->first_to_check;
 	/* 
@@ -484,7 +741,7 @@ check_next:
 		QDIO_DBF_HEX2(1,sbal,q->sbal[f_mod_no],256);
 
 		/* kind of process the buffer */
-		set_slsb(&q->slsb.acc.val[f_mod_no], SLSB_P_OUTPUT_NOT_INIT);
+		set_slsb(q, &f_mod_no, SLSB_P_OUTPUT_NOT_INIT, &count);
 
 		/* 
 		 * we increment the frontier, as this buffer
@@ -597,48 +854,48 @@ qdio_kick_outbound_q(struct qdio_q *q)
 
 	result=qdio_siga_output(q);
 
-		switch (result) {
-		case 0:
-			/* went smooth this time, reset timestamp */
+	switch (result) {
+	case 0:
+		/* went smooth this time, reset timestamp */
 #ifdef CONFIG_QDIO_DEBUG
-			QDIO_DBF_TEXT3(0,trace,"cc2reslv");
-			sprintf(dbf_text,"%4x%2x%2x",q->irq,q->q_no,
-				atomic_read(&q->busy_siga_counter));
-			QDIO_DBF_TEXT3(0,trace,dbf_text);
+		QDIO_DBF_TEXT3(0,trace,"cc2reslv");
+		sprintf(dbf_text,"%4x%2x%2x",q->schid.sch_no,q->q_no,
+			atomic_read(&q->busy_siga_counter));
+		QDIO_DBF_TEXT3(0,trace,dbf_text);
 #endif /* CONFIG_QDIO_DEBUG */
-			q->timing.busy_start=0;
+		q->timing.busy_start=0;
+		break;
+	case (2|QDIO_SIGA_ERROR_B_BIT_SET):
+		/* cc=2 and busy bit: */
+		atomic_inc(&q->busy_siga_counter);
+
+		/* if the last siga was successful, save
+		 * timestamp here */
+		if (!q->timing.busy_start)
+			q->timing.busy_start=NOW;
+
+		/* if we're in time, don't touch error_status_flags
+		 * and siga_error */
+		if (NOW-q->timing.busy_start<QDIO_BUSY_BIT_GIVE_UP) {
+			qdio_mark_q(q);
 			break;
-		case (2|QDIO_SIGA_ERROR_B_BIT_SET):
-			/* cc=2 and busy bit: */
-			atomic_inc(&q->busy_siga_counter);
-
-			/* if the last siga was successful, save
-			 * timestamp here */
-			if (!q->timing.busy_start)
-				q->timing.busy_start=NOW;
-
-			/* if we're in time, don't touch error_status_flags
-			 * and siga_error */
-			if (NOW-q->timing.busy_start<QDIO_BUSY_BIT_GIVE_UP) {
-				qdio_mark_q(q);
-				break;
-			}
-			QDIO_DBF_TEXT2(0,trace,"cc2REPRT");
+		}
+		QDIO_DBF_TEXT2(0,trace,"cc2REPRT");
 #ifdef CONFIG_QDIO_DEBUG
-			sprintf(dbf_text,"%4x%2x%2x",q->irq,q->q_no,
-				atomic_read(&q->busy_siga_counter));
-			QDIO_DBF_TEXT3(0,trace,dbf_text);
+		sprintf(dbf_text,"%4x%2x%2x",q->schid.sch_no,q->q_no,
+			atomic_read(&q->busy_siga_counter));
+		QDIO_DBF_TEXT3(0,trace,dbf_text);
 #endif /* CONFIG_QDIO_DEBUG */
-			/* else fallthrough and report error */
-		default:
-			/* for plain cc=1, 2 or 3: */
-			if (q->siga_error)
-				q->error_status_flags|=
-					QDIO_STATUS_MORE_THAN_ONE_SIGA_ERROR;
+		/* else fallthrough and report error */
+	default:
+		/* for plain cc=1, 2 or 3: */
+		if (q->siga_error)
 			q->error_status_flags|=
-				QDIO_STATUS_LOOK_FOR_ERROR;
-			q->siga_error=result;
-		}
+				QDIO_STATUS_MORE_THAN_ONE_SIGA_ERROR;
+		q->error_status_flags|=
+			QDIO_STATUS_LOOK_FOR_ERROR;
+		q->siga_error=result;
+	}
 }
 
 static inline void
@@ -743,8 +1000,10 @@ qdio_outbound_processing(struct qdio_q *q)
 static inline int
 qdio_get_inbound_buffer_frontier(struct qdio_q *q)
 {
+	struct qdio_irq *irq;
 	int f,f_mod_no;
 	volatile char *slsb;
+	unsigned int count = 1;
 	int first_not_to_check;
 #ifdef CONFIG_QDIO_DEBUG
 	char dbf_text[15];
@@ -756,6 +1015,10 @@ qdio_get_inbound_buffer_frontier(struct qdio_q *q)
 	QDIO_DBF_TEXT4(0,trace,"getibfro");
 	QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
 
+	irq = (struct qdio_irq *) q->irq_ptr;
+	if (irq->is_qebsm)
+		return qdio_qebsm_get_inbound_buffer_frontier(q);
+
 	slsb=&q->slsb.acc.val[0];
 	f_mod_no=f=q->first_to_check;
 	/* 
@@ -792,19 +1055,19 @@ check_next:
 		 * kill VM in terms of CP overhead 
 		 */
 		if (q->siga_sync) {
-			set_slsb(&slsb[f_mod_no],SLSB_P_INPUT_NOT_INIT);
+			set_slsb(q, &f_mod_no, SLSB_P_INPUT_NOT_INIT, &count);
 		} else {
 			/* set the previous buffer to NOT_INIT. The current
 			 * buffer will be set to PROCESSING at the end of
 			 * this function to avoid further interrupts. */
 			if (last_position>=0)
-				set_slsb(&slsb[last_position],
-					 SLSB_P_INPUT_NOT_INIT);
+				set_slsb(q, &last_position,
+					 SLSB_P_INPUT_NOT_INIT, &count);
 			atomic_set(&q->polling,1);
 			last_position=f_mod_no;
 		}
 #else /* QDIO_USE_PROCESSING_STATE */
-		set_slsb(&slsb[f_mod_no],SLSB_P_INPUT_NOT_INIT);
+		set_slsb(q, &f_mod_no, SLSB_P_INPUT_NOT_INIT, &count);
 #endif /* QDIO_USE_PROCESSING_STATE */
 		/* 
 		 * not needed, as the inbound queue will be synced on the next
@@ -829,7 +1092,7 @@ check_next:
 		QDIO_DBF_HEX2(1,sbal,q->sbal[f_mod_no],256);
 
 		/* kind of process the buffer */
-		set_slsb(&slsb[f_mod_no],SLSB_P_INPUT_NOT_INIT);
+		set_slsb(q, &f_mod_no, SLSB_P_INPUT_NOT_INIT, &count);
 
 		if (q->qdio_error)
 			q->error_status_flags|=
@@ -857,7 +1120,7 @@ out:
 
 #ifdef QDIO_USE_PROCESSING_STATE
 	if (last_position>=0)
-		set_slsb(&slsb[last_position],SLSB_P_INPUT_PROCESSING);
+		set_slsb(q, &last_position, SLSB_P_INPUT_NOT_INIT, &count);
 #endif /* QDIO_USE_PROCESSING_STATE */
 
 	QDIO_DBF_HEX4(0,trace,&q->first_to_check,sizeof(int));
@@ -902,6 +1165,10 @@ static inline int
 tiqdio_is_inbound_q_done(struct qdio_q *q)
 {
 	int no_used;
+	unsigned int start_buf, count;
+	unsigned char state = 0;
+	struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr;
+
 #ifdef CONFIG_QDIO_DEBUG
 	char dbf_text[15];
 #endif
@@ -927,8 +1194,13 @@ tiqdio_is_inbound_q_done(struct qdio_q *q)
 	if (!q->siga_sync)
 		/* we'll check for more primed buffers in qeth_stop_polling */
 		return 0;
-
-	if (q->slsb.acc.val[q->first_to_check]!=SLSB_P_INPUT_PRIMED)
+	if (irq->is_qebsm) {
+		count = 1;
+		start_buf = q->first_to_check;
+		qdio_do_eqbs(q, &state, &start_buf, &count);
+	} else
+		state = q->slsb.acc.val[q->first_to_check];
+	if (state != SLSB_P_INPUT_PRIMED)
 		/* 
 		 * nothing more to do, if next buffer is not PRIMED.
 		 * note that we did a SYNC_MEMORY before, that there
@@ -955,6 +1227,10 @@ static inline int
 qdio_is_inbound_q_done(struct qdio_q *q)
 {
 	int no_used;
+	unsigned int start_buf, count;
+	unsigned char state = 0;
+	struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr;
+
 #ifdef CONFIG_QDIO_DEBUG
 	char dbf_text[15];
 #endif
@@ -973,8 +1249,13 @@ qdio_is_inbound_q_done(struct qdio_q *q)
 		QDIO_DBF_TEXT4(0,trace,dbf_text);
 		return 1;
 	}
-
-	if (q->slsb.acc.val[q->first_to_check]==SLSB_P_INPUT_PRIMED) {
+	if (irq->is_qebsm) {
+		count = 1;
+		start_buf = q->first_to_check;
+		qdio_do_eqbs(q, &state, &start_buf, &count);
+	} else
+		state = q->slsb.acc.val[q->first_to_check];
+	if (state == SLSB_P_INPUT_PRIMED) {
 		/* we got something to do */
 		QDIO_DBF_TEXT4(0,trace,"inqisntA");
 		QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
@@ -1456,7 +1737,7 @@ qdio_fill_qs(struct qdio_irq *irq_ptr, struct ccw_device *cdev,
 	void *ptr;
 	int available;
 
-	sprintf(dbf_text,"qfqs%4x",cdev->private->irq);
+	sprintf(dbf_text,"qfqs%4x",cdev->private->sch_no);
 	QDIO_DBF_TEXT0(0,setup,dbf_text);
 	for (i=0;i<no_input_qs;i++) {
 		q=irq_ptr->input_qs[i];
@@ -1476,7 +1757,7 @@ qdio_fill_qs(struct qdio_irq *irq_ptr, struct ccw_device *cdev,
 
                 q->queue_type=q_format;
 		q->int_parm=int_parm;
-		q->irq=irq_ptr->irq;
+		q->schid = irq_ptr->schid;
 		q->irq_ptr = irq_ptr;
 		q->cdev = cdev;
 		q->mask=1<<(31-i);
@@ -1523,11 +1804,11 @@ qdio_fill_qs(struct qdio_irq *irq_ptr, struct ccw_device *cdev,
 		QDIO_DBF_HEX2(0,setup,&ptr,sizeof(void*));
 
 		/* fill in slsb */
-		for (j=0;j<QDIO_MAX_BUFFERS_PER_Q;j++) {
-			set_slsb(&q->slsb.acc.val[j],
-		   		 SLSB_P_INPUT_NOT_INIT);
-/*			q->sbal[j]->element[1].sbalf.i1.key=QDIO_STORAGE_KEY;*/
-		}
+		if (!irq_ptr->is_qebsm) {
+                        unsigned int count = 1;
+                        for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; j++)
+                                set_slsb(q, &j, SLSB_P_INPUT_NOT_INIT, &count);
+                }
 	}
 
 	for (i=0;i<no_output_qs;i++) {
@@ -1549,7 +1830,7 @@ qdio_fill_qs(struct qdio_irq *irq_ptr, struct ccw_device *cdev,
                 q->queue_type=q_format;
 		q->int_parm=int_parm;
 		q->is_input_q=0;
-		q->irq=irq_ptr->irq;
+		q->schid = irq_ptr->schid;
 		q->cdev = cdev;
 		q->irq_ptr = irq_ptr;
 		q->mask=1<<(31-i);
@@ -1584,11 +1865,11 @@ qdio_fill_qs(struct qdio_irq *irq_ptr, struct ccw_device *cdev,
 		QDIO_DBF_HEX2(0,setup,&ptr,sizeof(void*));
 
 		/* fill in slsb */
-		for (j=0;j<QDIO_MAX_BUFFERS_PER_Q;j++) {
-			set_slsb(&q->slsb.acc.val[j],
-		   		 SLSB_P_OUTPUT_NOT_INIT);
-/*			q->sbal[j]->element[1].sbalf.i1.key=QDIO_STORAGE_KEY;*/
-		}
+                if (!irq_ptr->is_qebsm) {
+                        unsigned int count = 1;
+                        for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; j++)
+                                set_slsb(q, &j, SLSB_P_OUTPUT_NOT_INIT, &count);
+                }
 	}
 }
 
@@ -1656,7 +1937,7 @@ qdio_set_state(struct qdio_irq *irq_ptr, enum qdio_irq_states state)
 	char dbf_text[15];
 
 	QDIO_DBF_TEXT5(0,trace,"newstate");
-	sprintf(dbf_text,"%4x%4x",irq_ptr->irq,state);
+	sprintf(dbf_text,"%4x%4x",irq_ptr->schid.sch_no,state);
 	QDIO_DBF_TEXT5(0,trace,dbf_text);
 #endif /* CONFIG_QDIO_DEBUG */
 
@@ -1669,12 +1950,12 @@ qdio_set_state(struct qdio_irq *irq_ptr, enum qdio_irq_states state)
 }
 
 static inline void
-qdio_irq_check_sense(int irq, struct irb *irb)
+qdio_irq_check_sense(struct subchannel_id schid, struct irb *irb)
 {
 	char dbf_text[15];
 
 	if (irb->esw.esw0.erw.cons) {
-		sprintf(dbf_text,"sens%4x",irq);
+		sprintf(dbf_text,"sens%4x",schid.sch_no);
 		QDIO_DBF_TEXT2(1,trace,dbf_text);
 		QDIO_DBF_HEX0(0,sense,irb,QDIO_DBF_SENSE_LEN);
 
@@ -1785,21 +2066,22 @@ qdio_timeout_handler(struct ccw_device *cdev)
 
 	switch (irq_ptr->state) {
 	case QDIO_IRQ_STATE_INACTIVE:
-		QDIO_PRINT_ERR("establish queues on irq %04x: timed out\n",
-			       irq_ptr->irq);
+		QDIO_PRINT_ERR("establish queues on irq 0.%x.%04x: timed out\n",
+			       irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
 		QDIO_DBF_TEXT2(1,setup,"eq:timeo");
 		qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR);
 		break;
 	case QDIO_IRQ_STATE_CLEANUP:
-		QDIO_PRINT_INFO("Did not get interrupt on cleanup, irq=0x%x.\n",
-				irq_ptr->irq);
+		QDIO_PRINT_INFO("Did not get interrupt on cleanup, "
+				"irq=0.%x.%x.\n",
+				irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
 		qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR);
 		break;
 	case QDIO_IRQ_STATE_ESTABLISHED:
 	case QDIO_IRQ_STATE_ACTIVE:
 		/* I/O has been terminated by common I/O layer. */
-		QDIO_PRINT_INFO("Queues on irq %04x killed by cio.\n",
-				irq_ptr->irq);
+		QDIO_PRINT_INFO("Queues on irq 0.%x.%04x killed by cio.\n",
+				irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
 		QDIO_DBF_TEXT2(1, trace, "cio:term");
 		qdio_set_state(irq_ptr, QDIO_IRQ_STATE_STOPPED);
 		if (get_device(&cdev->dev)) {
@@ -1862,7 +2144,7 @@ qdio_handler(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
 		}
 	}
 
-	qdio_irq_check_sense(irq_ptr->irq, irb);
+	qdio_irq_check_sense(irq_ptr->schid, irb);
 
 #ifdef CONFIG_QDIO_DEBUG
 	sprintf(dbf_text, "state:%d", irq_ptr->state);
@@ -1905,7 +2187,7 @@ int
 qdio_synchronize(struct ccw_device *cdev, unsigned int flags,
 		 unsigned int queue_number)
 {
-	int cc;
+	int cc = 0;
 	struct qdio_q *q;
 	struct qdio_irq *irq_ptr;
 	void *ptr;
@@ -1918,7 +2200,7 @@ qdio_synchronize(struct ccw_device *cdev, unsigned int flags,
 		return -ENODEV;
 
 #ifdef CONFIG_QDIO_DEBUG
-	*((int*)(&dbf_text[4])) = irq_ptr->irq;
+	*((int*)(&dbf_text[4])) = irq_ptr->schid.sch_no;
 	QDIO_DBF_HEX4(0,trace,dbf_text,QDIO_DBF_TRACE_LEN);
 	*((int*)(&dbf_text[0]))=flags;
 	*((int*)(&dbf_text[4]))=queue_number;
@@ -1929,12 +2211,14 @@ qdio_synchronize(struct ccw_device *cdev, unsigned int flags,
 		q=irq_ptr->input_qs[queue_number];
 		if (!q)
 			return -EINVAL;
-		cc = do_siga_sync(q->irq, 0, q->mask);
+		if (!(irq_ptr->is_qebsm))
+			cc = do_siga_sync(q->schid, 0, q->mask);
 	} else if (flags&QDIO_FLAG_SYNC_OUTPUT) {
 		q=irq_ptr->output_qs[queue_number];
 		if (!q)
 			return -EINVAL;
-		cc = do_siga_sync(q->irq, q->mask, 0);
+		if (!(irq_ptr->is_qebsm))
+			cc = do_siga_sync(q->schid, q->mask, 0);
 	} else 
 		return -EINVAL;
 
@@ -1945,15 +2229,54 @@ qdio_synchronize(struct ccw_device *cdev, unsigned int flags,
 	return cc;
 }
 
-static unsigned char
-qdio_check_siga_needs(int sch)
+static inline void
+qdio_check_subchannel_qebsm(struct qdio_irq *irq_ptr, unsigned char qdioac,
+			    unsigned long token)
+{
+	struct qdio_q *q;
+	int i;
+	unsigned int count, start_buf;
+	char dbf_text[15];
+
+	/*check if QEBSM is disabled */
+	if (!(irq_ptr->is_qebsm) || !(qdioac & 0x01)) {
+		irq_ptr->is_qebsm  = 0;
+		irq_ptr->sch_token = 0;
+		irq_ptr->qib.rflags &= ~QIB_RFLAGS_ENABLE_QEBSM;
+		QDIO_DBF_TEXT0(0,setup,"noV=V");
+		return;
+	}
+	irq_ptr->sch_token = token;
+	/*input queue*/
+	for (i = 0; i < irq_ptr->no_input_qs;i++) {
+		q = irq_ptr->input_qs[i];
+		count = QDIO_MAX_BUFFERS_PER_Q;
+		start_buf = 0;
+		set_slsb(q, &start_buf, SLSB_P_INPUT_NOT_INIT, &count);
+	}
+	sprintf(dbf_text,"V=V:%2x",irq_ptr->is_qebsm);
+	QDIO_DBF_TEXT0(0,setup,dbf_text);
+	sprintf(dbf_text,"%8lx",irq_ptr->sch_token);
+	QDIO_DBF_TEXT0(0,setup,dbf_text);
+	/*output queue*/
+	for (i = 0; i < irq_ptr->no_output_qs; i++) {
+		q = irq_ptr->output_qs[i];
+		count = QDIO_MAX_BUFFERS_PER_Q;
+		start_buf = 0;
+		set_slsb(q, &start_buf, SLSB_P_OUTPUT_NOT_INIT, &count);
+	}
+}
+
+static void
+qdio_get_ssqd_information(struct qdio_irq *irq_ptr)
 {
 	int result;
 	unsigned char qdioac;
-
 	struct {
 		struct chsc_header request;
-		u16 reserved1;
+		u16 reserved1:10;
+		u16 ssid:2;
+		u16 fmt:4;
 		u16 first_sch;
 		u16 reserved2;
 		u16 last_sch;
@@ -1964,67 +2287,83 @@ qdio_check_siga_needs(int sch)
 		u8  reserved5;
 		u16 sch;
 		u8  qfmt;
-		u8  reserved6;
-		u8  qdioac;
+		u8  parm;
+		u8  qdioac1;
 		u8  sch_class;
 		u8  reserved7;
 		u8  icnt;
 		u8  reserved8;
 		u8  ocnt;
+		u8 reserved9;
+		u8 mbccnt;
+		u16 qdioac2;
+		u64 sch_token;
 	} *ssqd_area;
 
+	QDIO_DBF_TEXT0(0,setup,"getssqd");
+	qdioac = 0;
 	ssqd_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
 	if (!ssqd_area) {
 	        QDIO_PRINT_WARN("Could not get memory for chsc. Using all " \
-				"SIGAs for sch x%x.\n", sch);
-		return CHSC_FLAG_SIGA_INPUT_NECESSARY ||
-			CHSC_FLAG_SIGA_OUTPUT_NECESSARY ||
-			CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */
+				"SIGAs for sch x%x.\n", irq_ptr->schid.sch_no);
+		irq_ptr->qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY ||
+				  CHSC_FLAG_SIGA_OUTPUT_NECESSARY ||
+				  CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */
+		irq_ptr->is_qebsm = 0;
+		irq_ptr->sch_token = 0;
+		irq_ptr->qib.rflags &= ~QIB_RFLAGS_ENABLE_QEBSM;
+		return;
 	}
+
 	ssqd_area->request = (struct chsc_header) {
 		.length = 0x0010,
 		.code   = 0x0024,
 	};
-
-	ssqd_area->first_sch = sch;
-	ssqd_area->last_sch = sch;
-
-	result=chsc(ssqd_area);
+	ssqd_area->first_sch = irq_ptr->schid.sch_no;
+	ssqd_area->last_sch = irq_ptr->schid.sch_no;
+	ssqd_area->ssid = irq_ptr->schid.ssid;
+	result = chsc(ssqd_area);
 
 	if (result) {
 		QDIO_PRINT_WARN("CHSC returned cc %i. Using all " \
-				"SIGAs for sch x%x.\n",
-				result,sch);
+				"SIGAs for sch 0.%x.%x.\n", result,
+				irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
 		qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY ||
 			CHSC_FLAG_SIGA_OUTPUT_NECESSARY ||
 			CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */
+		irq_ptr->is_qebsm  = 0;
 		goto out;
 	}
 
 	if (ssqd_area->response.code != QDIO_CHSC_RESPONSE_CODE_OK) {
 		QDIO_PRINT_WARN("response upon checking SIGA needs " \
-				"is 0x%x. Using all SIGAs for sch x%x.\n",
-				ssqd_area->response.code, sch);
+				"is 0x%x. Using all SIGAs for sch 0.%x.%x.\n",
+				ssqd_area->response.code,
+				irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
 		qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY ||
 			CHSC_FLAG_SIGA_OUTPUT_NECESSARY ||
 			CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */
+		irq_ptr->is_qebsm  = 0;
 		goto out;
 	}
 	if (!(ssqd_area->flags & CHSC_FLAG_QDIO_CAPABILITY) ||
 	    !(ssqd_area->flags & CHSC_FLAG_VALIDITY) ||
-	    (ssqd_area->sch != sch)) {
-		QDIO_PRINT_WARN("huh? problems checking out sch x%x... " \
-				"using all SIGAs.\n",sch);
+	    (ssqd_area->sch != irq_ptr->schid.sch_no)) {
+		QDIO_PRINT_WARN("huh? problems checking out sch 0.%x.%x... " \
+				"using all SIGAs.\n",
+				irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
 		qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY |
 			CHSC_FLAG_SIGA_OUTPUT_NECESSARY |
 			CHSC_FLAG_SIGA_SYNC_NECESSARY; /* worst case */
+		irq_ptr->is_qebsm  = 0;
 		goto out;
 	}
-
-	qdioac = ssqd_area->qdioac;
+	qdioac = ssqd_area->qdioac1;
 out:
+	qdio_check_subchannel_qebsm(irq_ptr, qdioac,
+				    ssqd_area->sch_token);
 	free_page ((unsigned long) ssqd_area);
-	return qdioac;
+	irq_ptr->qdioac = qdioac;
 }
 
 static unsigned int
@@ -2055,6 +2394,13 @@ tiqdio_check_chsc_availability(void)
 	sprintf(dbf_text,"hydrati%1x", hydra_thinints);
 	QDIO_DBF_TEXT0(0,setup,dbf_text);
 
+#ifdef CONFIG_64BIT
+	/* Check for QEBSM support in general (bit 58). */
+	is_passthrough = css_general_characteristics.qebsm;
+#endif
+	sprintf(dbf_text,"cssQBS:%1x", is_passthrough);
+	QDIO_DBF_TEXT0(0,setup,dbf_text);
+
 	/* Check for aif time delay disablement fac (bit 56). If installed,
 	 * omit svs even under lpar (good point by rick again) */
 	omit_svs = css_general_characteristics.aif_tdd;
@@ -2091,7 +2437,7 @@ tiqdio_set_subchannel_ind(struct qdio_irq *irq_ptr, int reset_to_zero)
 		/* set to 0x10000000 to enable
 		 * time delay disablement facility */
 		u32 reserved5;
-		u32 subsystem_id;
+		struct subchannel_id schid;
 		u32 reserved6[1004];
 		struct chsc_header response;
 		u32 reserved7;
@@ -2113,7 +2459,8 @@ tiqdio_set_subchannel_ind(struct qdio_irq *irq_ptr, int reset_to_zero)
 	scssc_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
 	if (!scssc_area) {
 		QDIO_PRINT_WARN("No memory for setting indicators on " \
-				"subchannel x%x.\n", irq_ptr->irq);
+				"subchannel 0.%x.%x.\n",
+				irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
 		return -ENOMEM;
 	}
 	scssc_area->request = (struct chsc_header) {
@@ -2127,7 +2474,7 @@ tiqdio_set_subchannel_ind(struct qdio_irq *irq_ptr, int reset_to_zero)
 	scssc_area->ks = QDIO_STORAGE_KEY;
 	scssc_area->kc = QDIO_STORAGE_KEY;
 	scssc_area->isc = TIQDIO_THININT_ISC;
-	scssc_area->subsystem_id = (1<<16) + irq_ptr->irq;
+	scssc_area->schid = irq_ptr->schid;
 	/* enables the time delay disablement facility. Don't care
 	 * whether it is really there (i.e. we haven't checked for
 	 * it) */
@@ -2137,12 +2484,11 @@ tiqdio_set_subchannel_ind(struct qdio_irq *irq_ptr, int reset_to_zero)
 		QDIO_PRINT_WARN("Time delay disablement facility " \
 				"not available\n");
 
-
-
 	result = chsc(scssc_area);
 	if (result) {
-		QDIO_PRINT_WARN("could not set indicators on irq x%x, " \
-				"cc=%i.\n",irq_ptr->irq,result);
+		QDIO_PRINT_WARN("could not set indicators on irq 0.%x.%x, " \
+				"cc=%i.\n",
+				irq_ptr->schid.ssid, irq_ptr->schid.sch_no,result);
 		result = -EIO;
 		goto out;
 	}
@@ -2198,7 +2544,8 @@ tiqdio_set_delay_target(struct qdio_irq *irq_ptr, unsigned long delay_target)
 	scsscf_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
 	if (!scsscf_area) {
 		QDIO_PRINT_WARN("No memory for setting delay target on " \
-				"subchannel x%x.\n", irq_ptr->irq);
+				"subchannel 0.%x.%x.\n",
+				irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
 		return -ENOMEM;
 	}
 	scsscf_area->request = (struct chsc_header) {
@@ -2210,8 +2557,10 @@ tiqdio_set_delay_target(struct qdio_irq *irq_ptr, unsigned long delay_target)
 
 	result=chsc(scsscf_area);
 	if (result) {
-		QDIO_PRINT_WARN("could not set delay target on irq x%x, " \
-				"cc=%i. Continuing.\n",irq_ptr->irq,result);
+		QDIO_PRINT_WARN("could not set delay target on irq 0.%x.%x, " \
+				"cc=%i. Continuing.\n",
+				irq_ptr->schid.ssid, irq_ptr->schid.sch_no,
+				result);
 		result = -EIO;
 		goto out;
 	}
@@ -2245,7 +2594,7 @@ qdio_cleanup(struct ccw_device *cdev, int how)
 	if (!irq_ptr)
 		return -ENODEV;
 
-	sprintf(dbf_text,"qcln%4x",irq_ptr->irq);
+	sprintf(dbf_text,"qcln%4x",irq_ptr->schid.sch_no);
 	QDIO_DBF_TEXT1(0,trace,dbf_text);
 	QDIO_DBF_TEXT0(0,setup,dbf_text);
 
@@ -2272,7 +2621,7 @@ qdio_shutdown(struct ccw_device *cdev, int how)
 
 	down(&irq_ptr->setting_up_sema);
 
-	sprintf(dbf_text,"qsqs%4x",irq_ptr->irq);
+	sprintf(dbf_text,"qsqs%4x",irq_ptr->schid.sch_no);
 	QDIO_DBF_TEXT1(0,trace,dbf_text);
 	QDIO_DBF_TEXT0(0,setup,dbf_text);
 
@@ -2378,7 +2727,7 @@ qdio_free(struct ccw_device *cdev)
 
 	down(&irq_ptr->setting_up_sema);
 
-	sprintf(dbf_text,"qfqs%4x",irq_ptr->irq);
+	sprintf(dbf_text,"qfqs%4x",irq_ptr->schid.sch_no);
 	QDIO_DBF_TEXT1(0,trace,dbf_text);
 	QDIO_DBF_TEXT0(0,setup,dbf_text);
 
@@ -2526,13 +2875,14 @@ qdio_establish_irq_check_for_errors(struct ccw_device *cdev, int cstat,
 	irq_ptr = cdev->private->qdio_data;
 
 	if (cstat || (dstat & ~(DEV_STAT_CHN_END|DEV_STAT_DEV_END))) {
-		sprintf(dbf_text,"ick1%4x",irq_ptr->irq);
+		sprintf(dbf_text,"ick1%4x",irq_ptr->schid.sch_no);
 		QDIO_DBF_TEXT2(1,trace,dbf_text);
 		QDIO_DBF_HEX2(0,trace,&dstat,sizeof(int));
 		QDIO_DBF_HEX2(0,trace,&cstat,sizeof(int));
 		QDIO_PRINT_ERR("received check condition on establish " \
-			       "queues on irq 0x%x (cs=x%x, ds=x%x).\n",
-			       irq_ptr->irq,cstat,dstat);
+			       "queues on irq 0.%x.%x (cs=x%x, ds=x%x).\n",
+			       irq_ptr->schid.ssid, irq_ptr->schid.sch_no,
+			       cstat,dstat);
 		qdio_set_state(irq_ptr,QDIO_IRQ_STATE_ERR);
 	}
 	
@@ -2540,9 +2890,10 @@ qdio_establish_irq_check_for_errors(struct ccw_device *cdev, int cstat,
 		QDIO_DBF_TEXT2(1,setup,"eq:no de");
 		QDIO_DBF_HEX2(0,setup,&dstat, sizeof(dstat));
 		QDIO_DBF_HEX2(0,setup,&cstat, sizeof(cstat));
-		QDIO_PRINT_ERR("establish queues on irq %04x: didn't get "
+		QDIO_PRINT_ERR("establish queues on irq 0.%x.%04x: didn't get "
 			       "device end: dstat=%02x, cstat=%02x\n",
-			       irq_ptr->irq, dstat, cstat);
+			       irq_ptr->schid.ssid, irq_ptr->schid.sch_no,
+			       dstat, cstat);
 		qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR);
 		return 1;
 	}
@@ -2551,10 +2902,10 @@ qdio_establish_irq_check_for_errors(struct ccw_device *cdev, int cstat,
 		QDIO_DBF_TEXT2(1,setup,"eq:badio");
 		QDIO_DBF_HEX2(0,setup,&dstat, sizeof(dstat));
 		QDIO_DBF_HEX2(0,setup,&cstat, sizeof(cstat));
-		QDIO_PRINT_ERR("establish queues on irq %04x: got "
+		QDIO_PRINT_ERR("establish queues on irq 0.%x.%04x: got "
 			       "the following devstat: dstat=%02x, "
-			       "cstat=%02x\n",
-			       irq_ptr->irq, dstat, cstat);
+			       "cstat=%02x\n", irq_ptr->schid.ssid,
+			       irq_ptr->schid.sch_no, dstat, cstat);
 		qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR);
 		return 1;
 	}
@@ -2569,7 +2920,7 @@ qdio_establish_handle_irq(struct ccw_device *cdev, int cstat, int dstat)
 
 	irq_ptr = cdev->private->qdio_data;
 
-	sprintf(dbf_text,"qehi%4x",cdev->private->irq);
+	sprintf(dbf_text,"qehi%4x",cdev->private->sch_no);
 	QDIO_DBF_TEXT0(0,setup,dbf_text);
 	QDIO_DBF_TEXT0(0,trace,dbf_text);
 
@@ -2588,7 +2939,7 @@ qdio_initialize(struct qdio_initialize *init_data)
 	int rc;
 	char dbf_text[15];
 
-	sprintf(dbf_text,"qini%4x",init_data->cdev->private->irq);
+	sprintf(dbf_text,"qini%4x",init_data->cdev->private->sch_no);
 	QDIO_DBF_TEXT0(0,setup,dbf_text);
 	QDIO_DBF_TEXT0(0,trace,dbf_text);
 
@@ -2609,7 +2960,7 @@ qdio_allocate(struct qdio_initialize *init_data)
 	struct qdio_irq *irq_ptr;
 	char dbf_text[15];
 
-	sprintf(dbf_text,"qalc%4x",init_data->cdev->private->irq);
+	sprintf(dbf_text,"qalc%4x",init_data->cdev->private->sch_no);
 	QDIO_DBF_TEXT0(0,setup,dbf_text);
 	QDIO_DBF_TEXT0(0,trace,dbf_text);
 	if ( (init_data->no_input_qs>QDIO_MAX_QUEUES_PER_IRQ) ||
@@ -2682,7 +3033,7 @@ int qdio_fill_irq(struct qdio_initialize *init_data)
 
 	irq_ptr->int_parm=init_data->int_parm;
 
-	irq_ptr->irq = init_data->cdev->private->irq;
+	irq_ptr->schid = ccw_device_get_subchannel_id(init_data->cdev);
 	irq_ptr->no_input_qs=init_data->no_input_qs;
 	irq_ptr->no_output_qs=init_data->no_output_qs;
 
@@ -2698,11 +3049,12 @@ int qdio_fill_irq(struct qdio_initialize *init_data)
 	QDIO_DBF_TEXT2(0,setup,dbf_text);
 
 	if (irq_ptr->is_thinint_irq) {
-		irq_ptr->dev_st_chg_ind=qdio_get_indicator();
+		irq_ptr->dev_st_chg_ind = qdio_get_indicator();
 		QDIO_DBF_HEX1(0,setup,&irq_ptr->dev_st_chg_ind,sizeof(void*));
 		if (!irq_ptr->dev_st_chg_ind) {
 			QDIO_PRINT_WARN("no indicator location available " \
-					"for irq 0x%x\n",irq_ptr->irq);
+					"for irq 0.%x.%x\n",
+					irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
 			qdio_release_irq_memory(irq_ptr);
 			return -ENOBUFS;
 		}
@@ -2747,6 +3099,10 @@ int qdio_fill_irq(struct qdio_initialize *init_data)
 	irq_ptr->qdr->qkey=QDIO_STORAGE_KEY;
 
 	/* fill in qib */
+	irq_ptr->is_qebsm = is_passthrough;
+	if (irq_ptr->is_qebsm)
+		irq_ptr->qib.rflags |= QIB_RFLAGS_ENABLE_QEBSM;
+
 	irq_ptr->qib.qfmt=init_data->q_format;
 	if (init_data->no_input_qs)
 		irq_ptr->qib.isliba=(unsigned long)(irq_ptr->input_qs[0]->slib);
@@ -2829,7 +3185,7 @@ qdio_establish(struct qdio_initialize *init_data)
 		tiqdio_set_delay_target(irq_ptr,TIQDIO_DELAY_TARGET);
 	}
 
-	sprintf(dbf_text,"qest%4x",cdev->private->irq);
+	sprintf(dbf_text,"qest%4x",cdev->private->sch_no);
 	QDIO_DBF_TEXT0(0,setup,dbf_text);
 	QDIO_DBF_TEXT0(0,trace,dbf_text);
 
@@ -2855,9 +3211,10 @@ qdio_establish(struct qdio_initialize *init_data)
 			sprintf(dbf_text,"eq:io%4x",result);
 			QDIO_DBF_TEXT2(1,setup,dbf_text);
 		}
-		QDIO_PRINT_WARN("establish queues on irq %04x: do_IO " \
-                           "returned %i, next try returned %i\n",
-                           irq_ptr->irq,result,result2);
+		QDIO_PRINT_WARN("establish queues on irq 0.%x.%04x: do_IO " \
+				"returned %i, next try returned %i\n",
+				irq_ptr->schid.ssid, irq_ptr->schid.sch_no,
+				result, result2);
 		result=result2;
 		if (result)
 			ccw_device_set_timeout(cdev, 0);
@@ -2884,7 +3241,7 @@ qdio_establish(struct qdio_initialize *init_data)
 		return -EIO;
 	}
 
-	irq_ptr->qdioac=qdio_check_siga_needs(irq_ptr->irq);
+	qdio_get_ssqd_information(irq_ptr);
 	/* if this gets set once, we're running under VM and can omit SVSes */
 	if (irq_ptr->qdioac&CHSC_FLAG_SIGA_SYNC_NECESSARY)
 		omit_svs=1;
@@ -2930,7 +3287,7 @@ qdio_activate(struct ccw_device *cdev, int flags)
 		goto out;
 	}
 
-	sprintf(dbf_text,"qact%4x", irq_ptr->irq);
+	sprintf(dbf_text,"qact%4x", irq_ptr->schid.sch_no);
 	QDIO_DBF_TEXT2(0,setup,dbf_text);
 	QDIO_DBF_TEXT2(0,trace,dbf_text);
 
@@ -2955,9 +3312,10 @@ qdio_activate(struct ccw_device *cdev, int flags)
 			sprintf(dbf_text,"aq:io%4x",result);
 			QDIO_DBF_TEXT2(1,setup,dbf_text);
 		}
-		QDIO_PRINT_WARN("activate queues on irq %04x: do_IO " \
-                           "returned %i, next try returned %i\n",
-                           irq_ptr->irq,result,result2);
+		QDIO_PRINT_WARN("activate queues on irq 0.%x.%04x: do_IO " \
+				"returned %i, next try returned %i\n",
+				irq_ptr->schid.ssid, irq_ptr->schid.sch_no,
+				result, result2);
 		result=result2;
 	}
 
@@ -3015,30 +3373,40 @@ static inline void
 qdio_do_qdio_fill_input(struct qdio_q *q, unsigned int qidx,
 			unsigned int count, struct qdio_buffer *buffers)
 {
+	struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr;
+	qidx &= (QDIO_MAX_BUFFERS_PER_Q - 1);
+	if (irq->is_qebsm) {
+		while (count)
+			set_slsb(q, &qidx, SLSB_CU_INPUT_EMPTY, &count);
+		return;
+	}
 	for (;;) {
-		set_slsb(&q->slsb.acc.val[qidx],SLSB_CU_INPUT_EMPTY);
+		set_slsb(q, &qidx, SLSB_CU_INPUT_EMPTY, &count);
 		count--;
 		if (!count) break;
-		qidx=(qidx+1)&(QDIO_MAX_BUFFERS_PER_Q-1);
+		qidx = (qidx + 1) & (QDIO_MAX_BUFFERS_PER_Q - 1);
 	}
-
-	/* not necessary, as the queues are synced during the SIGA read */
-	/*SYNC_MEMORY;*/
 }
 
 static inline void
 qdio_do_qdio_fill_output(struct qdio_q *q, unsigned int qidx,
 			 unsigned int count, struct qdio_buffer *buffers)
 {
+	struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr;
+
+	qidx &= (QDIO_MAX_BUFFERS_PER_Q - 1);
+	if (irq->is_qebsm) {
+		while (count)
+			set_slsb(q, &qidx, SLSB_CU_OUTPUT_PRIMED, &count);
+		return;
+	}
+
 	for (;;) {
-		set_slsb(&q->slsb.acc.val[qidx],SLSB_CU_OUTPUT_PRIMED);
+		set_slsb(q, &qidx, SLSB_CU_OUTPUT_PRIMED, &count);
 		count--;
 		if (!count) break;
-		qidx=(qidx+1)&(QDIO_MAX_BUFFERS_PER_Q-1);
+		qidx = (qidx + 1) & (QDIO_MAX_BUFFERS_PER_Q - 1);
 	}
-
-	/* SIGA write will sync the queues */
-	/*SYNC_MEMORY;*/
 }
 
 static inline void
@@ -3083,6 +3451,9 @@ do_qdio_handle_outbound(struct qdio_q *q, unsigned int callflags,
 			struct qdio_buffer *buffers)
 {
 	int used_elements;
+	unsigned int cnt, start_buf;
+	unsigned char state = 0;
+	struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr;
 
 	/* This is the outbound handling of queues */
 #ifdef QDIO_PERFORMANCE_STATS
@@ -3115,9 +3486,15 @@ do_qdio_handle_outbound(struct qdio_q *q, unsigned int callflags,
 			 * SYNC_MEMORY :-/ ), we try to
 			 * fast-requeue buffers 
 			 */
-			if (q->slsb.acc.val[(qidx+QDIO_MAX_BUFFERS_PER_Q-1)
-					    &(QDIO_MAX_BUFFERS_PER_Q-1)]!=
-			    SLSB_CU_OUTPUT_PRIMED) {
+			if (irq->is_qebsm) {
+				cnt = 1;
+				start_buf = ((qidx+QDIO_MAX_BUFFERS_PER_Q-1) &
+					     (QDIO_MAX_BUFFERS_PER_Q-1));
+				qdio_do_eqbs(q, &state, &start_buf, &cnt);
+			} else
+				state = q->slsb.acc.val[(qidx+QDIO_MAX_BUFFERS_PER_Q-1)
+					&(QDIO_MAX_BUFFERS_PER_Q-1) ];
+			 if (state != SLSB_CU_OUTPUT_PRIMED) {
 				qdio_kick_outbound_q(q);
 			} else {
 				QDIO_DBF_TEXT3(0,trace, "fast-req");
@@ -3150,7 +3527,7 @@ do_QDIO(struct ccw_device *cdev,unsigned int callflags,
 #ifdef CONFIG_QDIO_DEBUG
 	char dbf_text[20];
 
-	sprintf(dbf_text,"doQD%04x",cdev->private->irq);
+	sprintf(dbf_text,"doQD%04x",cdev->private->sch_no);
  	QDIO_DBF_TEXT3(0,trace,dbf_text);
 #endif /* CONFIG_QDIO_DEBUG */
 
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h
index 328e31cc6854..fa385e761fe1 100644
--- a/drivers/s390/cio/qdio.h
+++ b/drivers/s390/cio/qdio.h
@@ -3,14 +3,15 @@
 
 #include <asm/page.h>
 
-#define VERSION_CIO_QDIO_H "$Revision: 1.33 $"
+#include "schid.h"
+
+#define VERSION_CIO_QDIO_H "$Revision: 1.40 $"
 
 #ifdef CONFIG_QDIO_DEBUG
 #define QDIO_VERBOSE_LEVEL 9
 #else /* CONFIG_QDIO_DEBUG */
 #define QDIO_VERBOSE_LEVEL 5
 #endif /* CONFIG_QDIO_DEBUG */
-
 #define QDIO_USE_PROCESSING_STATE
 
 #ifdef CONFIG_QDIO_PERF_STATS
@@ -265,12 +266,64 @@ QDIO_PRINT_##importance(header "%02x %02x %02x %02x  %02x %02x %02x %02x  " \
 /*
  * Some instructions as assembly
  */
+
+static inline int
+do_sqbs(unsigned long sch, unsigned char state, int queue,
+       unsigned int *start, unsigned int *count)
+{
+#ifdef CONFIG_64BIT
+       register unsigned long _ccq asm ("0") = *count;
+       register unsigned long _sch asm ("1") = sch;
+       unsigned long _queuestart = ((unsigned long)queue << 32) | *start;
+
+       asm volatile (
+              " .insn rsy,0xeb000000008A,%1,0,0(%2)\n\t"
+              : "+d" (_ccq), "+d" (_queuestart)
+              : "d" ((unsigned long)state), "d" (_sch)
+              : "memory", "cc"
+       );
+       *count = _ccq & 0xff;
+       *start = _queuestart & 0xff;
+
+       return (_ccq >> 32) & 0xff;
+#else
+       return 0;
+#endif
+}
+
+static inline int
+do_eqbs(unsigned long sch, unsigned char *state, int queue,
+	unsigned int *start, unsigned int *count)
+{
+#ifdef CONFIG_64BIT
+	register unsigned long _ccq asm ("0") = *count;
+	register unsigned long _sch asm ("1") = sch;
+	unsigned long _queuestart = ((unsigned long)queue << 32) | *start;
+	unsigned long _state = 0;
+
+	asm volatile (
+	      " .insn rrf,0xB99c0000,%1,%2,0,0  \n\t"
+	      : "+d" (_ccq), "+d" (_queuestart), "+d" (_state)
+	      : "d" (_sch)
+	      : "memory", "cc"
+	);
+	*count = _ccq & 0xff;
+	*start = _queuestart & 0xff;
+	*state = _state & 0xff;
+
+	return (_ccq >> 32) & 0xff;
+#else
+	return 0;
+#endif
+}
+
+
 static inline int
-do_siga_sync(unsigned int irq, unsigned int mask1, unsigned int mask2)
+do_siga_sync(struct subchannel_id schid, unsigned int mask1, unsigned int mask2)
 {
 	int cc;
 
-#ifndef CONFIG_ARCH_S390X
+#ifndef CONFIG_64BIT
 	asm volatile (
 		"lhi	0,2	\n\t"
 		"lr	1,%1	\n\t"
@@ -280,10 +333,10 @@ do_siga_sync(unsigned int irq, unsigned int mask1, unsigned int mask2)
 		"ipm	%0	\n\t"
 		"srl	%0,28	\n\t"
 		: "=d" (cc)
-		: "d" (0x10000|irq), "d" (mask1), "d" (mask2)
+		: "d" (schid), "d" (mask1), "d" (mask2)
 		: "cc", "0", "1", "2", "3"
 		);
-#else /* CONFIG_ARCH_S390X */
+#else /* CONFIG_64BIT */
 	asm volatile (
 		"lghi	0,2	\n\t"
 		"llgfr	1,%1	\n\t"
@@ -293,19 +346,19 @@ do_siga_sync(unsigned int irq, unsigned int mask1, unsigned int mask2)
 		"ipm	%0	\n\t"
 		"srl	%0,28	\n\t"
 		: "=d" (cc)
-		: "d" (0x10000|irq), "d" (mask1), "d" (mask2)
+		: "d" (schid), "d" (mask1), "d" (mask2)
 		: "cc", "0", "1", "2", "3"
 		);
-#endif /* CONFIG_ARCH_S390X */
+#endif /* CONFIG_64BIT */
 	return cc;
 }
 
 static inline int
-do_siga_input(unsigned int irq, unsigned int mask)
+do_siga_input(struct subchannel_id schid, unsigned int mask)
 {
 	int cc;
 
-#ifndef CONFIG_ARCH_S390X
+#ifndef CONFIG_64BIT
 	asm volatile (
 		"lhi	0,1	\n\t"
 		"lr	1,%1	\n\t"
@@ -314,10 +367,10 @@ do_siga_input(unsigned int irq, unsigned int mask)
 		"ipm	%0	\n\t"
 		"srl	%0,28	\n\t"
 		: "=d" (cc)
-		: "d" (0x10000|irq), "d" (mask)
+		: "d" (schid), "d" (mask)
 		: "cc", "0", "1", "2", "memory"
 		);
-#else /* CONFIG_ARCH_S390X */
+#else /* CONFIG_64BIT */
 	asm volatile (
 		"lghi	0,1	\n\t"
 		"llgfr	1,%1	\n\t"
@@ -326,21 +379,22 @@ do_siga_input(unsigned int irq, unsigned int mask)
 		"ipm	%0	\n\t"
 		"srl	%0,28	\n\t"
 		: "=d" (cc)
-		: "d" (0x10000|irq), "d" (mask)
+		: "d" (schid), "d" (mask)
 		: "cc", "0", "1", "2", "memory"
 		);
-#endif /* CONFIG_ARCH_S390X */
+#endif /* CONFIG_64BIT */
 	
 	return cc;
 }
 
 static inline int
-do_siga_output(unsigned long irq, unsigned long mask, __u32 *bb)
+do_siga_output(unsigned long schid, unsigned long mask, __u32 *bb,
+	       unsigned int fc)
 {
 	int cc;
 	__u32 busy_bit;
 
-#ifndef CONFIG_ARCH_S390X
+#ifndef CONFIG_64BIT
 	asm volatile (
 		"lhi	0,0	\n\t"
 		"lr	1,%2	\n\t"
@@ -366,14 +420,14 @@ do_siga_output(unsigned long irq, unsigned long mask, __u32 *bb)
 		".long	0b,2b	\n\t"
 		".previous	\n\t"
 		: "=d" (cc), "=d" (busy_bit)
-		: "d" (0x10000|irq), "d" (mask),
+		: "d" (schid), "d" (mask),
 		"i" (QDIO_SIGA_ERROR_ACCESS_EXCEPTION)
 		: "cc", "0", "1", "2", "memory"
 		);
-#else /* CONFIG_ARCH_S390X */
+#else /* CONFIG_64BIT */
 	asm volatile (
-		"lghi	0,0	\n\t"
-		"llgfr	1,%2	\n\t"
+        	"llgfr  0,%5    \n\t"
+                "lgr    1,%2    \n\t"
 		"llgfr	2,%3	\n\t"
 		"siga	0	\n\t"
 		"0:"
@@ -391,11 +445,11 @@ do_siga_output(unsigned long irq, unsigned long mask, __u32 *bb)
 		".quad	0b,1b	\n\t"
 		".previous	\n\t"
 		: "=d" (cc), "=d" (busy_bit)
-		: "d" (0x10000|irq), "d" (mask),
-		"i" (QDIO_SIGA_ERROR_ACCESS_EXCEPTION)
+		: "d" (schid), "d" (mask),
+		"i" (QDIO_SIGA_ERROR_ACCESS_EXCEPTION), "d" (fc)
 		: "cc", "0", "1", "2", "memory"
 		);
-#endif /* CONFIG_ARCH_S390X */
+#endif /* CONFIG_64BIT */
 	
 	(*bb) = busy_bit;
 	return cc;
@@ -407,21 +461,21 @@ do_clear_global_summary(void)
 
 	unsigned long time;
 
-#ifndef CONFIG_ARCH_S390X
+#ifndef CONFIG_64BIT
 	asm volatile (
 		"lhi	1,3	\n\t"
 		".insn	rre,0xb2650000,2,0	\n\t"
 		"lr	%0,3	\n\t"
 		: "=d" (time) : : "cc", "1", "2", "3"
 		);
-#else /* CONFIG_ARCH_S390X */
+#else /* CONFIG_64BIT */
 	asm volatile (
 		"lghi	1,3	\n\t"
 		".insn	rre,0xb2650000,2,0	\n\t"
 		"lgr	%0,3	\n\t"
 		: "=d" (time) : : "cc", "1", "2", "3"
 		);
-#endif /* CONFIG_ARCH_S390X */
+#endif /* CONFIG_64BIT */
 	
 	return time;
 }
@@ -488,42 +542,21 @@ struct qdio_perf_stats {
 
 #define MY_MODULE_STRING(x) #x
 
-#ifdef CONFIG_ARCH_S390X
+#ifdef CONFIG_64BIT
 #define QDIO_GET_ADDR(x) ((__u32)(unsigned long)x)
-#else /* CONFIG_ARCH_S390X */
+#else /* CONFIG_64BIT */
 #define QDIO_GET_ADDR(x) ((__u32)(long)x)
-#endif /* CONFIG_ARCH_S390X */
-
-#ifdef CONFIG_QDIO_DEBUG
-#define set_slsb(x,y) \
-  if(q->queue_type==QDIO_TRACE_QTYPE) { \
-        if(q->is_input_q) { \
-            QDIO_DBF_HEX2(0,slsb_in,&q->slsb,QDIO_MAX_BUFFERS_PER_Q); \
-        } else { \
-            QDIO_DBF_HEX2(0,slsb_out,&q->slsb,QDIO_MAX_BUFFERS_PER_Q); \
-        } \
-  } \
-  qdio_set_slsb(x,y); \
-  if(q->queue_type==QDIO_TRACE_QTYPE) { \
-        if(q->is_input_q) { \
-            QDIO_DBF_HEX2(0,slsb_in,&q->slsb,QDIO_MAX_BUFFERS_PER_Q); \
-        } else { \
-            QDIO_DBF_HEX2(0,slsb_out,&q->slsb,QDIO_MAX_BUFFERS_PER_Q); \
-        } \
-  }
-#else /* CONFIG_QDIO_DEBUG */
-#define set_slsb(x,y) qdio_set_slsb(x,y)
-#endif /* CONFIG_QDIO_DEBUG */
+#endif /* CONFIG_64BIT */
 
 struct qdio_q {
 	volatile struct slsb slsb;
 
 	char unused[QDIO_MAX_BUFFERS_PER_Q];
 
-	__u32 * volatile dev_st_chg_ind;
+	__u32 * dev_st_chg_ind;
 
 	int is_input_q;
-	int irq;
+	struct subchannel_id schid;
 	struct ccw_device *cdev;
 
 	unsigned int is_iqdio_q;
@@ -568,6 +601,7 @@ struct qdio_q {
 	struct tasklet_struct tasklet;
 #endif /* QDIO_USE_TIMERS_FOR_POLLING */
 
+
 	enum qdio_irq_states state;
 
 	/* used to store the error condition during a data transfer */
@@ -617,13 +651,17 @@ struct qdio_irq {
 	__u32 * volatile dev_st_chg_ind;
 
 	unsigned long int_parm;
-	int irq;
+	struct subchannel_id schid;
 
 	unsigned int is_iqdio_irq;
 	unsigned int is_thinint_irq;
 	unsigned int hydra_gives_outbound_pcis;
 	unsigned int sync_done_on_outb_pcis;
 
+	/* QEBSM facility */
+	unsigned int is_qebsm;
+	unsigned long sch_token;
+
 	enum qdio_irq_states state;
 
 	unsigned int no_input_qs;
diff --git a/drivers/s390/cio/schid.h b/drivers/s390/cio/schid.h
new file mode 100644
index 000000000000..54328fec5ade
--- /dev/null
+++ b/drivers/s390/cio/schid.h
@@ -0,0 +1,26 @@
+#ifndef S390_SCHID_H
+#define S390_SCHID_H
+
+struct subchannel_id {
+	__u32 reserved:13;
+	__u32 ssid:2;
+	__u32 one:1;
+	__u32 sch_no:16;
+} __attribute__ ((packed,aligned(4)));
+
+
+/* Helper function for sane state of pre-allocated subchannel_id. */
+static inline void
+init_subchannel_id(struct subchannel_id *schid)
+{
+	memset(schid, 0, sizeof(struct subchannel_id));
+	schid->one = 1;
+}
+
+static inline int
+schid_equal(struct subchannel_id *schid1, struct subchannel_id *schid2)
+{
+	return !memcmp(schid1, schid2, sizeof(struct subchannel_id));
+}
+
+#endif /* S390_SCHID_H */
diff --git a/drivers/s390/crypto/z90common.h b/drivers/s390/crypto/z90common.h
index e319e78b5ea2..f87c785f2039 100644
--- a/drivers/s390/crypto/z90common.h
+++ b/drivers/s390/crypto/z90common.h
@@ -1,9 +1,9 @@
 /*
  *  linux/drivers/s390/crypto/z90common.h
  *
- *  z90crypt 1.3.2
+ *  z90crypt 1.3.3
  *
- *  Copyright (C)  2001, 2004 IBM Corporation
+ *  Copyright (C)  2001, 2005 IBM Corporation
  *  Author(s): Robert Burroughs (burrough@us.ibm.com)
  *             Eric Rossman (edrossma@us.ibm.com)
  *
@@ -91,12 +91,13 @@ enum hdstat {
 #define TSQ_FATAL_ERROR 34
 #define RSQ_FATAL_ERROR 35
 
-#define Z90CRYPT_NUM_TYPES	5
+#define Z90CRYPT_NUM_TYPES	6
 #define PCICA		0
 #define PCICC		1
 #define PCIXCC_MCL2	2
 #define PCIXCC_MCL3	3
 #define CEX2C		4
+#define CEX2A		5
 #define NILDEV		-1
 #define ANYDEV		-1
 #define PCIXCC_UNK	-2
@@ -105,7 +106,7 @@ enum hdevice_type {
 	PCICC_HW  = 3,
 	PCICA_HW  = 4,
 	PCIXCC_HW = 5,
-	OTHER_HW  = 6,
+	CEX2A_HW  = 6,
 	CEX2C_HW  = 7
 };
 
diff --git a/drivers/s390/crypto/z90crypt.h b/drivers/s390/crypto/z90crypt.h
index 0a3bb5a10dd4..3a18443fdfa7 100644
--- a/drivers/s390/crypto/z90crypt.h
+++ b/drivers/s390/crypto/z90crypt.h
@@ -1,9 +1,9 @@
 /*
  *  linux/drivers/s390/crypto/z90crypt.h
  *
- *  z90crypt 1.3.2
+ *  z90crypt 1.3.3
  *
- *  Copyright (C)  2001, 2004 IBM Corporation
+ *  Copyright (C)  2001, 2005 IBM Corporation
  *  Author(s): Robert Burroughs (burrough@us.ibm.com)
  *             Eric Rossman (edrossma@us.ibm.com)
  *
@@ -29,11 +29,11 @@
 
 #include <linux/ioctl.h>
 
-#define VERSION_Z90CRYPT_H "$Revision: 1.11 $"
+#define VERSION_Z90CRYPT_H "$Revision: 1.2.2.4 $"
 
 #define z90crypt_VERSION 1
 #define z90crypt_RELEASE 3	// 2 = PCIXCC, 3 = rewrite for coding standards
-#define z90crypt_VARIANT 2	// 2 = added PCIXCC MCL3 and CEX2C support
+#define z90crypt_VARIANT 3	// 3 = CEX2A support
 
 /**
  * struct ica_rsa_modexpo
@@ -122,6 +122,9 @@ struct ica_rsa_modexpo_crt {
  *   Z90STAT_CEX2CCOUNT
  *     Return an integer count of all CEX2Cs.
  *
+ *   Z90STAT_CEX2ACOUNT
+ *     Return an integer count of all CEX2As.
+ *
  *   Z90STAT_REQUESTQ_COUNT
  *     Return an integer count of the number of entries waiting to be
  *     sent to a device.
@@ -144,6 +147,7 @@ struct ica_rsa_modexpo_crt {
  *       0x03: PCIXCC_MCL2
  *       0x04: PCIXCC_MCL3
  *       0x05: CEX2C
+ *       0x06: CEX2A
  *       0x0d: device is disabled via the proc filesystem
  *
  *   Z90STAT_QDEPTH_MASK
@@ -199,6 +203,7 @@ struct ica_rsa_modexpo_crt {
 #define Z90STAT_PCIXCCMCL2COUNT	_IOR(Z90_IOCTL_MAGIC, 0x4b, int)
 #define Z90STAT_PCIXCCMCL3COUNT	_IOR(Z90_IOCTL_MAGIC, 0x4c, int)
 #define Z90STAT_CEX2CCOUNT	_IOR(Z90_IOCTL_MAGIC, 0x4d, int)
+#define Z90STAT_CEX2ACOUNT	_IOR(Z90_IOCTL_MAGIC, 0x4e, int)
 #define Z90STAT_REQUESTQ_COUNT	_IOR(Z90_IOCTL_MAGIC, 0x44, int)
 #define Z90STAT_PENDINGQ_COUNT	_IOR(Z90_IOCTL_MAGIC, 0x45, int)
 #define Z90STAT_TOTALOPEN_COUNT _IOR(Z90_IOCTL_MAGIC, 0x46, int)
diff --git a/drivers/s390/crypto/z90hardware.c b/drivers/s390/crypto/z90hardware.c
index c215e0889736..d7f7494a0cbe 100644
--- a/drivers/s390/crypto/z90hardware.c
+++ b/drivers/s390/crypto/z90hardware.c
@@ -1,9 +1,9 @@
 /*
  *  linux/drivers/s390/crypto/z90hardware.c
  *
- *  z90crypt 1.3.2
+ *  z90crypt 1.3.3
  *
- *  Copyright (C)  2001, 2004 IBM Corporation
+ *  Copyright (C)  2001, 2005 IBM Corporation
  *  Author(s): Robert Burroughs (burrough@us.ibm.com)
  *             Eric Rossman (edrossma@us.ibm.com)
  *
@@ -648,6 +648,87 @@ static struct cca_public_sec static_cca_pub_sec = {
 #define RESPONSE_CPRB_SIZE  0x000006B8
 #define RESPONSE_CPRBX_SIZE 0x00000724
 
+struct type50_hdr {
+	u8    reserved1;
+	u8    msg_type_code;
+	u16   msg_len;
+	u8    reserved2;
+	u8    ignored;
+	u16   reserved3;
+};
+
+#define TYPE50_TYPE_CODE 0x50
+
+#define TYPE50_MEB1_LEN (sizeof(struct type50_meb1_msg))
+#define TYPE50_MEB2_LEN (sizeof(struct type50_meb2_msg))
+#define TYPE50_CRB1_LEN (sizeof(struct type50_crb1_msg))
+#define TYPE50_CRB2_LEN (sizeof(struct type50_crb2_msg))
+
+#define TYPE50_MEB1_FMT 0x0001
+#define TYPE50_MEB2_FMT 0x0002
+#define TYPE50_CRB1_FMT 0x0011
+#define TYPE50_CRB2_FMT 0x0012
+
+struct type50_meb1_msg {
+	struct type50_hdr	header;
+	u16			keyblock_type;
+	u8			reserved[6];
+	u8			exponent[128];
+	u8			modulus[128];
+	u8			message[128];
+};
+
+struct type50_meb2_msg {
+	struct type50_hdr	header;
+	u16			keyblock_type;
+	u8			reserved[6];
+	u8			exponent[256];
+	u8			modulus[256];
+	u8			message[256];
+};
+
+struct type50_crb1_msg {
+	struct type50_hdr	header;
+	u16			keyblock_type;
+	u8			reserved[6];
+	u8			p[64];
+	u8			q[64];
+	u8			dp[64];
+	u8			dq[64];
+	u8			u[64];
+	u8			message[128];
+};
+
+struct type50_crb2_msg {
+	struct type50_hdr	header;
+	u16			keyblock_type;
+	u8			reserved[6];
+	u8			p[128];
+	u8			q[128];
+	u8			dp[128];
+	u8			dq[128];
+	u8			u[128];
+	u8			message[256];
+};
+
+union type50_msg {
+	struct type50_meb1_msg meb1;
+	struct type50_meb2_msg meb2;
+	struct type50_crb1_msg crb1;
+	struct type50_crb2_msg crb2;
+};
+
+struct type80_hdr {
+	u8	reserved1;
+	u8	type;
+	u16	len;
+	u8	code;
+	u8	reserved2[3];
+	u8	reserved3[8];
+};
+
+#define TYPE80_RSP_CODE 0x80
+
 struct error_hdr {
 	unsigned char reserved1;
 	unsigned char type;
@@ -657,6 +738,7 @@ struct error_hdr {
 };
 
 #define TYPE82_RSP_CODE 0x82
+#define TYPE88_RSP_CODE 0x88
 
 #define REP82_ERROR_MACHINE_FAILURE  0x10
 #define REP82_ERROR_PREEMPT_FAILURE  0x12
@@ -679,6 +761,22 @@ struct error_hdr {
 #define REP82_ERROR_PACKET_TRUNCATED 0xA0
 #define REP82_ERROR_ZERO_BUFFER_LEN  0xB0
 
+#define REP88_ERROR_MODULE_FAILURE   0x10
+#define REP88_ERROR_MODULE_TIMEOUT   0x11
+#define REP88_ERROR_MODULE_NOTINIT   0x13
+#define REP88_ERROR_MODULE_NOTAVAIL  0x14
+#define REP88_ERROR_MODULE_DISABLED  0x15
+#define REP88_ERROR_MODULE_IN_DIAGN  0x17
+#define REP88_ERROR_FASTPATH_DISABLD 0x19
+#define REP88_ERROR_MESSAGE_TYPE     0x20
+#define REP88_ERROR_MESSAGE_MALFORMD 0x22
+#define REP88_ERROR_MESSAGE_LENGTH   0x23
+#define REP88_ERROR_RESERVED_FIELD   0x24
+#define REP88_ERROR_KEY_TYPE         0x34
+#define REP88_ERROR_INVALID_KEY      0x82
+#define REP88_ERROR_OPERAND          0x84
+#define REP88_ERROR_OPERAND_EVEN_MOD 0x85
+
 #define CALLER_HEADER 12
 
 static inline int
@@ -687,7 +785,7 @@ testq(int q_nr, int *q_depth, int *dev_type, struct ap_status_word *stat)
 	int ccode;
 
 	asm volatile
-#ifdef __s390x__
+#ifdef CONFIG_64BIT
 	("	llgfr	0,%4		\n"
 	 "	slgr	1,1		\n"
 	 "	lgr	2,1		\n"
@@ -757,7 +855,7 @@ resetq(int q_nr, struct ap_status_word *stat_p)
 	int ccode;
 
 	asm volatile
-#ifdef __s390x__
+#ifdef CONFIG_64BIT
 	("	llgfr	0,%2		\n"
 	 "	lghi	1,1		\n"
 	 "	sll	1,24		\n"
@@ -823,7 +921,7 @@ sen(int msg_len, unsigned char *msg_ext, struct ap_status_word *stat)
 	int ccode;
 
 	asm volatile
-#ifdef __s390x__
+#ifdef CONFIG_64BIT
 	("	lgr	6,%3		\n"
 	 "	llgfr	7,%2		\n"
 	 "	llgt	0,0(6)		\n"
@@ -902,7 +1000,7 @@ rec(int q_nr, int buff_l, unsigned char *rsp, unsigned char *id,
 	int ccode;
 
 	asm volatile
-#ifdef __s390x__
+#ifdef CONFIG_64BIT
 	("	llgfr	0,%2		\n"
 	 "	lgr	3,%4		\n"
 	 "	lgr	6,%3		\n"
@@ -1029,10 +1127,6 @@ query_online(int deviceNr, int cdx, int resetNr, int *q_depth, int *dev_type)
 			stat = HD_ONLINE;
 			*q_depth = t_depth + 1;
 			switch (t_dev_type) {
-			case OTHER_HW:
-				stat = HD_NOT_THERE;
-				*dev_type = NILDEV;
-				break;
 			case PCICA_HW:
 				*dev_type = PCICA;
 				break;
@@ -1045,6 +1139,9 @@ query_online(int deviceNr, int cdx, int resetNr, int *q_depth, int *dev_type)
 			case CEX2C_HW:
 				*dev_type = CEX2C;
 				break;
+			case CEX2A_HW:
+				*dev_type = CEX2A;
+				break;
 			default:
 				*dev_type = NILDEV;
 				break;
@@ -2029,6 +2126,177 @@ ICACRT_msg_to_type6CRT_msgX(struct ica_rsa_modexpo_crt *icaMsg_p, int cdx,
 	return 0;
 }
 
+static int
+ICAMEX_msg_to_type50MEX_msg(struct ica_rsa_modexpo *icaMex_p, int *z90cMsg_l_p,
+			    union type50_msg *z90cMsg_p)
+{
+	int mod_len, msg_size, mod_tgt_len, exp_tgt_len, inp_tgt_len;
+	unsigned char *mod_tgt, *exp_tgt, *inp_tgt;
+	union type50_msg *tmp_type50_msg;
+
+	mod_len = icaMex_p->inputdatalength;
+
+	msg_size = ((mod_len <= 128) ? TYPE50_MEB1_LEN : TYPE50_MEB2_LEN) +
+		    CALLER_HEADER;
+
+	memset(z90cMsg_p, 0, msg_size);
+
+	tmp_type50_msg = (union type50_msg *)
+		((unsigned char *) z90cMsg_p + CALLER_HEADER);
+
+	tmp_type50_msg->meb1.header.msg_type_code = TYPE50_TYPE_CODE;
+
+	if (mod_len <= 128) {
+		tmp_type50_msg->meb1.header.msg_len = TYPE50_MEB1_LEN;
+		tmp_type50_msg->meb1.keyblock_type = TYPE50_MEB1_FMT;
+		mod_tgt = tmp_type50_msg->meb1.modulus;
+		mod_tgt_len = sizeof(tmp_type50_msg->meb1.modulus);
+		exp_tgt = tmp_type50_msg->meb1.exponent;
+		exp_tgt_len = sizeof(tmp_type50_msg->meb1.exponent);
+		inp_tgt = tmp_type50_msg->meb1.message;
+		inp_tgt_len = sizeof(tmp_type50_msg->meb1.message);
+	} else {
+		tmp_type50_msg->meb2.header.msg_len = TYPE50_MEB2_LEN;
+		tmp_type50_msg->meb2.keyblock_type = TYPE50_MEB2_FMT;
+		mod_tgt = tmp_type50_msg->meb2.modulus;
+		mod_tgt_len = sizeof(tmp_type50_msg->meb2.modulus);
+		exp_tgt = tmp_type50_msg->meb2.exponent;
+		exp_tgt_len = sizeof(tmp_type50_msg->meb2.exponent);
+		inp_tgt = tmp_type50_msg->meb2.message;
+		inp_tgt_len = sizeof(tmp_type50_msg->meb2.message);
+	}
+
+	mod_tgt += (mod_tgt_len - mod_len);
+	if (copy_from_user(mod_tgt, icaMex_p->n_modulus, mod_len))
+		return SEN_RELEASED;
+	if (is_empty(mod_tgt, mod_len))
+		return SEN_USER_ERROR;
+	exp_tgt += (exp_tgt_len - mod_len);
+	if (copy_from_user(exp_tgt, icaMex_p->b_key, mod_len))
+		return SEN_RELEASED;
+	if (is_empty(exp_tgt, mod_len))
+		return SEN_USER_ERROR;
+	inp_tgt += (inp_tgt_len - mod_len);
+	if (copy_from_user(inp_tgt, icaMex_p->inputdata, mod_len))
+		return SEN_RELEASED;
+	if (is_empty(inp_tgt, mod_len))
+		return SEN_USER_ERROR;
+
+	*z90cMsg_l_p = msg_size - CALLER_HEADER;
+
+	return 0;
+}
+
+static int
+ICACRT_msg_to_type50CRT_msg(struct ica_rsa_modexpo_crt *icaMsg_p,
+			    int *z90cMsg_l_p, union type50_msg *z90cMsg_p)
+{
+	int mod_len, short_len, long_len, tmp_size, p_tgt_len, q_tgt_len,
+	    dp_tgt_len, dq_tgt_len, u_tgt_len, inp_tgt_len, long_offset;
+	unsigned char *p_tgt, *q_tgt, *dp_tgt, *dq_tgt, *u_tgt, *inp_tgt,
+		      temp[8];
+	union type50_msg *tmp_type50_msg;
+
+	mod_len = icaMsg_p->inputdatalength;
+	short_len = mod_len / 2;
+	long_len = mod_len / 2 + 8;
+	long_offset = 0;
+
+	if (long_len > 128) {
+		memset(temp, 0x00, sizeof(temp));
+		if (copy_from_user(temp, icaMsg_p->np_prime, long_len-128))
+			return SEN_RELEASED;
+		if (!is_empty(temp, 8))
+			return SEN_NOT_AVAIL;
+		if (copy_from_user(temp, icaMsg_p->bp_key, long_len-128))
+			return SEN_RELEASED;
+		if (!is_empty(temp, 8))
+			return SEN_NOT_AVAIL;
+		if (copy_from_user(temp, icaMsg_p->u_mult_inv, long_len-128))
+			return SEN_RELEASED;
+		if (!is_empty(temp, 8))
+			return SEN_NOT_AVAIL;
+		long_offset = long_len - 128;
+		long_len = 128;
+	}
+
+	tmp_size = ((mod_len <= 128) ? TYPE50_CRB1_LEN : TYPE50_CRB2_LEN) +
+		    CALLER_HEADER;
+
+	memset(z90cMsg_p, 0, tmp_size);
+
+	tmp_type50_msg = (union type50_msg *)
+		((unsigned char *) z90cMsg_p + CALLER_HEADER);
+
+	tmp_type50_msg->crb1.header.msg_type_code = TYPE50_TYPE_CODE;
+	if (long_len <= 64) {
+		tmp_type50_msg->crb1.header.msg_len = TYPE50_CRB1_LEN;
+		tmp_type50_msg->crb1.keyblock_type = TYPE50_CRB1_FMT;
+		p_tgt = tmp_type50_msg->crb1.p;
+		p_tgt_len = sizeof(tmp_type50_msg->crb1.p);
+		q_tgt = tmp_type50_msg->crb1.q;
+		q_tgt_len = sizeof(tmp_type50_msg->crb1.q);
+		dp_tgt = tmp_type50_msg->crb1.dp;
+		dp_tgt_len = sizeof(tmp_type50_msg->crb1.dp);
+		dq_tgt = tmp_type50_msg->crb1.dq;
+		dq_tgt_len = sizeof(tmp_type50_msg->crb1.dq);
+		u_tgt = tmp_type50_msg->crb1.u;
+		u_tgt_len = sizeof(tmp_type50_msg->crb1.u);
+		inp_tgt = tmp_type50_msg->crb1.message;
+		inp_tgt_len = sizeof(tmp_type50_msg->crb1.message);
+	} else {
+		tmp_type50_msg->crb2.header.msg_len = TYPE50_CRB2_LEN;
+		tmp_type50_msg->crb2.keyblock_type = TYPE50_CRB2_FMT;
+		p_tgt = tmp_type50_msg->crb2.p;
+		p_tgt_len = sizeof(tmp_type50_msg->crb2.p);
+		q_tgt = tmp_type50_msg->crb2.q;
+		q_tgt_len = sizeof(tmp_type50_msg->crb2.q);
+		dp_tgt = tmp_type50_msg->crb2.dp;
+		dp_tgt_len = sizeof(tmp_type50_msg->crb2.dp);
+		dq_tgt = tmp_type50_msg->crb2.dq;
+		dq_tgt_len = sizeof(tmp_type50_msg->crb2.dq);
+		u_tgt = tmp_type50_msg->crb2.u;
+		u_tgt_len = sizeof(tmp_type50_msg->crb2.u);
+		inp_tgt = tmp_type50_msg->crb2.message;
+		inp_tgt_len = sizeof(tmp_type50_msg->crb2.message);
+	}
+
+	p_tgt += (p_tgt_len - long_len);
+	if (copy_from_user(p_tgt, icaMsg_p->np_prime + long_offset, long_len))
+		return SEN_RELEASED;
+	if (is_empty(p_tgt, long_len))
+		return SEN_USER_ERROR;
+	q_tgt += (q_tgt_len - short_len);
+	if (copy_from_user(q_tgt, icaMsg_p->nq_prime, short_len))
+		return SEN_RELEASED;
+	if (is_empty(q_tgt, short_len))
+		return SEN_USER_ERROR;
+	dp_tgt += (dp_tgt_len - long_len);
+	if (copy_from_user(dp_tgt, icaMsg_p->bp_key + long_offset, long_len))
+		return SEN_RELEASED;
+	if (is_empty(dp_tgt, long_len))
+		return SEN_USER_ERROR;
+	dq_tgt += (dq_tgt_len - short_len);
+	if (copy_from_user(dq_tgt, icaMsg_p->bq_key, short_len))
+		return SEN_RELEASED;
+	if (is_empty(dq_tgt, short_len))
+		return SEN_USER_ERROR;
+	u_tgt += (u_tgt_len - long_len);
+	if (copy_from_user(u_tgt, icaMsg_p->u_mult_inv + long_offset, long_len))
+		return SEN_RELEASED;
+	if (is_empty(u_tgt, long_len))
+		return SEN_USER_ERROR;
+	inp_tgt += (inp_tgt_len - mod_len);
+	if (copy_from_user(inp_tgt, icaMsg_p->inputdata, mod_len))
+		return SEN_RELEASED;
+	if (is_empty(inp_tgt, mod_len))
+		return SEN_USER_ERROR;
+
+	*z90cMsg_l_p = tmp_size - CALLER_HEADER;
+
+	return 0;
+}
+
 int
 convert_request(unsigned char *buffer, int func, unsigned short function,
 		int cdx, int dev_type, int *msg_l_p, unsigned char *msg_p)
@@ -2071,6 +2339,16 @@ convert_request(unsigned char *buffer, int func, unsigned short function,
 				cdx, msg_l_p, (struct type6_msg *) msg_p,
 				dev_type);
 	}
+	if (dev_type == CEX2A) {
+		if (func == ICARSACRT)
+			return ICACRT_msg_to_type50CRT_msg(
+				(struct ica_rsa_modexpo_crt *) buffer,
+				msg_l_p, (union type50_msg *) msg_p);
+		else
+			return ICAMEX_msg_to_type50MEX_msg(
+				(struct ica_rsa_modexpo *) buffer,
+				msg_l_p, (union type50_msg *) msg_p);
+	}
 
 	return 0;
 }
@@ -2081,8 +2359,8 @@ unset_ext_bitlens(void)
 {
 	if (!ext_bitlens_msg_count) {
 		PRINTK("Unable to use coprocessors for extended bitlengths. "
-		       "Using PCICAs (if present) for extended bitlengths. "
-		       "This is not an error.\n");
+		       "Using PCICAs/CEX2As (if present) for extended "
+		       "bitlengths. This is not an error.\n");
 		ext_bitlens_msg_count++;
 	}
 	ext_bitlens = 0;
@@ -2094,6 +2372,7 @@ convert_response(unsigned char *response, unsigned char *buffer,
 {
 	struct ica_rsa_modexpo *icaMsg_p = (struct ica_rsa_modexpo *) buffer;
 	struct error_hdr *errh_p = (struct error_hdr *) response;
+	struct type80_hdr *t80h_p = (struct type80_hdr *) response;
 	struct type84_hdr *t84h_p = (struct type84_hdr *) response;
 	struct type86_fmt2_msg *t86m_p =  (struct type86_fmt2_msg *) response;
 	int reply_code, service_rc, service_rs, src_l;
@@ -2108,6 +2387,7 @@ convert_response(unsigned char *response, unsigned char *buffer,
 	src_l = 0;
 	switch (errh_p->type) {
 	case TYPE82_RSP_CODE:
+	case TYPE88_RSP_CODE:
 		reply_code = errh_p->reply_code;
 		src_p = (unsigned char *)errh_p;
 		PRINTK("Hardware error: Type %02X Message Header: "
@@ -2116,6 +2396,10 @@ convert_response(unsigned char *response, unsigned char *buffer,
 		       src_p[0], src_p[1], src_p[2], src_p[3],
 		       src_p[4], src_p[5], src_p[6], src_p[7]);
 		break;
+	case TYPE80_RSP_CODE:
+		src_l = icaMsg_p->outputdatalength;
+		src_p = response + (int)t80h_p->len - src_l;
+		break;
 	case TYPE84_RSP_CODE:
 		src_l = icaMsg_p->outputdatalength;
 		src_p = response + (int)t84h_p->len - src_l;
@@ -2202,6 +2486,7 @@ convert_response(unsigned char *response, unsigned char *buffer,
 	if (reply_code)
 		switch (reply_code) {
 		case REP82_ERROR_OPERAND_INVALID:
+		case REP88_ERROR_MESSAGE_MALFORMD:
 			return REC_OPERAND_INV;
 		case REP82_ERROR_OPERAND_SIZE:
 			return REC_OPERAND_SIZE;
diff --git a/drivers/s390/crypto/z90main.c b/drivers/s390/crypto/z90main.c
index 4010f2bb85af..135ae04e6e75 100644
--- a/drivers/s390/crypto/z90main.c
+++ b/drivers/s390/crypto/z90main.c
@@ -34,7 +34,6 @@
 #include <linux/miscdevice.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/kobject_uevent.h>
 #include <linux/proc_fs.h>
 #include <linux/syscalls.h>
 #include "z90crypt.h"
@@ -229,7 +228,7 @@ struct device_x {
  */
 struct device {
 	int		 dev_type;	    // PCICA, PCICC, PCIXCC_MCL2,
-					    // PCIXCC_MCL3, CEX2C
+					    // PCIXCC_MCL3, CEX2C, CEX2A
 	enum devstat	 dev_stat;	    // current device status
 	int		 dev_self_x;	    // Index in array
 	int		 disabled;	    // Set when device is in error
@@ -296,26 +295,30 @@ struct caller {
 /**
  * Function prototypes from z90hardware.c
  */
-enum hdstat query_online(int, int, int, int *, int *);
-enum devstat reset_device(int, int, int);
-enum devstat send_to_AP(int, int, int, unsigned char *);
-enum devstat receive_from_AP(int, int, int, unsigned char *, unsigned char *);
-int convert_request(unsigned char *, int, short, int, int, int *,
-		    unsigned char *);
-int convert_response(unsigned char *, unsigned char *, int *, unsigned char *);
+enum hdstat query_online(int deviceNr, int cdx, int resetNr, int *q_depth,
+			 int *dev_type);
+enum devstat reset_device(int deviceNr, int cdx, int resetNr);
+enum devstat send_to_AP(int dev_nr, int cdx, int msg_len, unsigned char *msg_ext);
+enum devstat receive_from_AP(int dev_nr, int cdx, int resplen,
+			     unsigned char *resp, unsigned char *psmid);
+int convert_request(unsigned char *buffer, int func, unsigned short function,
+		    int cdx, int dev_type, int *msg_l_p, unsigned char *msg_p);
+int convert_response(unsigned char *response, unsigned char *buffer,
+		     int *respbufflen_p, unsigned char *resp_buff);
 
 /**
  * Low level function prototypes
  */
-static int create_z90crypt(int *);
-static int refresh_z90crypt(int *);
-static int find_crypto_devices(struct status *);
-static int create_crypto_device(int);
-static int destroy_crypto_device(int);
+static int create_z90crypt(int *cdx_p);
+static int refresh_z90crypt(int *cdx_p);
+static int find_crypto_devices(struct status *deviceMask);
+static int create_crypto_device(int index);
+static int destroy_crypto_device(int index);
 static void destroy_z90crypt(void);
-static int refresh_index_array(struct status *, struct device_x *);
-static int probe_device_type(struct device *);
-static int probe_PCIXCC_type(struct device *);
+static int refresh_index_array(struct status *status_str,
+			       struct device_x *index_array);
+static int probe_device_type(struct device *devPtr);
+static int probe_PCIXCC_type(struct device *devPtr);
 
 /**
  * proc fs definitions
@@ -426,7 +429,7 @@ static struct miscdevice z90crypt_misc_device = {
 MODULE_AUTHOR("zSeries Linux Crypto Team: Robert H. Burroughs, Eric D. Rossman"
 	      "and Jochen Roehrig");
 MODULE_DESCRIPTION("zSeries Linux Cryptographic Coprocessor device driver, "
-		   "Copyright 2001, 2004 IBM Corporation");
+		   "Copyright 2001, 2005 IBM Corporation");
 MODULE_LICENSE("GPL");
 module_param(domain, int, 0);
 MODULE_PARM_DESC(domain, "domain index for device");
@@ -861,6 +864,12 @@ get_status_CEX2Ccount(void)
 }
 
 static inline int
+get_status_CEX2Acount(void)
+{
+	return z90crypt.hdware_info->type_mask[CEX2A].st_count;
+}
+
+static inline int
 get_status_requestq_count(void)
 {
 	return requestq_count;
@@ -1009,11 +1018,13 @@ static inline int
 select_device_type(int *dev_type_p, int bytelength)
 {
 	static int count = 0;
-	int PCICA_avail, PCIXCC_MCL3_avail, CEX2C_avail, index_to_use;
+	int PCICA_avail, PCIXCC_MCL3_avail, CEX2C_avail, CEX2A_avail,
+	    index_to_use;
 	struct status *stat;
 	if ((*dev_type_p != PCICC) && (*dev_type_p != PCICA) &&
 	    (*dev_type_p != PCIXCC_MCL2) && (*dev_type_p != PCIXCC_MCL3) &&
-	    (*dev_type_p != CEX2C) && (*dev_type_p != ANYDEV))
+	    (*dev_type_p != CEX2C) && (*dev_type_p != CEX2A) &&
+	    (*dev_type_p != ANYDEV))
 		return -1;
 	if (*dev_type_p != ANYDEV) {
 		stat = &z90crypt.hdware_info->type_mask[*dev_type_p];
@@ -1023,7 +1034,13 @@ select_device_type(int *dev_type_p, int bytelength)
 		return -1;
 	}
 
-	/* Assumption: PCICA, PCIXCC_MCL3, and CEX2C are all similar in speed */
+	/**
+	 * Assumption: PCICA, PCIXCC_MCL3, CEX2C, and CEX2A are all similar in
+	 * speed.
+	 *
+	 * PCICA and CEX2A do NOT co-exist, so it would be either one or the
+	 * other present.
+	 */
 	stat = &z90crypt.hdware_info->type_mask[PCICA];
 	PCICA_avail = stat->st_count -
 			(stat->disabled_count + stat->user_disabled_count);
@@ -1033,29 +1050,38 @@ select_device_type(int *dev_type_p, int bytelength)
 	stat = &z90crypt.hdware_info->type_mask[CEX2C];
 	CEX2C_avail = stat->st_count -
 			(stat->disabled_count + stat->user_disabled_count);
-	if (PCICA_avail || PCIXCC_MCL3_avail || CEX2C_avail) {
+	stat = &z90crypt.hdware_info->type_mask[CEX2A];
+	CEX2A_avail = stat->st_count -
+			(stat->disabled_count + stat->user_disabled_count);
+	if (PCICA_avail || PCIXCC_MCL3_avail || CEX2C_avail || CEX2A_avail) {
 		/**
-		 * bitlength is a factor, PCICA is the most capable, even with
-		 * the new MCL for PCIXCC.
+		 * bitlength is a factor, PCICA or CEX2A are the most capable,
+		 * even with the new MCL for PCIXCC.
 		 */
 		if ((bytelength < PCIXCC_MIN_MOD_SIZE) ||
 		    (!ext_bitlens && (bytelength < OLD_PCIXCC_MIN_MOD_SIZE))) {
-			if (!PCICA_avail)
-				return -1;
-			else {
+			if (PCICA_avail) {
 				*dev_type_p = PCICA;
 				return 0;
 			}
+			if (CEX2A_avail) {
+				*dev_type_p = CEX2A;
+				return 0;
+			}
+			return -1;
 		}
 
 		index_to_use = count % (PCICA_avail + PCIXCC_MCL3_avail +
-					CEX2C_avail);
+					CEX2C_avail + CEX2A_avail);
 		if (index_to_use < PCICA_avail)
 			*dev_type_p = PCICA;
 		else if (index_to_use < (PCICA_avail + PCIXCC_MCL3_avail))
 			*dev_type_p = PCIXCC_MCL3;
-		else
+		else if (index_to_use < (PCICA_avail + PCIXCC_MCL3_avail +
+					 CEX2C_avail))
 			*dev_type_p = CEX2C;
+		else
+			*dev_type_p = CEX2A;
 		count++;
 		return 0;
 	}
@@ -1360,7 +1386,7 @@ build_caller(struct work_element *we_p, short function)
 
 	if ((we_p->devtype != PCICC) && (we_p->devtype != PCICA) &&
 	    (we_p->devtype != PCIXCC_MCL2) && (we_p->devtype != PCIXCC_MCL3) &&
-	    (we_p->devtype != CEX2C))
+	    (we_p->devtype != CEX2C) && (we_p->devtype != CEX2A))
 		return SEN_NOT_AVAIL;
 
 	memcpy(caller_p->caller_id, we_p->caller_id,
@@ -1429,7 +1455,8 @@ get_crypto_request_buffer(struct work_element *we_p)
 
 	if ((we_p->devtype != PCICA) && (we_p->devtype != PCICC) &&
 	    (we_p->devtype != PCIXCC_MCL2) && (we_p->devtype != PCIXCC_MCL3) &&
-	    (we_p->devtype != CEX2C) && (we_p->devtype != ANYDEV)) {
+	    (we_p->devtype != CEX2C) && (we_p->devtype != CEX2A) &&
+	    (we_p->devtype != ANYDEV)) {
 		PRINTK("invalid device type\n");
 		return SEN_USER_ERROR;
 	}
@@ -1504,8 +1531,9 @@ get_crypto_request_buffer(struct work_element *we_p)
 
 	function = PCI_FUNC_KEY_ENCRYPT;
 	switch (we_p->devtype) {
-	/* PCICA does everything with a simple RSA mod-expo operation */
+	/* PCICA and CEX2A do everything with a simple RSA mod-expo operation */
 	case PCICA:
+	case CEX2A:
 		function = PCI_FUNC_KEY_ENCRYPT;
 		break;
 	/**
@@ -1663,7 +1691,8 @@ z90crypt_rsa(struct priv_data *private_data_p, pid_t pid,
 		 * trigger a fallback to software.
 		 */
 		case -EINVAL:
-			if (we_p->devtype != PCICA)
+			if ((we_p->devtype != PCICA) &&
+			    (we_p->devtype != CEX2A))
 				rv = -EGETBUFF;
 			break;
 		case -ETIMEOUT:
@@ -1780,6 +1809,12 @@ z90crypt_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 			ret = -EFAULT;
 		break;
 
+	case Z90STAT_CEX2ACOUNT:
+		tempstat = get_status_CEX2Acount();
+		if (copy_to_user((int __user *)arg, &tempstat, sizeof(int)) != 0)
+			ret = -EFAULT;
+		break;
+
 	case Z90STAT_REQUESTQ_COUNT:
 		tempstat = get_status_requestq_count();
 		if (copy_to_user((int __user *)arg, &tempstat, sizeof(int)) != 0)
@@ -2020,6 +2055,8 @@ z90crypt_status(char *resp_buff, char **start, off_t offset,
 		get_status_PCIXCCMCL3count());
 	len += sprintf(resp_buff+len, "CEX2C count: %d\n",
 		get_status_CEX2Ccount());
+	len += sprintf(resp_buff+len, "CEX2A count: %d\n",
+		get_status_CEX2Acount());
 	len += sprintf(resp_buff+len, "requestq count: %d\n",
 		get_status_requestq_count());
 	len += sprintf(resp_buff+len, "pendingq count: %d\n",
@@ -2027,8 +2064,8 @@ z90crypt_status(char *resp_buff, char **start, off_t offset,
 	len += sprintf(resp_buff+len, "Total open handles: %d\n\n",
 		get_status_totalopen_count());
 	len += sprinthx(
-		"Online devices: 1: PCICA, 2: PCICC, 3: PCIXCC (MCL2), "
-		"4: PCIXCC (MCL3), 5: CEX2C",
+		"Online devices: 1=PCICA 2=PCICC 3=PCIXCC(MCL2) "
+		"4=PCIXCC(MCL3) 5=CEX2C 6=CEX2A",
 		resp_buff+len,
 		get_status_status_mask(workarea),
 		Z90CRYPT_NUM_APS);
@@ -2141,6 +2178,7 @@ z90crypt_status_write(struct file *file, const char __user *buffer,
 		case '3':	// PCIXCC_MCL2
 		case '4':	// PCIXCC_MCL3
 		case '5':	// CEX2C
+		case '6':       // CEX2A
 			j++;
 			break;
 		case 'd':
@@ -3008,7 +3046,9 @@ create_crypto_device(int index)
 			z90crypt.hdware_info->device_type_array[index] = 4;
 		else if (deviceType == CEX2C)
 			z90crypt.hdware_info->device_type_array[index] = 5;
-		else
+		else if (deviceType == CEX2A)
+			z90crypt.hdware_info->device_type_array[index] = 6;
+		else // No idea how this would happen.
 			z90crypt.hdware_info->device_type_array[index] = -1;
 	}
 
diff --git a/drivers/s390/net/Kconfig b/drivers/s390/net/Kconfig
index a7efc394515e..548854754921 100644
--- a/drivers/s390/net/Kconfig
+++ b/drivers/s390/net/Kconfig
@@ -1,5 +1,5 @@
 menu "S/390 network device drivers"
-	depends on NETDEVICES && ARCH_S390
+	depends on NETDEVICES && S390
 
 config LCS
 	tristate "Lan Channel Station Interface"
diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c
index 6b63d21612ec..e70af7f39946 100644
--- a/drivers/s390/net/claw.c
+++ b/drivers/s390/net/claw.c
@@ -1603,7 +1603,7 @@ dumpit(char* buf, int len)
         __u32      ct, sw, rm, dup;
         char       *ptr, *rptr;
         char       tbuf[82], tdup[82];
-#if (CONFIG_ARCH_S390X)
+#if (CONFIG_64BIT)
         char       addr[22];
 #else
         char       addr[12];
@@ -1619,7 +1619,7 @@ dumpit(char* buf, int len)
         dup = 0;
         for ( ct=0; ct < len; ct++, ptr++, rptr++ )  {
                 if (sw == 0) {
-#if (CONFIG_ARCH_S390X)
+#if (CONFIG_64BIT)
                         sprintf(addr, "%16.16lX",(unsigned long)rptr);
 #else
                         sprintf(addr, "%8.8X",(__u32)rptr);
@@ -1634,7 +1634,7 @@ dumpit(char* buf, int len)
                 if (sw == 8) {
                         strcat(bhex, "  ");
                 }
-#if (CONFIG_ARCH_S390X)
+#if (CONFIG_64BIT)
                 sprintf(tbuf,"%2.2lX", (unsigned long)*ptr);
 #else
                 sprintf(tbuf,"%2.2X", (__u32)*ptr);
diff --git a/drivers/s390/net/cu3088.c b/drivers/s390/net/cu3088.c
index 0075894c71db..77dacb465732 100644
--- a/drivers/s390/net/cu3088.c
+++ b/drivers/s390/net/cu3088.c
@@ -1,5 +1,5 @@
 /*
- * $Id: cu3088.c,v 1.35 2005/03/30 19:28:52 richtera Exp $
+ * $Id: cu3088.c,v 1.36 2005/10/25 14:37:17 cohuck Exp $
  *
  * CTC / LCS ccw_device driver
  *
@@ -27,6 +27,7 @@
 #include <linux/module.h>
 #include <linux/err.h>
 
+#include <asm/s390_rdev.h>
 #include <asm/ccwdev.h>
 #include <asm/ccwgroup.h>
 
diff --git a/drivers/s390/net/iucv.c b/drivers/s390/net/iucv.c
index df7647c3c100..ea8177392564 100644
--- a/drivers/s390/net/iucv.c
+++ b/drivers/s390/net/iucv.c
@@ -1,5 +1,5 @@
 /* 
- * $Id: iucv.c,v 1.45 2005/04/26 22:59:06 braunu Exp $
+ * $Id: iucv.c,v 1.47 2005/11/21 11:35:22 mschwide Exp $
  *
  * IUCV network driver
  *
@@ -29,7 +29,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * RELEASE-TAG: IUCV lowlevel driver $Revision: 1.45 $
+ * RELEASE-TAG: IUCV lowlevel driver $Revision: 1.47 $
  *
  */
 
@@ -54,7 +54,7 @@
 #include <asm/s390_ext.h>
 #include <asm/ebcdic.h>
 #include <asm/smp.h>
-#include <asm/ccwdev.h> //for root device stuff
+#include <asm/s390_rdev.h>
 
 /* FLAGS:
  * All flags are defined in the field IPFLAGS1 of each function
@@ -355,7 +355,7 @@ do { \
 static void
 iucv_banner(void)
 {
-	char vbuf[] = "$Revision: 1.45 $";
+	char vbuf[] = "$Revision: 1.47 $";
 	char *version = vbuf;
 
 	if ((version = strchr(version, ':'))) {
@@ -477,7 +477,7 @@ grab_param(void)
 		ptr++;
 		if (ptr >= iucv_param_pool + PARAM_POOL_SIZE)
 			ptr = iucv_param_pool;
-	} while (atomic_compare_and_swap(0, 1, &ptr->in_use));
+	} while (atomic_cmpxchg(&ptr->in_use, 0, 1) != 0);
 	hint = ptr - iucv_param_pool;
 
 	memset(&ptr->param, 0, sizeof(ptr->param));
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index f8f55cc468ba..97f927c01a82 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -65,6 +65,7 @@
 #include <asm/timex.h>
 #include <asm/semaphore.h>
 #include <asm/uaccess.h>
+#include <asm/s390_rdev.h>
 
 #include "qeth.h"
 #include "qeth_mpc.h"
@@ -1396,7 +1397,7 @@ qeth_idx_activate_get_answer(struct qeth_channel *channel,
 	channel->ccw.cda = (__u32) __pa(iob->data);
 
 	wait_event(card->wait_q,
-		   atomic_compare_and_swap(0,1,&channel->irq_pending) == 0);
+		   atomic_cmpxchg(&channel->irq_pending, 0, 1) == 0);
 	QETH_DBF_TEXT(setup, 6, "noirqpnd");
 	spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
 	rc = ccw_device_start(channel->ccwdev,
@@ -1463,7 +1464,7 @@ qeth_idx_activate_channel(struct qeth_channel *channel,
 	memcpy(QETH_IDX_ACT_QDIO_DEV_REALADDR(iob->data), &temp, 2);
 
 	wait_event(card->wait_q,
-		   atomic_compare_and_swap(0,1,&channel->irq_pending) == 0);
+		   atomic_cmpxchg(&channel->irq_pending, 0, 1) == 0);
 	QETH_DBF_TEXT(setup, 6, "noirqpnd");
 	spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
 	rc = ccw_device_start(channel->ccwdev,
@@ -1616,7 +1617,7 @@ qeth_issue_next_read(struct qeth_card *card)
 	}
 	qeth_setup_ccw(&card->read, iob->data, QETH_BUFSIZE);
 	wait_event(card->wait_q,
-		   atomic_compare_and_swap(0,1,&card->read.irq_pending) == 0);
+		   atomic_cmpxchg(&card->read.irq_pending, 0, 1) == 0);
 	QETH_DBF_TEXT(trace, 6, "noirqpnd");
 	rc = ccw_device_start(card->read.ccwdev, &card->read.ccw,
 			      (addr_t) iob, 0, 0);
@@ -1882,7 +1883,7 @@ qeth_send_control_data(struct qeth_card *card, int len,
 	spin_unlock_irqrestore(&card->lock, flags);
 	QETH_DBF_HEX(control, 2, iob->data, QETH_DBF_CONTROL_LEN);
 	wait_event(card->wait_q,
-		   atomic_compare_and_swap(0,1,&card->write.irq_pending) == 0);
+		   atomic_cmpxchg(&card->write.irq_pending, 0, 1) == 0);
 	qeth_prepare_control_data(card, len, iob);
 	if (IS_IPA(iob->data))
 		timer.expires = jiffies + QETH_IPA_TIMEOUT;
@@ -1924,7 +1925,7 @@ qeth_osn_send_control_data(struct qeth_card *card, int len,
 	QETH_DBF_TEXT(trace, 5, "osndctrd");
 
 	wait_event(card->wait_q,
-		   atomic_compare_and_swap(0,1,&card->write.irq_pending) == 0);
+		   atomic_cmpxchg(&card->write.irq_pending, 0, 1) == 0);
 	qeth_prepare_control_data(card, len, iob);
 	QETH_DBF_TEXT(trace, 6, "osnoirqp");
 	spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags);
@@ -4236,9 +4237,8 @@ qeth_do_send_packet_fast(struct qeth_card *card, struct qeth_qdio_out_q *queue,
 	QETH_DBF_TEXT(trace, 6, "dosndpfa");
 
 	/* spin until we get the queue ... */
-	while (atomic_compare_and_swap(QETH_OUT_Q_UNLOCKED,
-				       QETH_OUT_Q_LOCKED,
-				       &queue->state));
+	while (atomic_cmpxchg(&queue->state, QETH_OUT_Q_UNLOCKED,
+			      QETH_OUT_Q_LOCKED) != QETH_OUT_Q_UNLOCKED);
 	/* ... now we've got the queue */
 	index = queue->next_buf_to_fill;
 	buffer = &queue->bufs[queue->next_buf_to_fill];
@@ -4292,9 +4292,8 @@ qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
 	QETH_DBF_TEXT(trace, 6, "dosndpkt");
 
 	/* spin until we get the queue ... */
-	while (atomic_compare_and_swap(QETH_OUT_Q_UNLOCKED,
-				       QETH_OUT_Q_LOCKED,
-				       &queue->state));
+	while (atomic_cmpxchg(&queue->state, QETH_OUT_Q_UNLOCKED,
+			      QETH_OUT_Q_LOCKED) != QETH_OUT_Q_UNLOCKED);
 	start_index = queue->next_buf_to_fill;
 	buffer = &queue->bufs[queue->next_buf_to_fill];
 	/*
diff --git a/drivers/s390/s390_rdev.c b/drivers/s390/s390_rdev.c
new file mode 100644
index 000000000000..566cc3d185b6
--- /dev/null
+++ b/drivers/s390/s390_rdev.c
@@ -0,0 +1,53 @@
+/*
+ *  drivers/s390/s390_rdev.c
+ *  s390 root device
+ *   $Revision: 1.2 $
+ *
+ *    Copyright (C) 2002, 2005 IBM Deutschland Entwicklung GmbH,
+ *			 IBM Corporation
+ *    Author(s): Cornelia Huck (cohuck@de.ibm.com)
+ *		  Carsten Otte  (cotte@de.ibm.com)
+ */
+
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/device.h>
+#include <asm/s390_rdev.h>
+
+static void
+s390_root_dev_release(struct device *dev)
+{
+	kfree(dev);
+}
+
+struct device *
+s390_root_dev_register(const char *name)
+{
+	struct device *dev;
+	int ret;
+
+	if (!strlen(name))
+		return ERR_PTR(-EINVAL);
+	dev = kmalloc(sizeof(struct device), GFP_KERNEL);
+	if (!dev)
+		return ERR_PTR(-ENOMEM);
+	memset(dev, 0, sizeof(struct device));
+	strncpy(dev->bus_id, name, min(strlen(name), (size_t)BUS_ID_SIZE));
+	dev->release = s390_root_dev_release;
+	ret = device_register(dev);
+	if (ret) {
+		kfree(dev);
+		return ERR_PTR(ret);
+	}
+	return dev;
+}
+
+void
+s390_root_dev_unregister(struct device *dev)
+{
+	if (dev)
+		device_unregister(dev);
+}
+
+EXPORT_SYMBOL(s390_root_dev_register);
+EXPORT_SYMBOL(s390_root_dev_unregister);
diff --git a/drivers/s390/s390mach.c b/drivers/s390/s390mach.c
index 4191fd9d4d11..3bf466603512 100644
--- a/drivers/s390/s390mach.c
+++ b/drivers/s390/s390mach.c
@@ -23,7 +23,7 @@
 
 static struct semaphore m_sem;
 
-extern int css_process_crw(int);
+extern int css_process_crw(int, int);
 extern int chsc_process_crw(void);
 extern int chp_process_crw(int, int);
 extern void css_reiterate_subchannels(void);
@@ -49,9 +49,10 @@ s390_handle_damage(char *msg)
 static int
 s390_collect_crw_info(void *param)
 {
-	struct crw crw;
+	struct crw crw[2];
 	int ccode, ret, slow;
 	struct semaphore *sem;
+	unsigned int chain;
 
 	sem = (struct semaphore *)param;
 	/* Set a nice name. */
@@ -59,25 +60,50 @@ s390_collect_crw_info(void *param)
 repeat:
 	down_interruptible(sem);
 	slow = 0;
+	chain = 0;
 	while (1) {
-		ccode = stcrw(&crw);
+		if (unlikely(chain > 1)) {
+			struct crw tmp_crw;
+
+			printk(KERN_WARNING"%s: Code does not support more "
+			       "than two chained crws; please report to "
+			       "linux390@de.ibm.com!\n", __FUNCTION__);
+			ccode = stcrw(&tmp_crw);
+			printk(KERN_WARNING"%s: crw reports slct=%d, oflw=%d, "
+			       "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n",
+			       __FUNCTION__, tmp_crw.slct, tmp_crw.oflw,
+			       tmp_crw.chn, tmp_crw.rsc, tmp_crw.anc,
+			       tmp_crw.erc, tmp_crw.rsid);
+			printk(KERN_WARNING"%s: This was crw number %x in the "
+			       "chain\n", __FUNCTION__, chain);
+			if (ccode != 0)
+				break;
+			chain = tmp_crw.chn ? chain + 1 : 0;
+			continue;
+		}
+		ccode = stcrw(&crw[chain]);
 		if (ccode != 0)
 			break;
 		DBG(KERN_DEBUG "crw_info : CRW reports slct=%d, oflw=%d, "
 		    "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n",
-		    crw.slct, crw.oflw, crw.chn, crw.rsc, crw.anc,
-		    crw.erc, crw.rsid);
+		    crw[chain].slct, crw[chain].oflw, crw[chain].chn,
+		    crw[chain].rsc, crw[chain].anc, crw[chain].erc,
+		    crw[chain].rsid);
 		/* Check for overflows. */
-		if (crw.oflw) {
+		if (crw[chain].oflw) {
 			pr_debug("%s: crw overflow detected!\n", __FUNCTION__);
 			css_reiterate_subchannels();
+			chain = 0;
 			slow = 1;
 			continue;
 		}
-		switch (crw.rsc) {
+		switch (crw[chain].rsc) {
 		case CRW_RSC_SCH:
-			pr_debug("source is subchannel %04X\n", crw.rsid);
-			ret = css_process_crw (crw.rsid);
+			if (crw[0].chn && !chain)
+				break;
+			pr_debug("source is subchannel %04X\n", crw[0].rsid);
+			ret = css_process_crw (crw[0].rsid,
+					       chain ? crw[1].rsid : 0);
 			if (ret == -EAGAIN)
 				slow = 1;
 			break;
@@ -85,18 +111,18 @@ repeat:
 			pr_debug("source is monitoring facility\n");
 			break;
 		case CRW_RSC_CPATH:
-			pr_debug("source is channel path %02X\n", crw.rsid);
-			switch (crw.erc) {
+			pr_debug("source is channel path %02X\n", crw[0].rsid);
+			switch (crw[0].erc) {
 			case CRW_ERC_IPARM: /* Path has come. */
-				ret = chp_process_crw(crw.rsid, 1);
+				ret = chp_process_crw(crw[0].rsid, 1);
 				break;
 			case CRW_ERC_PERRI: /* Path has gone. */
 			case CRW_ERC_PERRN:
-				ret = chp_process_crw(crw.rsid, 0);
+				ret = chp_process_crw(crw[0].rsid, 0);
 				break;
 			default:
 				pr_debug("Don't know how to handle erc=%x\n",
-					 crw.erc);
+					 crw[0].erc);
 				ret = 0;
 			}
 			if (ret == -EAGAIN)
@@ -115,6 +141,8 @@ repeat:
 			pr_debug("unknown source\n");
 			break;
 		}
+		/* chain is always 0 or 1 here. */
+		chain = crw[chain].chn ? chain + 1 : 0;
 	}
 	if (slow)
 		queue_work(slow_path_wq, &slow_path_work);
@@ -218,7 +246,7 @@ s390_revalidate_registers(struct mci *mci)
 		 */
 		kill_task = 1;
 
-#ifndef __s390x__
+#ifndef CONFIG_64BIT
 	asm volatile("ld 0,0(%0)\n"
 		     "ld 2,8(%0)\n"
 		     "ld 4,16(%0)\n"
@@ -227,7 +255,7 @@ s390_revalidate_registers(struct mci *mci)
 #endif
 
 	if (MACHINE_HAS_IEEE) {
-#ifdef __s390x__
+#ifdef CONFIG_64BIT
 		fpt_save_area = &S390_lowcore.floating_pt_save_area;
 		fpt_creg_save_area = &S390_lowcore.fpt_creg_save_area;
 #else
@@ -286,7 +314,7 @@ s390_revalidate_registers(struct mci *mci)
 		 */
 		s390_handle_damage("invalid control registers.");
 	else
-#ifdef __s390x__
+#ifdef CONFIG_64BIT
 		asm volatile("lctlg 0,15,0(%0)"
 			     : : "a" (&S390_lowcore.cregs_save_area));
 #else
@@ -299,7 +327,7 @@ s390_revalidate_registers(struct mci *mci)
 	 * can't write something sensible into that register.
 	 */
 
-#ifdef __s390x__
+#ifdef CONFIG_64BIT
 	/*
 	 * See if we can revalidate the TOD programmable register with its
 	 * old contents (should be zero) otherwise set it to zero.
@@ -356,7 +384,7 @@ s390_do_machine_check(struct pt_regs *regs)
 		if (mci->b) {
 			/* Processing backup -> verify if we can survive this */
 			u64 z_mcic, o_mcic, t_mcic;
-#ifdef __s390x__
+#ifdef CONFIG_64BIT
 			z_mcic = (1ULL<<63 | 1ULL<<59 | 1ULL<<29);
 			o_mcic = (1ULL<<43 | 1ULL<<42 | 1ULL<<41 | 1ULL<<40 |
 				  1ULL<<36 | 1ULL<<35 | 1ULL<<34 | 1ULL<<32 |
diff --git a/drivers/s390/sysinfo.c b/drivers/s390/sysinfo.c
index 87c2db1bd4f5..66da840c9316 100644
--- a/drivers/s390/sysinfo.c
+++ b/drivers/s390/sysinfo.c
@@ -106,7 +106,7 @@ static inline int stsi (void *sysinfo,
 {
 	int cc, retv;
 
-#ifndef CONFIG_ARCH_S390X
+#ifndef CONFIG_64BIT
 	__asm__ __volatile__ (	"lr\t0,%2\n"
 				"\tlr\t1,%3\n"
 				"\tstsi\t0(%4)\n"
diff --git a/drivers/scsi/.gitignore b/drivers/scsi/.gitignore
new file mode 100644
index 000000000000..b385af314356
--- /dev/null
+++ b/drivers/scsi/.gitignore
@@ -0,0 +1,3 @@
+53c700_d.h
+53c7xx_d.h
+53c7xx_u.h
diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
index e7ad269041a4..4ce7438608ec 100644
--- a/drivers/scsi/53c700.c
+++ b/drivers/scsi/53c700.c
@@ -857,7 +857,7 @@ process_extended_message(struct Scsi_Host *host,
 		printk(KERN_INFO "scsi%d (%d:%d): Unexpected message %s: ",
 		       host->host_no, pun, lun,
 		       NCR_700_phase[(dsps & 0xf00) >> 8]);
-		scsi_print_msg(hostdata->msgin);
+		spi_print_msg(hostdata->msgin);
 		printk("\n");
 		/* just reject it */
 		hostdata->msgout[0] = A_REJECT_MSG;
@@ -887,7 +887,7 @@ process_message(struct Scsi_Host *host,	struct NCR_700_Host_Parameters *hostdata
 #ifdef NCR_700_DEBUG
 	printk("scsi%d (%d:%d): message %s: ", host->host_no, pun, lun,
 	       NCR_700_phase[(dsps & 0xf00) >> 8]);
-	scsi_print_msg(hostdata->msgin);
+	spi_print_msg(hostdata->msgin);
 	printk("\n");
 #endif
 
@@ -939,7 +939,7 @@ process_message(struct Scsi_Host *host,	struct NCR_700_Host_Parameters *hostdata
 		       host->host_no, pun, lun,
 		       NCR_700_phase[(dsps & 0xf00) >> 8]);
 
-		scsi_print_msg(hostdata->msgin);
+		spi_print_msg(hostdata->msgin);
 		printk("\n");
 		/* just reject it */
 		hostdata->msgout[0] = A_REJECT_MSG;
diff --git a/drivers/scsi/53c700.h b/drivers/scsi/53c700.h
index 362d78483d09..a8c83bb03630 100644
--- a/drivers/scsi/53c700.h
+++ b/drivers/scsi/53c700.h
@@ -238,21 +238,23 @@ struct NCR_700_Host_Parameters {
 #ifdef CONFIG_53C700_LE_ON_BE
 #define bE	(hostdata->force_le_on_be ? 0 : 3)
 #define	bSWAP	(hostdata->force_le_on_be)
-/* This is terrible, but there's no raw version of ioread32.  That means
- * that on a be board we swap twice (once in ioread32 and once again to 
- * get the value correct) */
-#define bS_to_io(x)	((hostdata->force_le_on_be) ? (x) : cpu_to_le32(x))
+#define bEBus	(!hostdata->force_le_on_be)
 #elif defined(__BIG_ENDIAN)
 #define bE	3
 #define bSWAP	0
-#define bS_to_io(x)	(x)
 #elif defined(__LITTLE_ENDIAN)
 #define bE	0
 #define bSWAP	0
-#define bS_to_io(x)	(x)
 #else
 #error "__BIG_ENDIAN or __LITTLE_ENDIAN must be defined, did you include byteorder.h?"
 #endif
+#ifndef bEBus
+#ifdef CONFIG_53C700_BE_BUS
+#define bEBus	1
+#else
+#define bEBus	0
+#endif
+#endif
 #define bS_to_cpu(x)	(bSWAP ? le32_to_cpu(x) : (x))
 #define bS_to_host(x)	(bSWAP ? cpu_to_le32(x) : (x))
 
@@ -466,14 +468,15 @@ NCR_700_readl(struct Scsi_Host *host, __u32 reg)
 {
 	const struct NCR_700_Host_Parameters *hostdata
 		= (struct NCR_700_Host_Parameters *)host->hostdata[0];
-	__u32 value = ioread32(hostdata->base + reg);
+	__u32 value = bEBus ? ioread32be(hostdata->base + reg) :
+		ioread32(hostdata->base + reg);
 #if 1
 	/* sanity check the register */
 	if((reg & 0x3) != 0)
 		BUG();
 #endif
 
-	return bS_to_io(value);
+	return value;
 }
 
 static inline void
@@ -497,7 +500,8 @@ NCR_700_writel(__u32 value, struct Scsi_Host *host, __u32 reg)
 		BUG();
 #endif
 
-	iowrite32(bS_to_io(value), hostdata->base + reg);
+	bEBus ? iowrite32be(value, hostdata->base + reg): 
+		iowrite32(value, hostdata->base + reg);
 }
 
 #endif
diff --git a/drivers/scsi/53c7xx.c b/drivers/scsi/53c7xx.c
index 9cb5dd48383f..7894b8ea84bd 100644
--- a/drivers/scsi/53c7xx.c
+++ b/drivers/scsi/53c7xx.c
@@ -282,6 +282,7 @@
 #include "scsi.h"
 #include <scsi/scsi_dbg.h>
 #include <scsi/scsi_host.h>
+#include <scsi/scsi_transport_spi.h>
 #include "53c7xx.h"
 #include <linux/stat.h>
 #include <linux/stddef.h>
@@ -1724,7 +1725,7 @@ NCR53c7xx_run_tests (struct Scsi_Host *host) {
 		printk ("scsi%d : status ", host->host_no);
 		scsi_print_status (status);
 		printk ("\nscsi%d : message ", host->host_no);
-		scsi_print_msg (&msg);
+		spi_print_msg(&msg);
 		printk ("\n");
 	    } else if (hostdata->test_completed == 3) {
 		printk("scsi%d : test 2 no connection with target %d\n",
@@ -2313,7 +2314,7 @@ NCR53c7x0_dstat_sir_intr (struct Scsi_Host *host, struct
 	    printk ("scsi%d : received message", host->host_no);
 	    if (c) 
 	    	printk (" from target %d lun %d ", c->device->id, c->device->lun);
-	    scsi_print_msg ((unsigned char *) hostdata->msg_buf);
+	    spi_print_msg((unsigned char *) hostdata->msg_buf);
 	    printk("\n");
 	}
 	
@@ -5540,7 +5541,7 @@ print_dsa (struct Scsi_Host *host, u32 *dsa, const char *prefix) {
 	    i > 0 && !check_address ((unsigned long) ptr, 1);
 	    ptr += len, i -= len) {
 	    printk("               ");
-	    len = scsi_print_msg (ptr);
+	    len = spi_print_msg(ptr);
 	    printk("\n");
 	    if (!len)
 		break;
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 20dd85a77813..3c606cf8c8ca 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -336,6 +336,7 @@ config SCSI_ACARD
 config SCSI_AHA152X
 	tristate "Adaptec AHA152X/2825 support"
 	depends on ISA && SCSI && !64BIT
+	select SCSI_SPI_ATTRS
 	---help---
 	  This is a driver for the AHA-1510, AHA-1520, AHA-1522, and AHA-2825
 	  SCSI host adapters. It also works for the AVA-1505, but the IRQ etc.
@@ -623,6 +624,7 @@ config SCSI_OMIT_FLASHPOINT
 config SCSI_DMX3191D
 	tristate "DMX3191D SCSI support"
 	depends on PCI && SCSI
+	select SCSI_SPI_ATTRS
 	help
 	  This is support for Domex DMX3191D SCSI Host Adapters.
 
@@ -632,6 +634,7 @@ config SCSI_DMX3191D
 config SCSI_DTC3280
 	tristate "DTC3180/3280 SCSI support"
 	depends on ISA && SCSI
+	select SCSI_SPI_ATTRS
 	help
 	  This is support for DTC 3180/3280 SCSI Host Adapters.  Please read
 	  the SCSI-HOWTO, available from
@@ -752,6 +755,7 @@ config SCSI_GDTH
 config SCSI_GENERIC_NCR5380
 	tristate "Generic NCR5380/53c400 SCSI PIO support"
 	depends on ISA && SCSI
+	select SCSI_SPI_ATTRS
 	---help---
 	  This is a driver for the old NCR 53c80 series of SCSI controllers
 	  on boards using PIO. Most boards such as the Trantor T130 fit this
@@ -771,6 +775,7 @@ config SCSI_GENERIC_NCR5380
 config SCSI_GENERIC_NCR5380_MMIO
 	tristate "Generic NCR5380/53c400 SCSI MMIO support"
 	depends on ISA && SCSI
+	select SCSI_SPI_ATTRS
 	---help---
 	  This is a driver for the old NCR 53c80 series of SCSI controllers
 	  on boards using memory mapped I/O. 
@@ -909,7 +914,7 @@ config SCSI_INIA100
 
 config SCSI_PPA
 	tristate "IOMEGA parallel port (ppa - older drives)"
-	depends on SCSI && PARPORT
+	depends on SCSI && PARPORT_PC
 	---help---
 	  This driver supports older versions of IOMEGA's parallel port ZIP
 	  drive (a 100 MB removable media device).
@@ -936,7 +941,7 @@ config SCSI_PPA
 
 config SCSI_IMM
 	tristate "IOMEGA parallel port (imm - newer drives)"
-	depends on SCSI && PARPORT
+	depends on SCSI && PARPORT_PC
 	---help---
 	  This driver supports newer versions of IOMEGA's parallel port ZIP
 	  drive (a 100 MB removable media device).
@@ -963,7 +968,7 @@ config SCSI_IMM
 
 config SCSI_IZIP_EPP16
 	bool "ppa/imm option - Use slow (but safe) EPP-16"
-	depends on PARPORT && (SCSI_PPA || SCSI_IMM)
+	depends on SCSI_PPA || SCSI_IMM
 	---help---
 	  EPP (Enhanced Parallel Port) is a standard for parallel ports which
 	  allows them to act as expansion buses that can handle up to 64
@@ -978,7 +983,7 @@ config SCSI_IZIP_EPP16
 
 config SCSI_IZIP_SLOW_CTR
 	bool "ppa/imm option - Assume slow parport control register"
-	depends on PARPORT && (SCSI_PPA || SCSI_IMM)
+	depends on SCSI_PPA || SCSI_IMM
 	help
 	  Some parallel ports are known to have excessive delays between
 	  changing the parallel port control register and good data being
@@ -1254,6 +1259,7 @@ config SCSI_MCA_53C9X
 config SCSI_PAS16
 	tristate "PAS16 SCSI support"
 	depends on ISA && SCSI
+	select SCSI_SPI_ATTRS
 	---help---
 	  This is support for a SCSI host adapter.  It is explained in section
 	  3.10 of the SCSI-HOWTO, available from
@@ -1423,6 +1429,7 @@ config SCSI_DC390T
 config SCSI_T128
 	tristate "Trantor T128/T128F/T228 SCSI support"
 	depends on ISA && SCSI
+	select SCSI_SPI_ATTRS
 	---help---
 	  This is support for a SCSI host adapter. It is explained in section
 	  3.11 of the SCSI-HOWTO, available from
@@ -1681,6 +1688,7 @@ config OKTAGON_SCSI
 config ATARI_SCSI
 	tristate "Atari native SCSI support"
 	depends on ATARI && SCSI && BROKEN
+	select SCSI_SPI_ATTRS
 	---help---
 	  If you have an Atari with built-in NCR5380 SCSI controller (TT,
 	  Falcon, ...) say Y to get it supported. Of course also, if you have
@@ -1722,6 +1730,7 @@ config TT_DMA_EMUL
 config MAC_SCSI
 	bool "Macintosh NCR5380 SCSI"
 	depends on MAC && SCSI=y
+	select SCSI_SPI_ATTRS
 	help
 	  This is the NCR 5380 SCSI controller included on most of the 68030
 	  based Macintoshes.  If you have one of these say Y and read the
@@ -1743,6 +1752,7 @@ config SCSI_MAC_ESP
 config MVME147_SCSI
 	bool "WD33C93 SCSI driver for MVME147"
 	depends on MVME147 && SCSI=y
+	select SCSI_SPI_ATTRS
 	help
 	  Support for the on-board SCSI controller on the Motorola MVME147
 	  single-board computer.
@@ -1750,6 +1760,7 @@ config MVME147_SCSI
 config MVME16x_SCSI
 	bool "NCR53C710 SCSI driver for MVME16x"
 	depends on MVME16x && SCSI && BROKEN
+	select SCSI_SPI_ATTRS
 	help
 	  The Motorola MVME162, 166, 167, 172 and 177 boards use the NCR53C710
 	  SCSI controller chip.  Almost everyone using one of these boards
@@ -1758,6 +1769,7 @@ config MVME16x_SCSI
 config BVME6000_SCSI
 	bool "NCR53C710 SCSI driver for BVME6000"
 	depends on BVME6000 && SCSI && BROKEN
+	select SCSI_SPI_ATTRS
 	help
 	  The BVME4000 and BVME6000 boards from BVM Ltd use the NCR53C710
 	  SCSI controller chip.  Almost everyone using one of these boards
@@ -1774,6 +1786,7 @@ config SCSI_NCR53C7xx_FAST
 config SUN3_SCSI
 	tristate "Sun3 NCR5380 SCSI"
 	depends on SUN3 && SCSI && BROKEN
+	select SCSI_SPI_ATTRS
 	help
 	  This option will enable support for the OBIO (onboard io) NCR5380
 	  SCSI controller found in the Sun 3/50 and 3/60, as well as for
@@ -1802,7 +1815,7 @@ config SCSI_SUNESP
 
 config ZFCP
 	tristate "FCP host bus adapter driver for IBM eServer zSeries"
-	depends on ARCH_S390 && QDIO && SCSI
+	depends on S390 && QDIO && SCSI
 	select SCSI_FC_ATTRS
 	help
           If you want to access SCSI devices attached to your IBM eServer
diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
index cba9655d0f14..9f0ddbe6dc76 100644
--- a/drivers/scsi/NCR5380.c
+++ b/drivers/scsi/NCR5380.c
@@ -87,6 +87,7 @@
  *      the high level code.
  */
 #include <scsi/scsi_dbg.h>
+#include <scsi/scsi_transport_spi.h>
 
 #ifndef NDEBUG
 #define NDEBUG 0
@@ -2377,7 +2378,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
  * 3..length+1  arguments
  *
  * Start the extended message buffer with the EXTENDED_MESSAGE
- * byte, since scsi_print_msg() wants the whole thing.  
+ * byte, since spi_print_msg() wants the whole thing.  
  */
 					extended_msg[0] = EXTENDED_MESSAGE;
 					/* Accept first byte by clearing ACK */
@@ -2424,7 +2425,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
 				default:
 					if (!tmp) {
 						printk("scsi%d: rejecting message ", instance->host_no);
-						scsi_print_msg(extended_msg);
+						spi_print_msg(extended_msg);
 						printk("\n");
 					} else if (tmp != EXTENDED_MESSAGE)
 						scmd_printk(KERN_INFO, cmd,
@@ -2560,7 +2561,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
 
 	if (!(msg[0] & 0x80)) {
 		printk(KERN_ERR "scsi%d : expecting IDENTIFY message, got ", instance->host_no);
-		scsi_print_msg(msg);
+		spi_print_msg(msg);
 		abort = 1;
 	} else {
 		/* Accept message by clearing ACK */
diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c
index 9df23b654cec..cb2ee25f213f 100644
--- a/drivers/scsi/aha152x.c
+++ b/drivers/scsi/aha152x.c
@@ -259,6 +259,7 @@
 #include "scsi.h"
 #include <scsi/scsi_dbg.h>
 #include <scsi/scsi_host.h>
+#include <scsi/scsi_transport_spi.h>
 #include "aha152x.h"
 
 
@@ -1845,7 +1846,7 @@ static void msgi_run(struct Scsi_Host *shpnt)
 #if defined(AHA152X_DEBUG)
 		if (HOSTDATA(shpnt)->debug & debug_msgi) {
 			printk(INFO_LEAD "inbound message %02x ", CMDINFO(CURRENT_SC), MSGI(0));
-			scsi_print_msg(&MSGI(0));
+			spi_print_msg(&MSGI(0));
 			printk("\n");
 		}
 #endif
@@ -1933,7 +1934,7 @@ static void msgi_run(struct Scsi_Host *shpnt)
 						break;
 
 					printk(INFO_LEAD, CMDINFO(CURRENT_SC));
-					scsi_print_msg(&MSGI(0));
+					spi_print_msg(&MSGI(0));
 					printk("\n");
 
 					ticks = (MSGI(3) * 4 + 49) / 50;
@@ -2031,7 +2032,7 @@ static void msgo_init(struct Scsi_Host *shpnt)
 		int i;
 
 		printk(DEBUG_LEAD "messages( ", CMDINFO(CURRENT_SC));
-		for (i=0; i<MSGOLEN; i+=scsi_print_msg(&MSGO(i)), printk(" "))
+		for (i=0; i<MSGOLEN; i+=spi_print_msg(&MSGO(i)), printk(" "))
 			;
 		printk(")\n");
 	}
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index 83467a05dc8e..d113290b5fc0 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -214,7 +214,6 @@ static struct scsi_host_template ahci_sht = {
 	.dma_boundary		= AHCI_DMA_BOUNDARY,
 	.slave_configure	= ata_scsi_slave_config,
 	.bios_param		= ata_std_bios_param,
-	.ordered_flush		= 1,
 };
 
 static const struct ata_port_operations ahci_ops = {
@@ -243,7 +242,7 @@ static const struct ata_port_operations ahci_ops = {
 	.port_stop		= ahci_port_stop,
 };
 
-static struct ata_port_info ahci_port_info[] = {
+static const struct ata_port_info ahci_port_info[] = {
 	/* board_ahci */
 	{
 		.sht		= &ahci_sht,
@@ -643,7 +642,8 @@ static void ahci_eng_timeout(struct ata_port *ap)
 	 	 * not being called from the SCSI EH.
 	 	 */
 		qc->scsidone = scsi_finish_command;
-		ata_qc_complete(qc, AC_ERR_OTHER);
+		qc->err_mask |= AC_ERR_OTHER;
+		ata_qc_complete(qc);
 	}
 
 	spin_unlock_irqrestore(&host_set->lock, flags);
@@ -664,7 +664,8 @@ static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
 	ci = readl(port_mmio + PORT_CMD_ISSUE);
 	if (likely((ci & 0x1) == 0)) {
 		if (qc) {
-			ata_qc_complete(qc, 0);
+			assert(qc->err_mask == 0);
+			ata_qc_complete(qc);
 			qc = NULL;
 		}
 	}
@@ -681,8 +682,10 @@ static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
 		/* command processing has stopped due to error; restart */
 		ahci_restart_port(ap, status);
 
-		if (qc)
-			ata_qc_complete(qc, err_mask);
+		if (qc) {
+			qc->err_mask |= AC_ERR_OTHER;
+			ata_qc_complete(qc);
+		}
 	}
 
 	return 1;
diff --git a/drivers/scsi/aic7xxx/.gitignore b/drivers/scsi/aic7xxx/.gitignore
new file mode 100644
index 000000000000..b8ee24d5748a
--- /dev/null
+++ b/drivers/scsi/aic7xxx/.gitignore
@@ -0,0 +1,6 @@
+aic79xx_reg.h
+aic79xx_reg_print.c
+aic79xx_seq.h
+aic7xxx_reg.h
+aic7xxx_reg_print.c
+aic7xxx_seq.h
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index 6aab9dacdeea..1c8f872e2dd4 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -1064,6 +1064,7 @@ ahd_linux_register_host(struct ahd_softc *ahd, struct scsi_host_template *templa
 	struct	Scsi_Host *host;
 	char	*new_name;
 	u_long	s;
+	int	retval;
 
 	template->name = ahd->description;
 	host = scsi_host_alloc(template, sizeof(struct ahd_softc *));
@@ -1096,9 +1097,15 @@ ahd_linux_register_host(struct ahd_softc *ahd, struct scsi_host_template *templa
 
 	host->transportt = ahd_linux_transport_template;
 
-	scsi_add_host(host, &ahd->dev_softc->dev); /* XXX handle failure */
+	retval = scsi_add_host(host, &ahd->dev_softc->dev);
+	if (retval) {
+		printk(KERN_WARNING "aic79xx: scsi_add_host failed\n");
+		scsi_host_put(host);
+		return retval;
+	}
+
 	scsi_scan_host(host);
-	return (0);
+	return 0;
 }
 
 uint64_t
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
index d866213f42b8..fd389e9f9460 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
@@ -1061,10 +1061,11 @@ uint32_t aic7xxx_verbose;
 int
 ahc_linux_register_host(struct ahc_softc *ahc, struct scsi_host_template *template)
 {
-	char	 buf[80];
-	struct	 Scsi_Host *host;
+	char	buf[80];
+	struct	Scsi_Host *host;
 	char	*new_name;
-	u_long	 s;
+	u_long	s;
+	int	retval;
 
 	template->name = ahc->description;
 	host = scsi_host_alloc(template, sizeof(struct ahc_softc *));
@@ -1097,9 +1098,16 @@ ahc_linux_register_host(struct ahc_softc *ahc, struct scsi_host_template *templa
 
 	host->transportt = ahc_linux_transport_template;
 
-	scsi_add_host(host, (ahc->dev_softc ? &ahc->dev_softc->dev : NULL)); /* XXX handle failure */
+	retval = scsi_add_host(host,
+			(ahc->dev_softc ? &ahc->dev_softc->dev : NULL));
+	if (retval) {
+		printk(KERN_WARNING "aic7xxx: scsi_add_host failed\n");
+		scsi_host_put(host);
+		return retval;
+	}
+
 	scsi_scan_host(host);
-	return (0);
+	return 0;
 }
 
 /*
diff --git a/drivers/scsi/arm/Kconfig b/drivers/scsi/arm/Kconfig
index 13f23043c8a3..06d7601cdf56 100644
--- a/drivers/scsi/arm/Kconfig
+++ b/drivers/scsi/arm/Kconfig
@@ -4,6 +4,7 @@
 config SCSI_ACORNSCSI_3
 	tristate "Acorn SCSI card (aka30) support"
 	depends on ARCH_ACORN && SCSI && BROKEN
+	select SCSI_SPI_ATTRS
 	help
 	  This enables support for the Acorn SCSI card (aka30). If you have an
 	  Acorn system with one of these, say Y. If unsure, say N.
diff --git a/drivers/scsi/arm/acornscsi.c b/drivers/scsi/arm/acornscsi.c
index b7b20c689c24..09ed05727bcb 100644
--- a/drivers/scsi/arm/acornscsi.c
+++ b/drivers/scsi/arm/acornscsi.c
@@ -152,6 +152,7 @@
 #include "../scsi.h"
 #include <scsi/scsi_dbg.h>
 #include <scsi/scsi_host.h>
+#include <scsi/scsi_transport_spi.h>
 #include "acornscsi.h"
 #include "msgqueue.h"
 #include "scsi.h"
@@ -1370,7 +1371,7 @@ void acornscsi_sendmessage(AS_Host *host)
 
 	host->scsi.last_message = msg->msg[0];
 #if (DEBUG & DEBUG_MESSAGES)
-	scsi_print_msg(msg->msg);
+	spi_print_msg(msg->msg);
 #endif
 	break;
 
@@ -1392,7 +1393,7 @@ void acornscsi_sendmessage(AS_Host *host)
 	while ((msg = msgqueue_getmsg(&host->scsi.msgs, msgnr++)) != NULL) {
 	    unsigned int i;
 #if (DEBUG & DEBUG_MESSAGES)
-	    scsi_print_msg(msg);
+	    spi_print_msg(msg);
 #endif
 	    i = 0;
 	    if (acornscsi_write_pio(host, msg->msg, &i, msg->length, 1000000))
@@ -1488,7 +1489,7 @@ void acornscsi_message(AS_Host *host)
 #if (DEBUG & DEBUG_MESSAGES)
     printk("scsi%d.%c: message in: ",
 	    host->host->host_no, acornscsi_target(host));
-    scsi_print_msg(message);
+    spi_print_msg(message);
     printk("\n");
 #endif
 
diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c
index 333d69dd84ef..557788ec4eec 100644
--- a/drivers/scsi/ata_piix.c
+++ b/drivers/scsi/ata_piix.c
@@ -37,6 +37,49 @@
  *
  *  Hardware documentation available at http://developer.intel.com/
  *
+ * Documentation
+ *	Publically available from Intel web site. Errata documentation
+ * is also publically available. As an aide to anyone hacking on this
+ * driver the list of errata that are relevant is below.going back to
+ * PIIX4. Older device documentation is now a bit tricky to find.
+ *
+ * The chipsets all follow very much the same design. The orginal Triton
+ * series chipsets do _not_ support independant device timings, but this
+ * is fixed in Triton II. With the odd mobile exception the chips then
+ * change little except in gaining more modes until SATA arrives. This
+ * driver supports only the chips with independant timing (that is those
+ * with SITRE and the 0x44 timing register). See pata_oldpiix and pata_mpiix
+ * for the early chip drivers.
+ *
+ * Errata of note:
+ *
+ * Unfixable
+ *	PIIX4    errata #9	- Only on ultra obscure hw
+ *	ICH3	 errata #13     - Not observed to affect real hw
+ *				  by Intel
+ *
+ * Things we must deal with
+ *	PIIX4	errata #10	- BM IDE hang with non UDMA
+ *				  (must stop/start dma to recover)
+ *	440MX   errata #15	- As PIIX4 errata #10
+ *	PIIX4	errata #15	- Must not read control registers
+ * 				  during a PIO transfer
+ *	440MX   errata #13	- As PIIX4 errata #15
+ *	ICH2	errata #21	- DMA mode 0 doesn't work right
+ *	ICH0/1  errata #55	- As ICH2 errata #21
+ *	ICH2	spec c #9	- Extra operations needed to handle
+ *				  drive hotswap [NOT YET SUPPORTED]
+ *	ICH2    spec c #20	- IDE PRD must not cross a 64K boundary
+ *				  and must be dword aligned
+ *	ICH2    spec c #24	- UDMA mode 4,5 t85/86 should be 6ns not 3.3
+ *
+ * Should have been BIOS fixed:
+ *	450NX:	errata #19	- DMA hangs on old 450NX
+ *	450NX:  errata #20	- DMA hangs on old 450NX
+ *	450NX:  errata #25	- Corruption with DMA on old 450NX
+ *	ICH3    errata #15      - IDE deadlock under high load
+ *				  (BIOS must set dev 31 fn 0 bit 23)
+ *	ICH3	errata #18	- Don't use native mode
  */
 
 #include <linux/kernel.h>
@@ -78,9 +121,7 @@ enum {
 	ich5_sata		= 1,
 	piix4_pata		= 2,
 	ich6_sata		= 3,
-	ich6_sata_rm		= 4,
-	ich7_sata		= 5,
-	esb2_sata		= 6,
+	ich6_sata_ahci		= 4,
 
 	PIIX_AHCI_DEVICE	= 6,
 };
@@ -111,11 +152,11 @@ static const struct pci_device_id piix_pci_tbl[] = {
 	{ 0x8086, 0x25a3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
 	{ 0x8086, 0x25b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
 	{ 0x8086, 0x2651, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata },
-	{ 0x8086, 0x2652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_rm },
-	{ 0x8086, 0x2653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_rm },
-	{ 0x8086, 0x27c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich7_sata },
-	{ 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich7_sata },
-	{ 0x8086, 0x2680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, esb2_sata },
+	{ 0x8086, 0x2652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
+	{ 0x8086, 0x2653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
+	{ 0x8086, 0x27c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
+	{ 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
+	{ 0x8086, 0x2680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
 
 	{ }	/* terminate list */
 };
@@ -125,6 +166,8 @@ static struct pci_driver piix_pci_driver = {
 	.id_table		= piix_pci_tbl,
 	.probe			= piix_init_one,
 	.remove			= ata_pci_remove_one,
+	.suspend		= ata_pci_device_suspend,
+	.resume			= ata_pci_device_resume,
 };
 
 static struct scsi_host_template piix_sht = {
@@ -144,7 +187,8 @@ static struct scsi_host_template piix_sht = {
 	.dma_boundary		= ATA_DMA_BOUNDARY,
 	.slave_configure	= ata_scsi_slave_config,
 	.bios_param		= ata_std_bios_param,
-	.ordered_flush		= 1,
+	.resume			= ata_scsi_device_resume,
+	.suspend		= ata_scsi_device_suspend,
 };
 
 static const struct ata_port_operations piix_pata_ops = {
@@ -258,31 +302,7 @@ static struct ata_port_info piix_port_info[] = {
 		.port_ops	= &piix_sata_ops,
 	},
 
-	/* ich6_sata_rm */
-	{
-		.sht		= &piix_sht,
-		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_SRST |
-				  PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR |
-				  ATA_FLAG_SLAVE_POSS | PIIX_FLAG_AHCI,
-		.pio_mask	= 0x1f,	/* pio0-4 */
-		.mwdma_mask	= 0x07, /* mwdma0-2 */
-		.udma_mask	= 0x7f,	/* udma0-6 */
-		.port_ops	= &piix_sata_ops,
-	},
-
-	/* ich7_sata */
-	{
-		.sht		= &piix_sht,
-		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_SRST |
-				  PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR |
-				  ATA_FLAG_SLAVE_POSS | PIIX_FLAG_AHCI,
-		.pio_mask	= 0x1f,	/* pio0-4 */
-		.mwdma_mask	= 0x07, /* mwdma0-2 */
-		.udma_mask	= 0x7f,	/* udma0-6 */
-		.port_ops	= &piix_sata_ops,
-	},
-
-	/* esb2_sata */
+	/* ich6_sata_ahci */
 	{
 		.sht		= &piix_sht,
 		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_SRST |
@@ -603,6 +623,40 @@ static int piix_disable_ahci(struct pci_dev *pdev)
 }
 
 /**
+ *	piix_check_450nx_errata	-	Check for problem 450NX setup
+ *	
+ *	Check for the present of 450NX errata #19 and errata #25. If
+ *	they are found return an error code so we can turn off DMA
+ */
+
+static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev)
+{
+	struct pci_dev *pdev = NULL;
+	u16 cfg;
+	u8 rev;
+	int no_piix_dma = 0;
+	
+	while((pdev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, pdev)) != NULL)
+	{
+		/* Look for 450NX PXB. Check for problem configurations
+		   A PCI quirk checks bit 6 already */
+		pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
+		pci_read_config_word(pdev, 0x41, &cfg);
+		/* Only on the original revision: IDE DMA can hang */
+		if(rev == 0x00)
+			no_piix_dma = 1;
+		/* On all revisions below 5 PXB bus lock must be disabled for IDE */
+		else if(cfg & (1<<14) && rev < 5)
+			no_piix_dma = 2;
+	}
+	if(no_piix_dma)
+		dev_printk(KERN_WARNING, &ata_dev->dev, "450NX errata present, disabling IDE DMA.\n");
+	if(no_piix_dma == 2)
+		dev_printk(KERN_WARNING, &ata_dev->dev, "A BIOS update may resolve this.\n");
+	return no_piix_dma;
+}		
+
+/**
  *	piix_init_one - Register PIIX ATA PCI device with kernel services
  *	@pdev: PCI device to register
  *	@ent: Entry in piix_pci_tbl matching with @pdev
@@ -676,7 +730,15 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 			   "combined mode detected (p=%u, s=%u)\n",
 			   pata_chan, sata_chan);
 	}
-
+	if (piix_check_450nx_errata(pdev)) {
+		/* This writes into the master table but it does not
+		   really matter for this errata as we will apply it to
+		   all the PIIX devices on the board */
+		port_info[0]->mwdma_mask = 0;
+		port_info[0]->udma_mask = 0;
+		port_info[1]->mwdma_mask = 0;
+		port_info[1]->udma_mask = 0;
+	}
 	return ata_pci_init_one(pdev, port_info, 2);
 }
 
diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c
index 2ae31ceb32a8..57295bcea3e7 100644
--- a/drivers/scsi/atari_NCR5380.c
+++ b/drivers/scsi/atari_NCR5380.c
@@ -74,6 +74,7 @@
  *     the high level code.
  */
 #include <scsi/scsi_dbg.h>
+#include <scsi/scsi_transport_spi.h>
 
 #if (NDEBUG & NDEBUG_LISTS)
 #define LIST(x,y) \
@@ -2355,7 +2356,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance)
  * 3..length+1	arguments
  *
  * Start the extended message buffer with the EXTENDED_MESSAGE
- * byte, since scsi_print_msg() wants the whole thing.  
+ * byte, since spi_print_msg() wants the whole thing.  
  */
 		    extended_msg[0] = EXTENDED_MESSAGE;
 		    /* Accept first byte by clearing ACK */
@@ -2408,7 +2409,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance)
 		default:
 		    if (!tmp) {
 			printk(KERN_DEBUG "scsi%d: rejecting message ", HOSTNO);
-			scsi_print_msg (extended_msg);
+			spi_print_msg(extended_msg);
 			printk("\n");
 		    } else if (tmp != EXTENDED_MESSAGE)
 			printk(KERN_DEBUG "scsi%d: rejecting unknown "
@@ -2541,7 +2542,7 @@ static void NCR5380_reselect (struct Scsi_Host *instance)
 
     if (!(msg[0] & 0x80)) {
 	printk(KERN_DEBUG "scsi%d: expecting IDENTIFY message, got ", HOSTNO);
-	scsi_print_msg(msg);
+	spi_print_msg(msg);
 	do_abort(instance);
 	return;
     }
diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c
index ccbbae2bf478..0920220f3313 100644
--- a/drivers/scsi/ch.c
+++ b/drivers/scsi/ch.c
@@ -75,7 +75,7 @@ static int vendor_counts[CH_TYPES-4];
 module_param_array(vendor_firsts, int, NULL, 0444);
 module_param_array(vendor_counts, int, NULL, 0444);
 
-static char *vendor_labels[CH_TYPES-4] = {
+static const char * vendor_labels[CH_TYPES-4] = {
 	"v0", "v1", "v2", "v3"
 };
 // module_param_string_array(vendor_labels, NULL, 0444);
@@ -140,7 +140,7 @@ static struct file_operations changer_fops =
 #endif
 };
 
-static struct {
+static const struct {
 	unsigned char  sense;
 	unsigned char  asc;
 	unsigned char  ascq;
diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c
index 09bc81557b6e..30a335349cee 100644
--- a/drivers/scsi/constants.c
+++ b/drivers/scsi/constants.c
@@ -1065,7 +1065,7 @@ struct error_info2 {
 	const char * fmt;
 };
 
-static struct error_info2 additional2[] =
+static const struct error_info2 additional2[] =
 {
 	{0x40,0x00,0x7f,"Ram failure (%x)"},
 	{0x40,0x80,0xff,"Diagnostic failure on component (%x)"},
@@ -1077,7 +1077,7 @@ static struct error_info2 additional2[] =
 };
 
 /* description of the sense key values */
-static const char *snstext[] = {
+static const char * const snstext[] = {
 	"No Sense",	    /* 0: There is no sense information */
 	"Recovered Error",  /* 1: The last command completed successfully
 				  but used error correction */
@@ -1278,114 +1278,6 @@ void scsi_print_req_sense(const char *devclass, struct scsi_request *sreq)
 }
 EXPORT_SYMBOL(scsi_print_req_sense);
 
-#ifdef CONFIG_SCSI_CONSTANTS
-static const char *one_byte_msgs[] = {
-/* 0x00 */ "Command Complete", NULL, "Save Pointers",
-/* 0x03 */ "Restore Pointers", "Disconnect", "Initiator Error", 
-/* 0x06 */ "Abort", "Message Reject", "Nop", "Message Parity Error",
-/* 0x0a */ "Linked Command Complete", "Linked Command Complete w/flag",
-/* 0x0c */ "Bus device reset", "Abort Tag", "Clear Queue", 
-/* 0x0f */ "Initiate Recovery", "Release Recovery"
-};
-#define NO_ONE_BYTE_MSGS (sizeof(one_byte_msgs)  / sizeof (const char *))
-
-static const char *two_byte_msgs[] = {
-/* 0x20 */ "Simple Queue Tag", "Head of Queue Tag", "Ordered Queue Tag"
-/* 0x23 */ "Ignore Wide Residue"
-};
-#define NO_TWO_BYTE_MSGS (sizeof(two_byte_msgs)  / sizeof (const char *))
-
-static const char *extended_msgs[] = {
-/* 0x00 */ "Modify Data Pointer", "Synchronous Data Transfer Request",
-/* 0x02 */ "SCSI-I Extended Identify", "Wide Data Transfer Request"
-};
-#define NO_EXTENDED_MSGS (sizeof(two_byte_msgs)  / sizeof (const char *))
-
-
-int scsi_print_msg (const unsigned char *msg)
-{
-	int len = 0, i;
-	if (msg[0] == EXTENDED_MESSAGE) {
-		len = 3 + msg[1];
-		if (msg[2] < NO_EXTENDED_MSGS)
-			printk ("%s ", extended_msgs[msg[2]]); 
-		else 
-			printk ("Extended Message, reserved code (0x%02x) ",
-				(int) msg[2]);
-		switch (msg[2]) {
-		case EXTENDED_MODIFY_DATA_POINTER:
-			printk("pointer = %d", (int) (msg[3] << 24) |
-				(msg[4] << 16) | (msg[5] << 8) | msg[6]);
-			break;
-		case EXTENDED_SDTR:
-			printk("period = %d ns, offset = %d",
-				(int) msg[3] * 4, (int) msg[4]);
-			break;
-		case EXTENDED_WDTR:
-			printk("width = 2^%d bytes", msg[3]);
-			break;
-		default:
-		for (i = 2; i < len; ++i) 
-			printk("%02x ", msg[i]);
-		}
-	/* Identify */
-	} else if (msg[0] & 0x80) {
-		printk("Identify disconnect %sallowed %s %d ",
-			(msg[0] & 0x40) ? "" : "not ",
-			(msg[0] & 0x20) ? "target routine" : "lun",
-			msg[0] & 0x7);
-		len = 1;
-	/* Normal One byte */
-	} else if (msg[0] < 0x1f) {
-		if (msg[0] < NO_ONE_BYTE_MSGS)
-			printk(one_byte_msgs[msg[0]]);
-		else
-			printk("reserved (%02x) ", msg[0]);
-		len = 1;
-	/* Two byte */
-	} else if (msg[0] <= 0x2f) {
-		if ((msg[0] - 0x20) < NO_TWO_BYTE_MSGS)
-			printk("%s %02x ", two_byte_msgs[msg[0] - 0x20], 
-				msg[1]);
-		else 
-			printk("reserved two byte (%02x %02x) ", 
-				msg[0], msg[1]);
-		len = 2;
-	} else 
-		printk("reserved");
-	return len;
-}
-EXPORT_SYMBOL(scsi_print_msg);
-
-#else  /* ifndef CONFIG_SCSI_CONSTANTS */
-
-int scsi_print_msg (const unsigned char *msg)
-{
-	int len = 0, i;
-
-	if (msg[0] == EXTENDED_MESSAGE) {
-		len = 3 + msg[1];
-		for (i = 0; i < len; ++i)
-			printk("%02x ", msg[i]);
-	/* Identify */
-	} else if (msg[0] & 0x80) {
-		printk("%02x ", msg[0]);
-		len = 1;
-	/* Normal One byte */
-	} else if (msg[0] < 0x1f) {
-		printk("%02x ", msg[0]);
-		len = 1;
-	/* Two byte */
-	} else if (msg[0] <= 0x2f) {
-		printk("%02x %02x", msg[0], msg[1]);
-		len = 2;
-	} else 
-		printk("%02x ", msg[0]);
-	return len;
-}
-EXPORT_SYMBOL(scsi_print_msg);
-#endif /* ! CONFIG_SCSI_CONSTANTS */
-
 void scsi_print_command(struct scsi_cmnd *cmd)
 {
 	/* Assume appended output (i.e. not at start of line) */
@@ -1397,7 +1289,7 @@ EXPORT_SYMBOL(scsi_print_command);
 
 #ifdef CONFIG_SCSI_CONSTANTS
 
-static const char * hostbyte_table[]={
+static const char * const hostbyte_table[]={
 "DID_OK", "DID_NO_CONNECT", "DID_BUS_BUSY", "DID_TIME_OUT", "DID_BAD_TARGET", 
 "DID_ABORT", "DID_PARITY", "DID_ERROR", "DID_RESET", "DID_BAD_INTR",
 "DID_PASSTHROUGH", "DID_SOFT_ERROR", "DID_IMM_RETRY"};
@@ -1422,12 +1314,12 @@ void scsi_print_hostbyte(int scsiresult)
 
 #ifdef CONFIG_SCSI_CONSTANTS
 
-static const char * driverbyte_table[]={
+static const char * const driverbyte_table[]={
 "DRIVER_OK", "DRIVER_BUSY", "DRIVER_SOFT",  "DRIVER_MEDIA", "DRIVER_ERROR", 
 "DRIVER_INVALID", "DRIVER_TIMEOUT", "DRIVER_HARD", "DRIVER_SENSE"};
 #define NUM_DRIVERBYTE_STRS (sizeof(driverbyte_table) / sizeof(const char *))
 
-static const char * driversuggest_table[]={"SUGGEST_OK",
+static const char * const driversuggest_table[]={"SUGGEST_OK",
 "SUGGEST_RETRY", "SUGGEST_ABORT", "SUGGEST_REMAP", "SUGGEST_DIE",
 "SUGGEST_5", "SUGGEST_6", "SUGGEST_7", "SUGGEST_SENSE"};
 #define NUM_SUGGEST_STRS (sizeof(driversuggest_table) / sizeof(const char *))
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index 5b9c2c5a7f0e..66783c860a19 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -347,17 +347,8 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
 	shost->cmd_per_lun = sht->cmd_per_lun;
 	shost->unchecked_isa_dma = sht->unchecked_isa_dma;
 	shost->use_clustering = sht->use_clustering;
-	shost->ordered_flush = sht->ordered_flush;
 	shost->ordered_tag = sht->ordered_tag;
 
-	/*
-	 * hosts/devices that do queueing must support ordered tags
-	 */
-	if (shost->can_queue > 1 && shost->ordered_flush) {
-		printk(KERN_ERR "scsi: ordered flushes don't support queueing\n");
-		shost->ordered_flush = 0;
-	}
-
 	if (sht->max_host_blocked)
 		shost->max_host_blocked = sht->max_host_blocked;
 	else
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
index 4cb1f3ed9100..3c688ef54660 100644
--- a/drivers/scsi/ide-scsi.c
+++ b/drivers/scsi/ide-scsi.c
@@ -1046,7 +1046,7 @@ static int idescsi_eh_reset (struct scsi_cmnd *cmd)
 
 	/* kill current request */
 	blkdev_dequeue_request(req);
-	end_that_request_last(req);
+	end_that_request_last(req, 0);
 	if (req->flags & REQ_SENSE)
 		kfree(scsi->pc->buffer);
 	kfree(scsi->pc);
@@ -1056,7 +1056,7 @@ static int idescsi_eh_reset (struct scsi_cmnd *cmd)
 	/* now nuke the drive queue */
 	while ((req = elv_next_request(drive->queue))) {
 		blkdev_dequeue_request(req);
-		end_that_request_last(req);
+		end_that_request_last(req, 0);
 	}
 
 	HWGROUP(drive)->rq = NULL;
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index fa2cb3582cfa..27acf78cf8d8 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -2132,7 +2132,7 @@ restart:
 	}
 
 	spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
-	kobject_uevent(&ioa_cfg->host->shost_classdev.kobj, KOBJ_CHANGE, NULL);
+	kobject_uevent(&ioa_cfg->host->shost_classdev.kobj, KOBJ_CHANGE);
 	LEAVE;
 }
 
@@ -5887,7 +5887,12 @@ static int __devinit ipr_probe_ioa_part2(struct ipr_ioa_cfg *ioa_cfg)
 	ENTER;
 	spin_lock_irqsave(ioa_cfg->host->host_lock, host_lock_flags);
 	dev_dbg(&ioa_cfg->pdev->dev, "ioa_cfg adx: 0x%p\n", ioa_cfg);
-	_ipr_initiate_ioa_reset(ioa_cfg, ipr_reset_enable_ioa, IPR_SHUTDOWN_NONE);
+	if (ioa_cfg->needs_hard_reset) {
+		ioa_cfg->needs_hard_reset = 0;
+		ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_NONE);
+	} else
+		_ipr_initiate_ioa_reset(ioa_cfg, ipr_reset_enable_ioa,
+					IPR_SHUTDOWN_NONE);
 
 	spin_unlock_irqrestore(ioa_cfg->host->host_lock, host_lock_flags);
 	wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload);
@@ -6264,6 +6269,7 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
 	unsigned long ipr_regs_pci;
 	void __iomem *ipr_regs;
 	u32 rc = PCIBIOS_SUCCESSFUL;
+	volatile u32 mask, uproc;
 
 	ENTER;
 
@@ -6356,6 +6362,15 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
 		goto cleanup_nomem;
 	}
 
+	/*
+	 * If HRRQ updated interrupt is not masked, or reset alert is set,
+	 * the card is in an unknown state and needs a hard reset
+	 */
+	mask = readl(ioa_cfg->regs.sense_interrupt_mask_reg);
+	uproc = readl(ioa_cfg->regs.sense_uproc_interrupt_reg);
+	if ((mask & IPR_PCII_HRRQ_UPDATED) == 0 || (uproc & IPR_UPROCI_RESET_ALERT))
+		ioa_cfg->needs_hard_reset = 1;
+
 	ipr_mask_and_clear_interrupts(ioa_cfg, ~IPR_PCII_IOA_TRANS_TO_OPER);
 	rc = request_irq(pdev->irq, ipr_isr, SA_SHIRQ, IPR_NAME, ioa_cfg);
 
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
index 6bec673c925c..b639332131f1 100644
--- a/drivers/scsi/ipr.h
+++ b/drivers/scsi/ipr.h
@@ -36,8 +36,8 @@
 /*
  * Literals
  */
-#define IPR_DRIVER_VERSION "2.1.0"
-#define IPR_DRIVER_DATE "(October 31, 2005)"
+#define IPR_DRIVER_VERSION "2.1.1"
+#define IPR_DRIVER_DATE "(November 15, 2005)"
 
 /*
  * IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding
@@ -922,6 +922,7 @@ struct ipr_ioa_cfg {
 	u8 dump_taken:1;
 	u8 allow_cmds:1;
 	u8 allow_ml_add_del:1;
+	u8 needs_hard_reset:1;
 
 	enum ipr_cache_state cache_state;
 	u16 type; /* CCIN of the card */
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 3d8009f55342..10bcf42cb65c 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -49,7 +49,7 @@ MODULE_AUTHOR("Dmitry Yusupov <dmitry_yus@yahoo.com>, "
 	      "Alex Aizman <itn780@yahoo.com>");
 MODULE_DESCRIPTION("iSCSI/TCP data-path");
 MODULE_LICENSE("GPL");
-MODULE_VERSION("0:4.409");
+MODULE_VERSION("0:4.445");
 /* #define DEBUG_TCP */
 /* #define DEBUG_SCSI */
 #define DEBUG_ASSERT
@@ -581,10 +581,16 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
 		crypto_digest_digest(conn->rx_tfm, &sg, 1, (u8 *)&cdgst);
 		rdgst = *(uint32_t*)((char*)hdr + sizeof(struct iscsi_hdr) +
 				     conn->in.ahslen);
+		if (cdgst != rdgst) {
+			printk(KERN_ERR "iscsi_tcp: itt %x: hdrdgst error "
+			       "recv 0x%x calc 0x%x\n", conn->in.itt, rdgst,
+			       cdgst);
+			return ISCSI_ERR_HDR_DGST;
+		}
 	}
 
 	/* save opcode for later */
-	conn->in.opcode = hdr->opcode;
+	conn->in.opcode = hdr->opcode & ISCSI_OPCODE_MASK;
 
 	/* verify itt (itt encoding: age+cid+itt) */
 	if (hdr->itt != cpu_to_be32(ISCSI_RESERVED_TAG)) {
@@ -610,13 +616,6 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
 		  conn->in.ahslen, conn->in.datalen);
 
 	if (conn->in.itt < session->cmds_max) {
-		if (conn->hdrdgst_en && cdgst != rdgst) {
-			printk(KERN_ERR "iscsi_tcp: itt %x: hdrdgst error "
-			       "recv 0x%x calc 0x%x\n", conn->in.itt, rdgst,
-			       cdgst);
-			return ISCSI_ERR_HDR_DGST;
-		}
-
 		ctask = (struct iscsi_cmd_task *)session->cmds[conn->in.itt];
 
 		if (!ctask->sc) {
@@ -642,9 +641,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
 		switch(conn->in.opcode) {
 		case ISCSI_OP_SCSI_CMD_RSP:
 			BUG_ON((void*)ctask != ctask->sc->SCp.ptr);
-			if (ctask->hdr.flags & ISCSI_FLAG_CMD_WRITE)
-				rc = iscsi_cmd_rsp(conn, ctask);
-			else if (!conn->in.datalen)
+			if (!conn->in.datalen)
 				rc = iscsi_cmd_rsp(conn, ctask);
 			else
 				/*
@@ -666,8 +663,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
 			break;
 		case ISCSI_OP_R2T:
 			BUG_ON((void*)ctask != ctask->sc->SCp.ptr);
-			if (ctask->hdr.flags & ISCSI_FLAG_CMD_WRITE &&
-			    ctask->sc->sc_data_direction == DMA_TO_DEVICE)
+			if (ctask->sc->sc_data_direction == DMA_TO_DEVICE)
 				rc = iscsi_r2t_rsp(conn, ctask);
 			else
 				rc = ISCSI_ERR_PROTO;
@@ -906,11 +902,20 @@ partial_sg_digest_update(struct iscsi_conn *conn, struct scatterlist *sg,
 	crypto_digest_update(conn->data_rx_tfm, &temp, 1);
 }
 
+static void
+iscsi_recv_digest_update(struct iscsi_conn *conn, char* buf, int len)
+{
+	struct scatterlist tmp;
+
+	sg_init_one(&tmp, buf, len);
+	crypto_digest_update(conn->data_rx_tfm, &tmp, 1);
+}
+
 static int iscsi_scsi_data_in(struct iscsi_conn *conn)
 {
 	struct iscsi_cmd_task *ctask = conn->in.ctask;
 	struct scsi_cmnd *sc = ctask->sc;
-	struct scatterlist tmp, *sg;
+	struct scatterlist *sg;
 	int i, offset, rc = 0;
 
 	BUG_ON((void*)ctask != sc->SCp.ptr);
@@ -924,10 +929,8 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn)
 				      sc->request_bufflen, ctask->data_offset);
 		if (rc == -EAGAIN)
 			return rc;
-		if (conn->datadgst_en) {
-			sg_init_one(&tmp, sc->request_buffer, i);
-			crypto_digest_update(conn->data_rx_tfm, &tmp, 1);
-		}
+		if (conn->datadgst_en) 
+			iscsi_recv_digest_update(conn, sc->request_buffer, i);
 		rc = 0;
 		goto done;
 	}
@@ -1021,6 +1024,9 @@ iscsi_data_recv(struct iscsi_conn *conn)
 		conn->in.hdr = &conn->hdr;
 		conn->senselen = (conn->data[0] << 8) | conn->data[1];
 		rc = iscsi_cmd_rsp(conn, conn->in.ctask);
+		if (!rc && conn->datadgst_en) 
+			iscsi_recv_digest_update(conn, conn->data,
+						 conn->in.datalen);
 	}
 	break;
 	case ISCSI_OP_TEXT_RSP:
@@ -1045,6 +1051,11 @@ iscsi_data_recv(struct iscsi_conn *conn)
 		rc = iscsi_recv_pdu(iscsi_handle(conn), conn->in.hdr,
 				    conn->data, conn->in.datalen);
 
+		if (!rc && conn->datadgst_en && 
+			conn->in.opcode != ISCSI_OP_LOGIN_RSP)
+			iscsi_recv_digest_update(conn, conn->data,
+			  			conn->in.datalen);
+
 		if (mtask && conn->login_mtask != mtask) {
 			spin_lock(&session->lock);
 			__kfifo_put(session->mgmtpool.queue, (void*)&mtask,
@@ -1053,6 +1064,8 @@ iscsi_data_recv(struct iscsi_conn *conn)
 		}
 	}
 	break;
+	case ISCSI_OP_ASYNC_EVENT:
+	case ISCSI_OP_REJECT:
 	default:
 		BUG_ON(1);
 	}
@@ -1114,8 +1127,7 @@ more:
 		 */
 		rc = iscsi_hdr_recv(conn);
 		if (!rc && conn->in.datalen) {
-			if (conn->datadgst_en &&
-			    conn->in.opcode == ISCSI_OP_SCSI_DATA_IN) {
+			if (conn->datadgst_en) {
 				BUG_ON(!conn->data_rx_tfm);
 				crypto_digest_init(conn->data_rx_tfm);
 			}
@@ -1127,26 +1139,24 @@ more:
 	}
 
 	if (conn->in_progress == IN_PROGRESS_DDIGEST_RECV) {
+		uint32_t recv_digest;
 		debug_tcp("extra data_recv offset %d copy %d\n",
 			  conn->in.offset, conn->in.copy);
-		if (conn->in.opcode == ISCSI_OP_SCSI_DATA_IN) {
-			uint32_t recv_digest;
-			skb_copy_bits(conn->in.skb, conn->in.offset,
-				      &recv_digest, 4);
-			conn->in.offset += 4;
-			conn->in.copy -= 4;
-			if (recv_digest != conn->in.datadgst) {
-				debug_tcp("iscsi_tcp: data digest error!"
-					  "0x%x != 0x%x\n", recv_digest,
-					  conn->in.datadgst);
-				iscsi_conn_failure(conn, ISCSI_ERR_DATA_DGST);
-				return 0;
-			} else {
-				debug_tcp("iscsi_tcp: data digest match!"
-					  "0x%x == 0x%x\n", recv_digest,
-					  conn->in.datadgst);
-				conn->in_progress = IN_PROGRESS_WAIT_HEADER;
-			}
+		skb_copy_bits(conn->in.skb, conn->in.offset,
+				&recv_digest, 4);
+		conn->in.offset += 4;
+		conn->in.copy -= 4;
+		if (recv_digest != conn->in.datadgst) {
+			debug_tcp("iscsi_tcp: data digest error!"
+				  "0x%x != 0x%x\n", recv_digest,
+				  conn->in.datadgst);
+			iscsi_conn_failure(conn, ISCSI_ERR_DATA_DGST);
+			return 0;
+		} else {
+			debug_tcp("iscsi_tcp: data digest match!"
+				  "0x%x == 0x%x\n", recv_digest,
+				  conn->in.datadgst);
+			conn->in_progress = IN_PROGRESS_WAIT_HEADER;
 		}
 	}
 
@@ -1167,8 +1177,7 @@ more:
 		}
 		conn->in.copy -= conn->in.padding;
 		conn->in.offset += conn->in.padding;
-		if (conn->datadgst_en &&
-		    conn->in.opcode == ISCSI_OP_SCSI_DATA_IN) {
+		if (conn->datadgst_en) {
 			if (conn->in.padding) {
 				debug_tcp("padding -> %d\n", conn->in.padding);
 				memset(pad, 0, conn->in.padding);
@@ -1237,8 +1246,9 @@ iscsi_tcp_state_change(struct sock *sk)
 	conn = (struct iscsi_conn*)sk->sk_user_data;
 	session = conn->session;
 
-	if (sk->sk_state == TCP_CLOSE_WAIT ||
-	    sk->sk_state == TCP_CLOSE) {
+	if ((sk->sk_state == TCP_CLOSE_WAIT ||
+	     sk->sk_state == TCP_CLOSE) &&
+	    !atomic_read(&sk->sk_rmem_alloc)) {
 		debug_tcp("iscsi_tcp_state_change: TCP_CLOSE|TCP_CLOSE_WAIT\n");
 		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
 	}
@@ -2389,6 +2399,15 @@ fault:
 }
 
 static int
+iscsi_change_queue_depth(struct scsi_device *sdev, int depth)
+{
+	if (depth > ISCSI_MAX_CMD_PER_LUN)
+		depth = ISCSI_MAX_CMD_PER_LUN;
+	scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth);
+	return sdev->queue_depth;
+}
+
+static int
 iscsi_pool_init(struct iscsi_queue *q, int max, void ***items, int item_size)
 {
 	int i;
@@ -2853,8 +2872,11 @@ iscsi_conn_stop(iscsi_connh_t connh, int flag)
 		 * in hdr_extract() and will be re-negotiated at
 		 * set_param() time.
 		 */
-		if (flag == STOP_CONN_RECOVER)
+		if (flag == STOP_CONN_RECOVER) {
 			conn->hdr_size = sizeof(struct iscsi_hdr);
+			conn->hdrdgst_en = 0;
+			conn->datadgst_en = 0;
+		}
 	}
 	up(&conn->xmitsema);
 }
@@ -3247,13 +3269,14 @@ iscsi_r2tpool_free(struct iscsi_session *session)
 static struct scsi_host_template iscsi_sht = {
 	.name			= "iSCSI Initiator over TCP/IP, v."
 				  ISCSI_VERSION_STR,
-        .queuecommand           = iscsi_queuecommand,
+	.queuecommand           = iscsi_queuecommand,
+	.change_queue_depth	= iscsi_change_queue_depth,
 	.can_queue		= ISCSI_XMIT_CMDS_MAX - 1,
 	.sg_tablesize		= ISCSI_SG_TABLESIZE,
-	.cmd_per_lun		= ISCSI_CMD_PER_LUN,
-        .eh_abort_handler       = iscsi_eh_abort,
-        .eh_host_reset_handler	= iscsi_eh_host_reset,
-        .use_clustering         = DISABLE_CLUSTERING,
+	.cmd_per_lun		= ISCSI_DEF_CMD_PER_LUN,
+	.eh_abort_handler       = iscsi_eh_abort,
+	.eh_host_reset_handler	= iscsi_eh_host_reset,
+	.use_clustering         = DISABLE_CLUSTERING,
 	.proc_name		= "iscsi_tcp",
 	.this_id		= -1,
 };
diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
index d23ae68fae0d..855f2dfd18af 100644
--- a/drivers/scsi/iscsi_tcp.h
+++ b/drivers/scsi/iscsi_tcp.h
@@ -71,7 +71,8 @@
 #define ISCSI_MGMT_CMDS_MAX		32	/* must be power of 2 */
 #define ISCSI_MGMT_ITT_OFFSET		0xa00
 #define ISCSI_SG_TABLESIZE		SG_ALL
-#define ISCSI_CMD_PER_LUN		128
+#define ISCSI_DEF_CMD_PER_LUN		32
+#define ISCSI_MAX_CMD_PER_LUN		128
 #define ISCSI_TCP_MAX_CMD_LEN		16
 
 #define ITT_MASK			(0xfff)
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index d0a0fdbd0fc4..f55b9b3f7b37 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -562,16 +562,28 @@ static const u8 ata_rw_cmds[] = {
 	ATA_CMD_WRITE_MULTI,
 	ATA_CMD_READ_MULTI_EXT,
 	ATA_CMD_WRITE_MULTI_EXT,
+	0,
+	0,
+	0,
+	ATA_CMD_WRITE_MULTI_FUA_EXT,
 	/* pio */
 	ATA_CMD_PIO_READ,
 	ATA_CMD_PIO_WRITE,
 	ATA_CMD_PIO_READ_EXT,
 	ATA_CMD_PIO_WRITE_EXT,
+	0,
+	0,
+	0,
+	0,
 	/* dma */
 	ATA_CMD_READ,
 	ATA_CMD_WRITE,
 	ATA_CMD_READ_EXT,
-	ATA_CMD_WRITE_EXT
+	ATA_CMD_WRITE_EXT,
+	0,
+	0,
+	0,
+	ATA_CMD_WRITE_FUA_EXT
 };
 
 /**
@@ -584,28 +596,35 @@ static const u8 ata_rw_cmds[] = {
  *	LOCKING:
  *	caller.
  */
-void ata_rwcmd_protocol(struct ata_queued_cmd *qc)
+int ata_rwcmd_protocol(struct ata_queued_cmd *qc)
 {
 	struct ata_taskfile *tf = &qc->tf;
 	struct ata_device *dev = qc->dev;
+	u8 cmd;
 
-	int index, lba48, write;
+	int index, fua, lba48, write;
  
+	fua = (tf->flags & ATA_TFLAG_FUA) ? 4 : 0;
 	lba48 = (tf->flags & ATA_TFLAG_LBA48) ? 2 : 0;
 	write = (tf->flags & ATA_TFLAG_WRITE) ? 1 : 0;
 
 	if (dev->flags & ATA_DFLAG_PIO) {
 		tf->protocol = ATA_PROT_PIO;
-		index = dev->multi_count ? 0 : 4;
+		index = dev->multi_count ? 0 : 8;
 	} else {
 		tf->protocol = ATA_PROT_DMA;
-		index = 8;
+		index = 16;
 	}
 
-	tf->command = ata_rw_cmds[index + lba48 + write];
+	cmd = ata_rw_cmds[index + fua + lba48 + write];
+	if (cmd) {
+		tf->command = cmd;
+		return 0;
+	}
+	return -1;
 }
 
-static const char * xfer_mode_str[] = {
+static const char * const xfer_mode_str[] = {
 	"UDMA/16",
 	"UDMA/25",
 	"UDMA/33",
@@ -1046,28 +1065,103 @@ static unsigned int ata_pio_modes(const struct ata_device *adev)
 	return modes;
 }
 
-static int ata_qc_wait_err(struct ata_queued_cmd *qc,
-			   struct completion *wait)
+struct ata_exec_internal_arg {
+	unsigned int err_mask;
+	struct ata_taskfile *tf;
+	struct completion *waiting;
+};
+
+int ata_qc_complete_internal(struct ata_queued_cmd *qc)
 {
-	int rc = 0;
+	struct ata_exec_internal_arg *arg = qc->private_data;
+	struct completion *waiting = arg->waiting;
 
-	if (wait_for_completion_timeout(wait, 30 * HZ) < 1) {
-		/* timeout handling */
-		unsigned int err_mask = ac_err_mask(ata_chk_status(qc->ap));
+	if (!(qc->err_mask & ~AC_ERR_DEV))
+		qc->ap->ops->tf_read(qc->ap, arg->tf);
+	arg->err_mask = qc->err_mask;
+	arg->waiting = NULL;
+	complete(waiting);
 
-		if (!err_mask) {
-			printk(KERN_WARNING "ata%u: slow completion (cmd %x)\n",
-			       qc->ap->id, qc->tf.command);
-		} else {
-			printk(KERN_WARNING "ata%u: qc timeout (cmd %x)\n",
-			       qc->ap->id, qc->tf.command);
-			rc = -EIO;
+	return 0;
+}
+
+/**
+ *	ata_exec_internal - execute libata internal command
+ *	@ap: Port to which the command is sent
+ *	@dev: Device to which the command is sent
+ *	@tf: Taskfile registers for the command and the result
+ *	@dma_dir: Data tranfer direction of the command
+ *	@buf: Data buffer of the command
+ *	@buflen: Length of data buffer
+ *
+ *	Executes libata internal command with timeout.  @tf contains
+ *	command on entry and result on return.  Timeout and error
+ *	conditions are reported via return value.  No recovery action
+ *	is taken after a command times out.  It's caller's duty to
+ *	clean up after timeout.
+ *
+ *	LOCKING:
+ *	None.  Should be called with kernel context, might sleep.
+ */
+
+static unsigned
+ata_exec_internal(struct ata_port *ap, struct ata_device *dev,
+		  struct ata_taskfile *tf,
+		  int dma_dir, void *buf, unsigned int buflen)
+{
+	u8 command = tf->command;
+	struct ata_queued_cmd *qc;
+	DECLARE_COMPLETION(wait);
+	unsigned long flags;
+	struct ata_exec_internal_arg arg;
+
+	spin_lock_irqsave(&ap->host_set->lock, flags);
+
+	qc = ata_qc_new_init(ap, dev);
+	BUG_ON(qc == NULL);
+
+	qc->tf = *tf;
+	qc->dma_dir = dma_dir;
+	if (dma_dir != DMA_NONE) {
+		ata_sg_init_one(qc, buf, buflen);
+		qc->nsect = buflen / ATA_SECT_SIZE;
+	}
+
+	arg.waiting = &wait;
+	arg.tf = tf;
+	qc->private_data = &arg;
+	qc->complete_fn = ata_qc_complete_internal;
+
+	if (ata_qc_issue(qc))
+		goto issue_fail;
+
+	spin_unlock_irqrestore(&ap->host_set->lock, flags);
+
+	if (!wait_for_completion_timeout(&wait, ATA_TMOUT_INTERNAL)) {
+		spin_lock_irqsave(&ap->host_set->lock, flags);
+
+		/* We're racing with irq here.  If we lose, the
+		 * following test prevents us from completing the qc
+		 * again.  If completion irq occurs after here but
+		 * before the caller cleans up, it will result in a
+		 * spurious interrupt.  We can live with that.
+		 */
+		if (arg.waiting) {
+			qc->err_mask = AC_ERR_OTHER;
+			ata_qc_complete(qc);
+			printk(KERN_WARNING "ata%u: qc timeout (cmd 0x%x)\n",
+			       ap->id, command);
 		}
 
-		ata_qc_complete(qc, err_mask);
+		spin_unlock_irqrestore(&ap->host_set->lock, flags);
 	}
 
-	return rc;
+	return arg.err_mask;
+
+ issue_fail:
+	ata_qc_free(qc);
+	spin_unlock_irqrestore(&ap->host_set->lock, flags);
+	return AC_ERR_OTHER;
 }
 
 /**
@@ -1099,9 +1193,8 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device)
 	u16 tmp;
 	unsigned long xfer_modes;
 	unsigned int using_edd;
-	DECLARE_COMPLETION(wait);
-	struct ata_queued_cmd *qc;
-	unsigned long flags;
+	struct ata_taskfile tf;
+	unsigned int err_mask;
 	int rc;
 
 	if (!ata_dev_present(dev)) {
@@ -1122,40 +1215,26 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device)
 
 	ata_dev_select(ap, device, 1, 1); /* select device 0/1 */
 
-	qc = ata_qc_new_init(ap, dev);
-	BUG_ON(qc == NULL);
-
-	ata_sg_init_one(qc, dev->id, sizeof(dev->id));
-	qc->dma_dir = DMA_FROM_DEVICE;
-	qc->tf.protocol = ATA_PROT_PIO;
-	qc->nsect = 1;
-
 retry:
+	ata_tf_init(ap, &tf, device);
+
 	if (dev->class == ATA_DEV_ATA) {
-		qc->tf.command = ATA_CMD_ID_ATA;
+		tf.command = ATA_CMD_ID_ATA;
 		DPRINTK("do ATA identify\n");
 	} else {
-		qc->tf.command = ATA_CMD_ID_ATAPI;
+		tf.command = ATA_CMD_ID_ATAPI;
 		DPRINTK("do ATAPI identify\n");
 	}
 
-	qc->waiting = &wait;
-	qc->complete_fn = ata_qc_complete_noop;
-
-	spin_lock_irqsave(&ap->host_set->lock, flags);
-	rc = ata_qc_issue(qc);
-	spin_unlock_irqrestore(&ap->host_set->lock, flags);
+	tf.protocol = ATA_PROT_PIO;
 
-	if (rc)
-		goto err_out;
-	else
-		ata_qc_wait_err(qc, &wait);
+	err_mask = ata_exec_internal(ap, dev, &tf, DMA_FROM_DEVICE,
+				     dev->id, sizeof(dev->id));
 
-	spin_lock_irqsave(&ap->host_set->lock, flags);
-	ap->ops->tf_read(ap, &qc->tf);
-	spin_unlock_irqrestore(&ap->host_set->lock, flags);
+	if (err_mask) {
+		if (err_mask & ~AC_ERR_DEV)
+			goto err_out;
 
-	if (qc->tf.command & ATA_ERR) {
 		/*
 		 * arg!  EDD works for all test cases, but seems to return
 		 * the ATA signature for some ATAPI devices.  Until the
@@ -1168,13 +1247,9 @@ retry:
 		 * to have this problem.
 		 */
 		if ((using_edd) && (dev->class == ATA_DEV_ATA)) {
-			u8 err = qc->tf.feature;
+			u8 err = tf.feature;
 			if (err & ATA_ABORTED) {
 				dev->class = ATA_DEV_ATAPI;
-				qc->cursg = 0;
-				qc->cursg_ofs = 0;
-				qc->cursect = 0;
-				qc->nsect = 1;
 				goto retry;
 			}
 		}
@@ -1444,11 +1519,23 @@ void __sata_phy_reset(struct ata_port *ap)
 	} while (time_before(jiffies, timeout));
 
 	/* TODO: phy layer with polling, timeouts, etc. */
-	if (sata_dev_present(ap))
+	sstatus = scr_read(ap, SCR_STATUS);
+	if (sata_dev_present(ap)) {
+		const char *speed;
+		u32 tmp;
+
+		tmp = (sstatus >> 4) & 0xf;
+		if (tmp & (1 << 0))
+			speed = "1.5";
+		else if (tmp & (1 << 1))
+			speed = "3.0";
+		else
+			speed = "<unknown>";
+		printk(KERN_INFO "ata%u: SATA link up %s Gbps (SStatus %X)\n",
+		       ap->id, speed, sstatus);
 		ata_port_probe(ap);
-	else {
-		sstatus = scr_read(ap, SCR_STATUS);
-		printk(KERN_INFO "ata%u: no device found (phy stat %08x)\n",
+	} else {
+		printk(KERN_INFO "ata%u: SATA link down (SStatus %X)\n",
 		       ap->id, sstatus);
 		ata_port_disable(ap);
 	}
@@ -2071,7 +2158,7 @@ static void ata_pr_blacklisted(const struct ata_port *ap,
 		ap->id, dev->devno);
 }
 
-static const char * ata_dma_blacklist [] = {
+static const char * const ata_dma_blacklist [] = {
 	"WDC AC11000H",
 	"WDC AC22100H",
 	"WDC AC32500H",
@@ -2266,34 +2353,23 @@ static int ata_choose_xfer_mode(const struct ata_port *ap,
 
 static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev)
 {
-	DECLARE_COMPLETION(wait);
-	struct ata_queued_cmd *qc;
-	int rc;
-	unsigned long flags;
+	struct ata_taskfile tf;
 
 	/* set up set-features taskfile */
 	DPRINTK("set features - xfer mode\n");
 
-	qc = ata_qc_new_init(ap, dev);
-	BUG_ON(qc == NULL);
-
-	qc->tf.command = ATA_CMD_SET_FEATURES;
-	qc->tf.feature = SETFEATURES_XFER;
-	qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
-	qc->tf.protocol = ATA_PROT_NODATA;
-	qc->tf.nsect = dev->xfer_mode;
-
-	qc->waiting = &wait;
-	qc->complete_fn = ata_qc_complete_noop;
-
-	spin_lock_irqsave(&ap->host_set->lock, flags);
-	rc = ata_qc_issue(qc);
-	spin_unlock_irqrestore(&ap->host_set->lock, flags);
+	ata_tf_init(ap, &tf, dev->devno);
+	tf.command = ATA_CMD_SET_FEATURES;
+	tf.feature = SETFEATURES_XFER;
+	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+	tf.protocol = ATA_PROT_NODATA;
+	tf.nsect = dev->xfer_mode;
 
-	if (rc)
+	if (ata_exec_internal(ap, dev, &tf, DMA_NONE, NULL, 0)) {
+		printk(KERN_ERR "ata%u: failed to set xfermode, disabled\n",
+		       ap->id);
 		ata_port_disable(ap);
-	else
-		ata_qc_wait_err(qc, &wait);
+	}
 
 	DPRINTK("EXIT\n");
 }
@@ -2308,41 +2384,25 @@ static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev)
 
 static void ata_dev_reread_id(struct ata_port *ap, struct ata_device *dev)
 {
-	DECLARE_COMPLETION(wait);
-	struct ata_queued_cmd *qc;
-	unsigned long flags;
-	int rc;
-
-	qc = ata_qc_new_init(ap, dev);
-	BUG_ON(qc == NULL);
+	struct ata_taskfile tf;
 
-	ata_sg_init_one(qc, dev->id, sizeof(dev->id));
-	qc->dma_dir = DMA_FROM_DEVICE;
+	ata_tf_init(ap, &tf, dev->devno);
 
 	if (dev->class == ATA_DEV_ATA) {
-		qc->tf.command = ATA_CMD_ID_ATA;
+		tf.command = ATA_CMD_ID_ATA;
 		DPRINTK("do ATA identify\n");
 	} else {
-		qc->tf.command = ATA_CMD_ID_ATAPI;
+		tf.command = ATA_CMD_ID_ATAPI;
 		DPRINTK("do ATAPI identify\n");
 	}
 
-	qc->tf.flags |= ATA_TFLAG_DEVICE;
-	qc->tf.protocol = ATA_PROT_PIO;
-	qc->nsect = 1;
-
-	qc->waiting = &wait;
-	qc->complete_fn = ata_qc_complete_noop;
+	tf.flags |= ATA_TFLAG_DEVICE;
+	tf.protocol = ATA_PROT_PIO;
 
-	spin_lock_irqsave(&ap->host_set->lock, flags);
-	rc = ata_qc_issue(qc);
-	spin_unlock_irqrestore(&ap->host_set->lock, flags);
-
-	if (rc)
+	if (ata_exec_internal(ap, dev, &tf, DMA_FROM_DEVICE,
+			      dev->id, sizeof(dev->id)))
 		goto err_out;
 
-	ata_qc_wait_err(qc, &wait);
-
 	swap_buf_le16(dev->id, ATA_ID_WORDS);
 
 	ata_dump_id(dev);
@@ -2351,6 +2411,7 @@ static void ata_dev_reread_id(struct ata_port *ap, struct ata_device *dev)
 
 	return;
 err_out:
+	printk(KERN_ERR "ata%u: failed to reread ID, disabled\n", ap->id);
 	ata_port_disable(ap);
 }
 
@@ -2364,10 +2425,7 @@ err_out:
 
 static void ata_dev_init_params(struct ata_port *ap, struct ata_device *dev)
 {
-	DECLARE_COMPLETION(wait);
-	struct ata_queued_cmd *qc;
-	int rc;
-	unsigned long flags;
+	struct ata_taskfile tf;
 	u16 sectors = dev->id[6];
 	u16 heads   = dev->id[3];
 
@@ -2378,26 +2436,18 @@ static void ata_dev_init_params(struct ata_port *ap, struct ata_device *dev)
 	/* set up init dev params taskfile */
 	DPRINTK("init dev params \n");
 
-	qc = ata_qc_new_init(ap, dev);
-	BUG_ON(qc == NULL);
-
-	qc->tf.command = ATA_CMD_INIT_DEV_PARAMS;
-	qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
-	qc->tf.protocol = ATA_PROT_NODATA;
-	qc->tf.nsect = sectors;
-	qc->tf.device |= (heads - 1) & 0x0f; /* max head = num. of heads - 1 */
-
-	qc->waiting = &wait;
-	qc->complete_fn = ata_qc_complete_noop;
-
-	spin_lock_irqsave(&ap->host_set->lock, flags);
-	rc = ata_qc_issue(qc);
-	spin_unlock_irqrestore(&ap->host_set->lock, flags);
+	ata_tf_init(ap, &tf, dev->devno);
+	tf.command = ATA_CMD_INIT_DEV_PARAMS;
+	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+	tf.protocol = ATA_PROT_NODATA;
+	tf.nsect = sectors;
+	tf.device |= (heads - 1) & 0x0f; /* max head = num. of heads - 1 */
 
-	if (rc)
+	if (ata_exec_internal(ap, dev, &tf, DMA_NONE, NULL, 0)) {
+		printk(KERN_ERR "ata%u: failed to init parameters, disabled\n",
+		       ap->id);
 		ata_port_disable(ap);
-	else
-		ata_qc_wait_err(qc, &wait);
+	}
 
 	DPRINTK("EXIT\n");
 }
@@ -2765,7 +2815,7 @@ skip_map:
  *	None.  (grabs host lock)
  */
 
-void ata_poll_qc_complete(struct ata_queued_cmd *qc, unsigned int err_mask)
+void ata_poll_qc_complete(struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
 	unsigned long flags;
@@ -2773,7 +2823,7 @@ void ata_poll_qc_complete(struct ata_queued_cmd *qc, unsigned int err_mask)
 	spin_lock_irqsave(&ap->host_set->lock, flags);
 	ap->flags &= ~ATA_FLAG_NOINTR;
 	ata_irq_on(ap);
-	ata_qc_complete(qc, err_mask);
+	ata_qc_complete(qc);
 	spin_unlock_irqrestore(&ap->host_set->lock, flags);
 }
 
@@ -2790,10 +2840,14 @@ void ata_poll_qc_complete(struct ata_queued_cmd *qc, unsigned int err_mask)
 
 static unsigned long ata_pio_poll(struct ata_port *ap)
 {
+	struct ata_queued_cmd *qc;
 	u8 status;
 	unsigned int poll_state = HSM_ST_UNKNOWN;
 	unsigned int reg_state = HSM_ST_UNKNOWN;
 
+	qc = ata_qc_from_tag(ap, ap->active_tag);
+	assert(qc != NULL);
+
 	switch (ap->hsm_task_state) {
 	case HSM_ST:
 	case HSM_ST_POLL:
@@ -2813,6 +2867,7 @@ static unsigned long ata_pio_poll(struct ata_port *ap)
 	status = ata_chk_status(ap);
 	if (status & ATA_BUSY) {
 		if (time_after(jiffies, ap->pio_task_timeout)) {
+			qc->err_mask |= AC_ERR_ATA_BUS;
 			ap->hsm_task_state = HSM_ST_TMOUT;
 			return 0;
 		}
@@ -2847,29 +2902,31 @@ static int ata_pio_complete (struct ata_port *ap)
 	 * msecs, then chk-status again.  If still busy, fall back to
 	 * HSM_ST_POLL state.
 	 */
-	drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 10);
-	if (drv_stat & (ATA_BUSY | ATA_DRQ)) {
+	drv_stat = ata_busy_wait(ap, ATA_BUSY, 10);
+	if (drv_stat & ATA_BUSY) {
 		msleep(2);
-		drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 10);
-		if (drv_stat & (ATA_BUSY | ATA_DRQ)) {
+		drv_stat = ata_busy_wait(ap, ATA_BUSY, 10);
+		if (drv_stat & ATA_BUSY) {
 			ap->hsm_task_state = HSM_ST_LAST_POLL;
 			ap->pio_task_timeout = jiffies + ATA_TMOUT_PIO;
 			return 0;
 		}
 	}
 
+	qc = ata_qc_from_tag(ap, ap->active_tag);
+	assert(qc != NULL);
+
 	drv_stat = ata_wait_idle(ap);
 	if (!ata_ok(drv_stat)) {
+		qc->err_mask |= __ac_err_mask(drv_stat);
 		ap->hsm_task_state = HSM_ST_ERR;
 		return 0;
 	}
 
-	qc = ata_qc_from_tag(ap, ap->active_tag);
-	assert(qc != NULL);
-
 	ap->hsm_task_state = HSM_ST_IDLE;
 
-	ata_poll_qc_complete(qc, 0);
+	assert(qc->err_mask == 0);
+	ata_poll_qc_complete(qc);
 
 	/* another command may start at this point */
 
@@ -3177,6 +3234,7 @@ static void atapi_pio_bytes(struct ata_queued_cmd *qc)
 err_out:
 	printk(KERN_INFO "ata%u: dev %u: ATAPI check failed\n",
 	      ap->id, dev->devno);
+	qc->err_mask |= AC_ERR_ATA_BUS;
 	ap->hsm_task_state = HSM_ST_ERR;
 }
 
@@ -3215,8 +3273,16 @@ static void ata_pio_block(struct ata_port *ap)
 	qc = ata_qc_from_tag(ap, ap->active_tag);
 	assert(qc != NULL);
 
+	/* check error */
+	if (status & (ATA_ERR | ATA_DF)) {
+		qc->err_mask |= AC_ERR_DEV;
+		ap->hsm_task_state = HSM_ST_ERR;
+		return;
+	}
+
+	/* transfer data if any */
 	if (is_atapi_taskfile(&qc->tf)) {
-		/* no more data to transfer or unsupported ATAPI command */
+		/* DRQ=0 means no more data to transfer */
 		if ((status & ATA_DRQ) == 0) {
 			ap->hsm_task_state = HSM_ST_LAST;
 			return;
@@ -3226,6 +3292,7 @@ static void ata_pio_block(struct ata_port *ap)
 	} else {
 		/* handle BSY=0, DRQ=0 as error */
 		if ((status & ATA_DRQ) == 0) {
+			qc->err_mask |= AC_ERR_ATA_BUS;
 			ap->hsm_task_state = HSM_ST_ERR;
 			return;
 		}
@@ -3243,9 +3310,14 @@ static void ata_pio_error(struct ata_port *ap)
 	qc = ata_qc_from_tag(ap, ap->active_tag);
 	assert(qc != NULL);
 
+	/* make sure qc->err_mask is available to 
+	 * know what's wrong and recover
+	 */
+	assert(qc->err_mask);
+
 	ap->hsm_task_state = HSM_ST_IDLE;
 
-	ata_poll_qc_complete(qc, AC_ERR_ATA_BUS);
+	ata_poll_qc_complete(qc);
 }
 
 static void ata_pio_task(void *_data)
@@ -3347,7 +3419,8 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc)
 		       ap->id, qc->tf.command, drv_stat, host_stat);
 
 		/* complete taskfile transaction */
-		ata_qc_complete(qc, ac_err_mask(drv_stat));
+		qc->err_mask |= ac_err_mask(drv_stat);
+		ata_qc_complete(qc);
 		break;
 	}
 
@@ -3446,15 +3519,10 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
 	return qc;
 }
 
-int ata_qc_complete_noop(struct ata_queued_cmd *qc, unsigned int err_mask)
-{
-	return 0;
-}
-
 static void __ata_qc_complete(struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
-	unsigned int tag, do_clear = 0;
+	unsigned int tag;
 
 	qc->flags = 0;
 	tag = qc->tag;
@@ -3462,17 +3530,8 @@ static void __ata_qc_complete(struct ata_queued_cmd *qc)
 		if (tag == ap->active_tag)
 			ap->active_tag = ATA_TAG_POISON;
 		qc->tag = ATA_TAG_POISON;
-		do_clear = 1;
-	}
-
-	if (qc->waiting) {
-		struct completion *waiting = qc->waiting;
-		qc->waiting = NULL;
-		complete(waiting);
-	}
-
-	if (likely(do_clear))
 		clear_bit(tag, &ap->qactive);
+	}
 }
 
 /**
@@ -3488,7 +3547,6 @@ static void __ata_qc_complete(struct ata_queued_cmd *qc)
 void ata_qc_free(struct ata_queued_cmd *qc)
 {
 	assert(qc != NULL);	/* ata_qc_from_tag _might_ return NULL */
-	assert(qc->waiting == NULL);	/* nothing should be waiting */
 
 	__ata_qc_complete(qc);
 }
@@ -3505,7 +3563,7 @@ void ata_qc_free(struct ata_queued_cmd *qc)
  *	spin_lock_irqsave(host_set lock)
  */
 
-void ata_qc_complete(struct ata_queued_cmd *qc, unsigned int err_mask)
+void ata_qc_complete(struct ata_queued_cmd *qc)
 {
 	int rc;
 
@@ -3522,7 +3580,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc, unsigned int err_mask)
 	qc->flags &= ~ATA_QCFLAG_ACTIVE;
 
 	/* call completion callback */
-	rc = qc->complete_fn(qc, err_mask);
+	rc = qc->complete_fn(qc);
 
 	/* if callback indicates not to complete command (non-zero),
 	 * return immediately
@@ -3960,7 +4018,8 @@ inline unsigned int ata_host_intr (struct ata_port *ap,
 		ap->ops->irq_clear(ap);
 
 		/* complete taskfile transaction */
-		ata_qc_complete(qc, ac_err_mask(status));
+		qc->err_mask |= ac_err_mask(status);
+		ata_qc_complete(qc);
 		break;
 
 	default:
@@ -4054,13 +4113,17 @@ static void atapi_packet_task(void *_data)
 
 	/* sleep-wait for BSY to clear */
 	DPRINTK("busy wait\n");
-	if (ata_busy_sleep(ap, ATA_TMOUT_CDB_QUICK, ATA_TMOUT_CDB))
-		goto err_out_status;
+	if (ata_busy_sleep(ap, ATA_TMOUT_CDB_QUICK, ATA_TMOUT_CDB)) {
+		qc->err_mask |= AC_ERR_ATA_BUS;
+		goto err_out;
+	}
 
 	/* make sure DRQ is set */
 	status = ata_chk_status(ap);
-	if ((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ)
+	if ((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ) {
+		qc->err_mask |= AC_ERR_ATA_BUS;
 		goto err_out;
+	}
 
 	/* send SCSI cdb */
 	DPRINTK("send cdb\n");
@@ -4092,10 +4155,8 @@ static void atapi_packet_task(void *_data)
 
 	return;
 
-err_out_status:
-	status = ata_chk_status(ap);
 err_out:
-	ata_poll_qc_complete(qc, __ac_err_mask(status));
+	ata_poll_qc_complete(qc);
 }
 
 
@@ -4112,6 +4173,96 @@ err_out:
  *	Inherited from caller.
  */
 
+/*
+ * Execute a 'simple' command, that only consists of the opcode 'cmd' itself,
+ * without filling any other registers
+ */
+static int ata_do_simple_cmd(struct ata_port *ap, struct ata_device *dev,
+			     u8 cmd)
+{
+	struct ata_taskfile tf;
+	int err;
+
+	ata_tf_init(ap, &tf, dev->devno);
+
+	tf.command = cmd;
+	tf.flags |= ATA_TFLAG_DEVICE;
+	tf.protocol = ATA_PROT_NODATA;
+
+	err = ata_exec_internal(ap, dev, &tf, DMA_NONE, NULL, 0);
+	if (err)
+		printk(KERN_ERR "%s: ata command failed: %d\n",
+				__FUNCTION__, err);
+
+	return err;
+}
+
+static int ata_flush_cache(struct ata_port *ap, struct ata_device *dev)
+{
+	u8 cmd;
+
+	if (!ata_try_flush_cache(dev))
+		return 0;
+
+	if (ata_id_has_flush_ext(dev->id))
+		cmd = ATA_CMD_FLUSH_EXT;
+	else
+		cmd = ATA_CMD_FLUSH;
+
+	return ata_do_simple_cmd(ap, dev, cmd);
+}
+
+static int ata_standby_drive(struct ata_port *ap, struct ata_device *dev)
+{
+	return ata_do_simple_cmd(ap, dev, ATA_CMD_STANDBYNOW1);
+}
+
+static int ata_start_drive(struct ata_port *ap, struct ata_device *dev)
+{
+	return ata_do_simple_cmd(ap, dev, ATA_CMD_IDLEIMMEDIATE);
+}
+
+/**
+ *	ata_device_resume - wakeup a previously suspended devices
+ *
+ *	Kick the drive back into action, by sending it an idle immediate
+ *	command and making sure its transfer mode matches between drive
+ *	and host.
+ *
+ */
+int ata_device_resume(struct ata_port *ap, struct ata_device *dev)
+{
+	if (ap->flags & ATA_FLAG_SUSPENDED) {
+		ap->flags &= ~ATA_FLAG_SUSPENDED;
+		ata_set_mode(ap);
+	}
+	if (!ata_dev_present(dev))
+		return 0;
+	if (dev->class == ATA_DEV_ATA)
+		ata_start_drive(ap, dev);
+
+	return 0;
+}
+
+/**
+ *	ata_device_suspend - prepare a device for suspend
+ *
+ *	Flush the cache on the drive, if appropriate, then issue a
+ *	standbynow command.
+ *
+ */
+int ata_device_suspend(struct ata_port *ap, struct ata_device *dev)
+{
+	if (!ata_dev_present(dev))
+		return 0;
+	if (dev->class == ATA_DEV_ATA)
+		ata_flush_cache(ap, dev);
+
+	ata_standby_drive(ap, dev);
+	ap->flags |= ATA_FLAG_SUSPENDED;
+	return 0;
+}
+
 int ata_port_start (struct ata_port *ap)
 {
 	struct device *dev = ap->host_set->dev;
@@ -4860,6 +5011,23 @@ int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits)
 
 	return (tmp == bits->val) ? 1 : 0;
 }
+
+int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	pci_save_state(pdev);
+	pci_disable_device(pdev);
+	pci_set_power_state(pdev, PCI_D3hot);
+	return 0;
+}
+
+int ata_pci_device_resume(struct pci_dev *pdev)
+{
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
+	pci_enable_device(pdev);
+	pci_set_master(pdev);
+	return 0;
+}
 #endif /* CONFIG_PCI */
 
 
@@ -4963,4 +5131,11 @@ EXPORT_SYMBOL_GPL(ata_pci_host_stop);
 EXPORT_SYMBOL_GPL(ata_pci_init_native_mode);
 EXPORT_SYMBOL_GPL(ata_pci_init_one);
 EXPORT_SYMBOL_GPL(ata_pci_remove_one);
+EXPORT_SYMBOL_GPL(ata_pci_device_suspend);
+EXPORT_SYMBOL_GPL(ata_pci_device_resume);
 #endif /* CONFIG_PCI */
+
+EXPORT_SYMBOL_GPL(ata_device_suspend);
+EXPORT_SYMBOL_GPL(ata_device_resume);
+EXPORT_SYMBOL_GPL(ata_scsi_device_suspend);
+EXPORT_SYMBOL_GPL(ata_scsi_device_resume);
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index 2282c04fee46..cfbceb504718 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -396,6 +396,22 @@ void ata_dump_status(unsigned id, struct ata_taskfile *tf)
 	}
 }
 
+int ata_scsi_device_resume(struct scsi_device *sdev)
+{
+	struct ata_port *ap = (struct ata_port *) &sdev->host->hostdata[0];
+	struct ata_device *dev = &ap->device[sdev->id];
+
+	return ata_device_resume(ap, dev);
+}
+
+int ata_scsi_device_suspend(struct scsi_device *sdev)
+{
+	struct ata_port *ap = (struct ata_port *) &sdev->host->hostdata[0];
+	struct ata_device *dev = &ap->device[sdev->id];
+
+	return ata_device_suspend(ap, dev);
+}
+
 /**
  *	ata_to_sense_error - convert ATA error to SCSI error
  *	@id: ATA device number
@@ -418,7 +434,7 @@ void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc,
 	int i;
 
 	/* Based on the 3ware driver translation table */
-	static unsigned char sense_table[][4] = {
+	static const unsigned char sense_table[][4] = {
 		/* BBD|ECC|ID|MAR */
 		{0xd1, 		ABORTED_COMMAND, 0x00, 0x00}, 	// Device busy                  Aborted command
 		/* BBD|ECC|ID */
@@ -449,7 +465,7 @@ void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc,
 		{0x80, 		MEDIUM_ERROR, 0x11, 0x04}, 	// Block marked bad		  Medium error, unrecovered read error
 		{0xFF, 0xFF, 0xFF, 0xFF}, // END mark
 	};
-	static unsigned char stat_table[][4] = {
+	static const unsigned char stat_table[][4] = {
 		/* Must be first because BUSY means no other bits valid */
 		{0x80, 		ABORTED_COMMAND, 0x47, 0x00},	// Busy, fake parity for now
 		{0x20, 		HARDWARE_ERROR,  0x00, 0x00}, 	// Device fault
@@ -1080,11 +1096,13 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm
 	    scsicmd[0] == WRITE_16)
 		tf->flags |= ATA_TFLAG_WRITE;
 
-	/* Calculate the SCSI LBA and transfer length. */
+	/* Calculate the SCSI LBA, transfer length and FUA. */
 	switch (scsicmd[0]) {
 	case READ_10:
 	case WRITE_10:
 		scsi_10_lba_len(scsicmd, &block, &n_block);
+		if (unlikely(scsicmd[1] & (1 << 3)))
+			tf->flags |= ATA_TFLAG_FUA;
 		break;
 	case READ_6:
 	case WRITE_6:
@@ -1099,6 +1117,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm
 	case READ_16:
 	case WRITE_16:
 		scsi_16_lba_len(scsicmd, &block, &n_block);
+		if (unlikely(scsicmd[1] & (1 << 3)))
+			tf->flags |= ATA_TFLAG_FUA;
 		break;
 	default:
 		DPRINTK("no-byte command\n");
@@ -1142,7 +1162,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm
 			tf->device |= (block >> 24) & 0xf;
 		}
 
-		ata_rwcmd_protocol(qc);
+		if (unlikely(ata_rwcmd_protocol(qc) < 0))
+			goto invalid_fld;
 
 		qc->nsect = n_block;
 		tf->nsect = n_block & 0xff;
@@ -1160,7 +1181,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm
 		if ((block >> 28) || (n_block > 256))
 			goto out_of_range;
 
-		ata_rwcmd_protocol(qc);
+		if (unlikely(ata_rwcmd_protocol(qc) < 0))
+			goto invalid_fld;
 
 		/* Convert LBA to CHS */
 		track = (u32)block / dev->sectors;
@@ -1203,12 +1225,11 @@ nothing_to_do:
 	return 1;
 }
 
-static int ata_scsi_qc_complete(struct ata_queued_cmd *qc,
-				unsigned int err_mask)
+static int ata_scsi_qc_complete(struct ata_queued_cmd *qc)
 {
 	struct scsi_cmnd *cmd = qc->scsicmd;
 	u8 *cdb = cmd->cmnd;
- 	int need_sense = (err_mask != 0);
+ 	int need_sense = (qc->err_mask != 0);
 
 	/* For ATA pass thru (SAT) commands, generate a sense block if
 	 * user mandated it or if there's an error.  Note that if we
@@ -1532,7 +1553,7 @@ unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf,
 	return 0;
 }
 
-static const char *inq_83_str = "Linux ATA-SCSI simulator";
+static const char * const inq_83_str = "Linux ATA-SCSI simulator";
 
 /**
  *	ata_scsiop_inq_83 - Simulate INQUIRY EVPD page 83, device identity
@@ -1696,6 +1717,7 @@ static unsigned int ata_msense_rw_recovery(u8 **ptr_io, const u8 *last)
 unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
 				  unsigned int buflen)
 {
+	struct ata_device *dev = args->dev;
 	u8 *scsicmd = args->cmd->cmnd, *p, *last;
 	const u8 sat_blk_desc[] = {
 		0, 0, 0, 0,	/* number of blocks: sat unspecified */
@@ -1704,6 +1726,7 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
 	};
 	u8 pg, spg;
 	unsigned int ebd, page_control, six_byte, output_len, alloc_len, minlen;
+	u8 dpofua;
 
 	VPRINTK("ENTER\n");
 
@@ -1772,9 +1795,17 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
 
 	if (minlen < 1)
 		return 0;
+
+	dpofua = 0;
+	if (ata_id_has_fua(args->id) && dev->flags & ATA_DFLAG_LBA48 &&
+	    (!(dev->flags & ATA_DFLAG_PIO) || dev->multi_count))
+		dpofua = 1 << 4;
+
 	if (six_byte) {
 		output_len--;
 		rbuf[0] = output_len;
+		if (minlen > 2)
+			rbuf[2] |= dpofua;
 		if (ebd) {
 			if (minlen > 3)
 				rbuf[3] = sizeof(sat_blk_desc);
@@ -1787,6 +1818,8 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
 		rbuf[0] = output_len >> 8;
 		if (minlen > 1)
 			rbuf[1] = output_len;
+		if (minlen > 3)
+			rbuf[3] |= dpofua;
 		if (ebd) {
 			if (minlen > 7)
 				rbuf[7] = sizeof(sat_blk_desc);
@@ -1955,9 +1988,9 @@ void ata_scsi_badcmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), u8
 	done(cmd);
 }
 
-static int atapi_sense_complete(struct ata_queued_cmd *qc,unsigned int err_mask)
+static int atapi_sense_complete(struct ata_queued_cmd *qc)
 {
-	if (err_mask && ((err_mask & AC_ERR_DEV) == 0))
+	if (qc->err_mask && ((qc->err_mask & AC_ERR_DEV) == 0))
 		/* FIXME: not quite right; we don't want the
 		 * translation of taskfile registers into
 		 * a sense descriptors, since that's only
@@ -2015,15 +2048,18 @@ static void atapi_request_sense(struct ata_queued_cmd *qc)
 
 	qc->complete_fn = atapi_sense_complete;
 
-	if (ata_qc_issue(qc))
-		ata_qc_complete(qc, AC_ERR_OTHER);
+	if (ata_qc_issue(qc)) {
+		qc->err_mask |= AC_ERR_OTHER;
+		ata_qc_complete(qc);
+	}
 
 	DPRINTK("EXIT\n");
 }
 
-static int atapi_qc_complete(struct ata_queued_cmd *qc, unsigned int err_mask)
+static int atapi_qc_complete(struct ata_queued_cmd *qc)
 {
 	struct scsi_cmnd *cmd = qc->scsicmd;
+	unsigned int err_mask = qc->err_mask;
 
 	VPRINTK("ENTER, err_mask 0x%X\n", err_mask);
 
@@ -2444,7 +2480,7 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 		if (xlat_func)
 			ata_scsi_translate(ap, dev, cmd, done, xlat_func);
 		else
-			ata_scsi_simulate(dev->id, cmd, done);
+			ata_scsi_simulate(ap, dev, cmd, done);
 	} else
 		ata_scsi_translate(ap, dev, cmd, done, atapi_xlat);
 
@@ -2467,14 +2503,16 @@ out_unlock:
  *	spin_lock_irqsave(host_set lock)
  */
 
-void ata_scsi_simulate(u16 *id,
+void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev,
 		      struct scsi_cmnd *cmd,
 		      void (*done)(struct scsi_cmnd *))
 {
 	struct ata_scsi_args args;
 	const u8 *scsicmd = cmd->cmnd;
 
-	args.id = id;
+	args.ap = ap;
+	args.dev = dev;
+	args.id = dev->id;
 	args.cmd = cmd;
 	args.done = done;
 
diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h
index 8ebaa694d18e..e03ce48b7b4b 100644
--- a/drivers/scsi/libata.h
+++ b/drivers/scsi/libata.h
@@ -32,6 +32,8 @@
 #define DRV_VERSION	"1.20"	/* must be exactly four chars */
 
 struct ata_scsi_args {
+	struct ata_port		*ap;
+	struct ata_device	*dev;
 	u16			*id;
 	struct scsi_cmnd	*cmd;
 	void			(*done)(struct scsi_cmnd *);
@@ -39,10 +41,9 @@ struct ata_scsi_args {
 
 /* libata-core.c */
 extern int atapi_enabled;
-extern int ata_qc_complete_noop(struct ata_queued_cmd *qc, unsigned int err_mask);
 extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
 				      struct ata_device *dev);
-extern void ata_rwcmd_protocol(struct ata_queued_cmd *qc);
+extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc);
 extern void ata_qc_free(struct ata_queued_cmd *qc);
 extern int ata_qc_issue(struct ata_queued_cmd *qc);
 extern int ata_check_atapi_dma(struct ata_queued_cmd *qc);
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 3062b39fbdb9..38ffa8d6e629 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -29,9 +29,10 @@ struct lpfc_sli2_slim;
 #define LPFC_LC_HBA_Q_DEPTH	1024	/* max cmds per low cost hba */
 #define LPFC_LP101_HBA_Q_DEPTH	128	/* max cmds per low cost hba */
 
-#define LPFC_CMD_PER_LUN	30	/* max outstanding cmds per lun */
+#define LPFC_CMD_PER_LUN	3	/* max outstanding cmds per lun */
 #define LPFC_SG_SEG_CNT		64	/* sg element count per scsi cmnd */
 #define LPFC_IOCB_LIST_CNT	2250	/* list of IOCBs for fast-path usage. */
+#define LPFC_Q_RAMP_UP_INTERVAL 120     /* lun q_depth ramp up interval */
 
 /* Define macros for 64 bit support */
 #define putPaddrLow(addr)    ((uint32_t) (0xffffffff & (u64)(addr)))
@@ -45,6 +46,11 @@ struct lpfc_sli2_slim;
 
 #define MAX_HBAEVT	32
 
+enum lpfc_polling_flags {
+	ENABLE_FCP_RING_POLLING = 0x1,
+	DISABLE_FCP_RING_INT    = 0x2
+};
+
 /* Provide DMA memory definitions the driver uses per port instance. */
 struct lpfc_dmabuf {
 	struct list_head list;
@@ -167,6 +173,7 @@ struct lpfc_hba {
 	dma_addr_t slim2p_mapping;
 	uint16_t pci_cfg_value;
 
+	struct semaphore hba_can_block;
 	uint32_t hba_state;
 
 #define LPFC_INIT_START           1	/* Initial state after board reset */
@@ -286,6 +293,8 @@ struct lpfc_hba {
 	uint32_t cfg_fcp_bind_method;
 	uint32_t cfg_discovery_threads;
 	uint32_t cfg_max_luns;
+	uint32_t cfg_poll;
+	uint32_t cfg_poll_tmo;
 	uint32_t cfg_sg_seg_cnt;
 	uint32_t cfg_sg_dma_buf_size;
 
@@ -337,7 +346,9 @@ struct lpfc_hba {
 #define VPD_PORT            0x8         /* valid vpd port data */
 #define VPD_MASK            0xf         /* mask for any vpd data */
 
+	struct timer_list fcp_poll_timer;
 	struct timer_list els_tmofunc;
+
 	/*
 	 * stat  counters
 	 */
@@ -348,6 +359,7 @@ struct lpfc_hba {
 	struct lpfc_sysfs_mbox sysfs_mbox;
 
 	/* fastpath list. */
+	spinlock_t scsi_buf_list_lock;
 	struct list_head lpfc_scsi_buf_list;
 	uint32_t total_scsi_bufs;
 	struct list_head lpfc_iocb_list;
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 89e8222bc7cc..5625a8c2a8fd 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -278,6 +278,71 @@ lpfc_board_online_store(struct class_device *cdev, const char *buf,
 		return -EIO;
 }
 
+static ssize_t
+lpfc_poll_show(struct class_device *cdev, char *buf)
+{
+	struct Scsi_Host *host = class_to_shost(cdev);
+	struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0];
+
+	return snprintf(buf, PAGE_SIZE, "%#x\n", phba->cfg_poll);
+}
+
+static ssize_t
+lpfc_poll_store(struct class_device *cdev, const char *buf,
+		size_t count)
+{
+	struct Scsi_Host *host = class_to_shost(cdev);
+	struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0];
+	uint32_t creg_val;
+	uint32_t old_val;
+	int val=0;
+
+	if (!isdigit(buf[0]))
+		return -EINVAL;
+
+	if (sscanf(buf, "%i", &val) != 1)
+		return -EINVAL;
+
+	if ((val & 0x3) != val)
+		return -EINVAL;
+
+	spin_lock_irq(phba->host->host_lock);
+
+	old_val = phba->cfg_poll;
+
+	if (val & ENABLE_FCP_RING_POLLING) {
+		if ((val & DISABLE_FCP_RING_INT) &&
+		    !(old_val & DISABLE_FCP_RING_INT)) {
+			creg_val = readl(phba->HCregaddr);
+			creg_val &= ~(HC_R0INT_ENA << LPFC_FCP_RING);
+			writel(creg_val, phba->HCregaddr);
+			readl(phba->HCregaddr); /* flush */
+
+			lpfc_poll_start_timer(phba);
+		}
+	} else if (val != 0x0) {
+		spin_unlock_irq(phba->host->host_lock);
+		return -EINVAL;
+	}
+
+	if (!(val & DISABLE_FCP_RING_INT) &&
+	    (old_val & DISABLE_FCP_RING_INT))
+	{
+		spin_unlock_irq(phba->host->host_lock);
+		del_timer(&phba->fcp_poll_timer);
+		spin_lock_irq(phba->host->host_lock);
+		creg_val = readl(phba->HCregaddr);
+		creg_val |= (HC_R0INT_ENA << LPFC_FCP_RING);
+		writel(creg_val, phba->HCregaddr);
+		readl(phba->HCregaddr); /* flush */
+	}
+
+	phba->cfg_poll = val;
+
+	spin_unlock_irq(phba->host->host_lock);
+
+	return strlen(buf);
+}
 
 #define lpfc_param_show(attr)	\
 static ssize_t \
@@ -416,6 +481,15 @@ static CLASS_DEVICE_ATTR(management_version, S_IRUGO, management_version_show,
 static CLASS_DEVICE_ATTR(board_online, S_IRUGO | S_IWUSR,
 			 lpfc_board_online_show, lpfc_board_online_store);
 
+static int lpfc_poll = 0;
+module_param(lpfc_poll, int, 0);
+MODULE_PARM_DESC(lpfc_poll, "FCP ring polling mode control:"
+		 " 0 - none,"
+		 " 1 - poll with interrupts enabled"
+		 " 3 - poll and disable FCP ring interrupts");
+
+static CLASS_DEVICE_ATTR(lpfc_poll, S_IRUGO | S_IWUSR,
+			 lpfc_poll_show, lpfc_poll_store);
 
 /*
 # lpfc_log_verbose: Only turn this flag on if you are willing to risk being
@@ -523,10 +597,10 @@ LPFC_ATTR_R(ack0, 0, 0, 1, "Enable ACK0 support");
 # is 0. Default value of cr_count is 1. The cr_count feature is disabled if
 # cr_delay is set to 0.
 */
-LPFC_ATTR(cr_delay, 0, 0, 63, "A count of milliseconds after which an"
+LPFC_ATTR_RW(cr_delay, 0, 0, 63, "A count of milliseconds after which an"
 		"interrupt response is generated");
 
-LPFC_ATTR(cr_count, 1, 1, 255, "A count of I/O completions after which an"
+LPFC_ATTR_RW(cr_count, 1, 1, 255, "A count of I/O completions after which an"
 		"interrupt response is generated");
 
 /*
@@ -553,6 +627,13 @@ LPFC_ATTR(discovery_threads, 32, 1, 64, "Maximum number of ELS commands"
 LPFC_ATTR_R(max_luns, 256, 1, 32768,
 	     "Maximum number of LUNs per target driver will support");
 
+/*
+# lpfc_poll_tmo: .Milliseconds driver will wait between polling FCP ring.
+# Value range is [1,255], default value is 10.
+*/
+LPFC_ATTR_RW(poll_tmo, 10, 1, 255,
+	     "Milliseconds driver will wait between polling FCP ring");
+
 struct class_device_attribute *lpfc_host_attrs[] = {
 	&class_device_attr_info,
 	&class_device_attr_serialnum,
@@ -575,11 +656,15 @@ struct class_device_attribute *lpfc_host_attrs[] = {
 	&class_device_attr_lpfc_topology,
 	&class_device_attr_lpfc_scan_down,
 	&class_device_attr_lpfc_link_speed,
+	&class_device_attr_lpfc_cr_delay,
+	&class_device_attr_lpfc_cr_count,
 	&class_device_attr_lpfc_fdmi_on,
 	&class_device_attr_lpfc_max_luns,
 	&class_device_attr_nport_evt_cnt,
 	&class_device_attr_management_version,
 	&class_device_attr_board_online,
+	&class_device_attr_lpfc_poll,
+	&class_device_attr_lpfc_poll_tmo,
 	NULL,
 };
 
@@ -1292,6 +1377,9 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
 	lpfc_fdmi_on_init(phba, lpfc_fdmi_on);
 	lpfc_discovery_threads_init(phba, lpfc_discovery_threads);
 	lpfc_max_luns_init(phba, lpfc_max_luns);
+	lpfc_poll_tmo_init(phba, lpfc_poll_tmo);
+
+	phba->cfg_poll = lpfc_poll;
 
 	/*
 	 * The total number of segments is the configuration value plus 2
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
index d527d05a607f..f1e708946e66 100644
--- a/drivers/scsi/lpfc/lpfc_crtn.h
+++ b/drivers/scsi/lpfc/lpfc_crtn.h
@@ -143,6 +143,9 @@ LPFC_MBOXQ_t *lpfc_mbox_get(struct lpfc_hba *);
 int lpfc_mem_alloc(struct lpfc_hba *);
 void lpfc_mem_free(struct lpfc_hba *);
 
+void lpfc_poll_timeout(unsigned long ptr);
+void lpfc_poll_start_timer(struct lpfc_hba * phba);
+void lpfc_sli_poll_fcp_ring(struct lpfc_hba * hba);
 struct lpfc_iocbq * lpfc_sli_get_iocbq(struct lpfc_hba *);
 void lpfc_sli_release_iocbq(struct lpfc_hba * phba, struct lpfc_iocbq * iocb);
 uint16_t lpfc_sli_next_iotag(struct lpfc_hba * phba, struct lpfc_iocbq * iocb);
diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h
index 084e7628ce17..ed6c81660e03 100644
--- a/drivers/scsi/lpfc/lpfc_disc.h
+++ b/drivers/scsi/lpfc/lpfc_disc.h
@@ -73,6 +73,8 @@ struct lpfc_nodelist {
 	struct lpfc_hba      *nlp_phba;
 	struct lpfc_work_evt nodev_timeout_evt;
 	struct lpfc_work_evt els_retry_evt;
+	unsigned long last_ramp_up_time;        /* jiffy of last ramp up */
+	unsigned long last_q_full_time;		/* jiffy of last queue full */
 };
 
 /* Defines for nlp_flag (uint32) */
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index bcc29ec126dc..20f1a0713db2 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -720,6 +720,7 @@ lpfc_cmpl_els_plogi(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
 		/* Do not call DSM for lpfc_els_abort'ed ELS cmds */
 		if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
 		   ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
+		   (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
 		   (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) {
 			disc = (ndlp->nlp_flag & NLP_NPR_2B_DISC);
 		}
@@ -869,6 +870,7 @@ lpfc_cmpl_els_prli(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
 		/* Do not call DSM for lpfc_els_abort'ed ELS cmds */
 		if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
 		   ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
+		   (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
 		   (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) {
 			goto out;
 		}
@@ -1054,6 +1056,7 @@ lpfc_cmpl_els_adisc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
 		/* Do not call DSM for lpfc_els_abort'ed ELS cmds */
 		if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
 		   ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
+		   (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
 		   (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) {
 			disc = (ndlp->nlp_flag & NLP_NPR_2B_DISC);
 		}
@@ -1205,6 +1208,7 @@ lpfc_cmpl_els_logo(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
 		/* Do not call DSM for lpfc_els_abort'ed ELS cmds */
 		if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
 		   ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
+		   (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
 		   (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) {
 			goto out;
 		}
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index 259eeb161b82..a1f751e79405 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -1017,12 +1017,7 @@ lpfc_register_remote_port(struct lpfc_hba * phba,
 	rport_ids.port_name = wwn_to_u64(ndlp->nlp_portname.u.wwn);
 	rport_ids.port_id = ndlp->nlp_DID;
 	rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;
-	if (ndlp->nlp_type & NLP_FCP_TARGET)
-		rport_ids.roles |= FC_RPORT_ROLE_FCP_TARGET;
-	if (ndlp->nlp_type & NLP_FCP_INITIATOR)
-		rport_ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR;
 
-	scsi_block_requests(phba->host);
 	ndlp->rport = rport = fc_remote_port_add(phba->host, 0, &rport_ids);
 	if (!rport) {
 		dev_printk(KERN_WARNING, &phba->pcidev->dev,
@@ -1039,7 +1034,16 @@ lpfc_register_remote_port(struct lpfc_hba * phba,
 	}
 	rdata = rport->dd_data;
 	rdata->pnode = ndlp;
-	scsi_unblock_requests(phba->host);
+
+	if (ndlp->nlp_type & NLP_FCP_TARGET)
+		rport_ids.roles |= FC_RPORT_ROLE_FCP_TARGET;
+	if (ndlp->nlp_type & NLP_FCP_INITIATOR)
+		rport_ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR;
+
+
+	if (rport_ids.roles !=  FC_RPORT_ROLE_UNKNOWN)
+		fc_remote_port_rolechg(rport, rport_ids.roles);
+
 
 	return;
 }
@@ -1053,9 +1057,7 @@ lpfc_unregister_remote_port(struct lpfc_hba * phba,
 
 	ndlp->rport = NULL;
 	rdata->pnode = NULL;
-	scsi_block_requests(phba->host);
 	fc_remote_port_delete(rport);
-	scsi_unblock_requests(phba->host);
 
 	return;
 }
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h
index 86c41981188b..1ea565e0561f 100644
--- a/drivers/scsi/lpfc/lpfc_hw.h
+++ b/drivers/scsi/lpfc/lpfc_hw.h
@@ -266,9 +266,11 @@ struct lpfc_name {
 		struct {
 #ifdef __BIG_ENDIAN_BITFIELD
 			uint8_t nameType:4;	/* FC Word 0, bit 28:31 */
-			uint8_t IEEEextMsn:4;	/* FC Word 0, bit 24:27, bit 8:11 of IEEE ext */
+			uint8_t IEEEextMsn:4;	/* FC Word 0, bit 24:27, bit
+						   8:11 of IEEE ext */
 #else	/*  __LITTLE_ENDIAN_BITFIELD */
-			uint8_t IEEEextMsn:4;	/* FC Word 0, bit 24:27, bit 8:11 of IEEE ext */
+			uint8_t IEEEextMsn:4;	/* FC Word 0, bit 24:27, bit
+						   8:11 of IEEE ext */
 			uint8_t nameType:4;	/* FC Word 0, bit 28:31 */
 #endif
 
@@ -278,7 +280,8 @@ struct lpfc_name {
 #define NAME_IP_TYPE        0x4	/* IP address */
 #define NAME_CCITT_TYPE     0xC
 #define NAME_CCITT_GR_TYPE  0xE
-			uint8_t IEEEextLsb;	/* FC Word 0, bit 16:23, IEEE extended Lsb */
+			uint8_t IEEEextLsb;	/* FC Word 0, bit 16:23, IEEE
+						   extended Lsb */
 			uint8_t IEEE[6];	/* FC IEEE address */
 		} s;
 		uint8_t wwn[8];
@@ -1024,23 +1027,38 @@ typedef struct {
 /* Start FireFly Register definitions */
 #define PCI_VENDOR_ID_EMULEX        0x10df
 #define PCI_DEVICE_ID_FIREFLY       0x1ae5
-#define PCI_DEVICE_ID_SUPERFLY      0xf700
-#define PCI_DEVICE_ID_DRAGONFLY     0xf800
 #define PCI_DEVICE_ID_RFLY          0xf095
 #define PCI_DEVICE_ID_PFLY          0xf098
+#define PCI_DEVICE_ID_LP101         0xf0a1
 #define PCI_DEVICE_ID_TFLY          0xf0a5
+#define PCI_DEVICE_ID_BSMB          0xf0d1
+#define PCI_DEVICE_ID_BMID          0xf0d5
+#define PCI_DEVICE_ID_ZSMB          0xf0e1
+#define PCI_DEVICE_ID_ZMID          0xf0e5
+#define PCI_DEVICE_ID_NEPTUNE       0xf0f5
+#define PCI_DEVICE_ID_NEPTUNE_SCSP  0xf0f6
+#define PCI_DEVICE_ID_NEPTUNE_DCSP  0xf0f7
+#define PCI_DEVICE_ID_SUPERFLY      0xf700
+#define PCI_DEVICE_ID_DRAGONFLY     0xf800
 #define PCI_DEVICE_ID_CENTAUR       0xf900
 #define PCI_DEVICE_ID_PEGASUS       0xf980
 #define PCI_DEVICE_ID_THOR          0xfa00
 #define PCI_DEVICE_ID_VIPER         0xfb00
+#define PCI_DEVICE_ID_LP10000S      0xfc00
+#define PCI_DEVICE_ID_LP11000S      0xfc10
+#define PCI_DEVICE_ID_LPE11000S     0xfc20
 #define PCI_DEVICE_ID_HELIOS        0xfd00
-#define PCI_DEVICE_ID_BMID          0xf0d5
-#define PCI_DEVICE_ID_BSMB          0xf0d1
+#define PCI_DEVICE_ID_HELIOS_SCSP   0xfd11
+#define PCI_DEVICE_ID_HELIOS_DCSP   0xfd12
 #define PCI_DEVICE_ID_ZEPHYR        0xfe00
-#define PCI_DEVICE_ID_ZMID          0xf0e5
-#define PCI_DEVICE_ID_ZSMB          0xf0e1
-#define PCI_DEVICE_ID_LP101	    0xf0a1
-#define PCI_DEVICE_ID_LP10000S	    0xfc00
+#define PCI_DEVICE_ID_ZEPHYR_SCSP   0xfe11
+#define PCI_DEVICE_ID_ZEPHYR_DCSP   0xfe12
+
+#define PCI_SUBSYSTEM_ID_LP11000S      0xfc11
+#define PCI_SUBSYSTEM_ID_LP11002S      0xfc12
+#define PCI_SUBSYSTEM_ID_LPE11000S     0xfc21
+#define PCI_SUBSYSTEM_ID_LPE11002S     0xfc22
+#define PCI_SUBSYSTEM_ID_LPE11010S     0xfc2A
 
 #define JEDEC_ID_ADDRESS            0x0080001c
 #define FIREFLY_JEDEC_ID            0x1ACC
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 07498118359d..b7a603a45328 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -126,34 +126,26 @@ lpfc_config_port_prep(struct lpfc_hba * phba)
 		return -ERESTART;
 	}
 
-	/* The HBA's current state is provided by the ProgType and rr fields.
-	 * Read and check the value of these fields before continuing to config
-	 * this port.
+	/*
+	 * The value of rr must be 1 since the driver set the cv field to 1.
+	 * This setting requires the FW to set all revision fields.
 	 */
-	if (mb->un.varRdRev.rr == 0 || mb->un.varRdRev.un.b.ProgType != 2) {
-		/* Old firmware */
+	if (mb->un.varRdRev.rr == 0) {
 		vp->rev.rBit = 0;
-		lpfc_printf_log(phba,
-				KERN_ERR,
-				LOG_INIT,
-				"%d:0440 Adapter failed to init, mbxCmd x%x "
-				"READ_REV detected outdated firmware"
-				"Data: x%x\n",
-				phba->brd_no,
-				mb->mbxCommand, 0);
+		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+				"%d:0440 Adapter failed to init, READ_REV has "
+				"missing revision information.\n",
+				phba->brd_no);
 		mempool_free(pmb, phba->mbox_mem_pool);
 		return -ERESTART;
-	} else {
-		vp->rev.rBit = 1;
-		vp->rev.sli1FwRev = mb->un.varRdRev.sli1FwRev;
-		memcpy(vp->rev.sli1FwName,
-			(char*)mb->un.varRdRev.sli1FwName, 16);
-		vp->rev.sli2FwRev = mb->un.varRdRev.sli2FwRev;
-		memcpy(vp->rev.sli2FwName,
-					(char *)mb->un.varRdRev.sli2FwName, 16);
 	}
 
 	/* Save information as VPD data */
+	vp->rev.rBit = 1;
+	vp->rev.sli1FwRev = mb->un.varRdRev.sli1FwRev;
+	memcpy(vp->rev.sli1FwName, (char*) mb->un.varRdRev.sli1FwName, 16);
+	vp->rev.sli2FwRev = mb->un.varRdRev.sli2FwRev;
+	memcpy(vp->rev.sli2FwName, (char *) mb->un.varRdRev.sli2FwName, 16);
 	vp->rev.biuRev = mb->un.varRdRev.biuRev;
 	vp->rev.smRev = mb->un.varRdRev.smRev;
 	vp->rev.smFwRev = mb->un.varRdRev.un.smFwRev;
@@ -378,6 +370,10 @@ lpfc_config_port_post(struct lpfc_hba * phba)
 	if (psli->num_rings > 3)
 		status |= HC_R3INT_ENA;
 
+	if ((phba->cfg_poll & ENABLE_FCP_RING_POLLING) &&
+	    (phba->cfg_poll & DISABLE_FCP_RING_INT))
+		status &= ~(HC_R0INT_ENA << LPFC_FCP_RING);
+
 	writel(status, phba->HCregaddr);
 	readl(phba->HCregaddr); /* flush */
 	spin_unlock_irq(phba->host->host_lock);
@@ -571,6 +567,8 @@ lpfc_handle_latt(struct lpfc_hba * phba)
 
 	rc = -EIO;
 
+	/* Cleanup any outstanding ELS commands */
+	lpfc_els_flush_cmd(phba);
 
 	psli->slistat.link_event++;
 	lpfc_read_la(phba, pmb, mp);
@@ -765,96 +763,139 @@ static void
 lpfc_get_hba_model_desc(struct lpfc_hba * phba, uint8_t * mdp, uint8_t * descp)
 {
 	lpfc_vpd_t *vp;
-	uint32_t id;
-	uint8_t hdrtype;
-	char str[16];
+	uint16_t dev_id = phba->pcidev->device;
+	uint16_t dev_subid = phba->pcidev->subsystem_device;
+	uint8_t hdrtype = phba->pcidev->hdr_type;
+	char *model_str = "";
 
 	vp = &phba->vpd;
-	pci_read_config_dword(phba->pcidev, PCI_VENDOR_ID, &id);
-	pci_read_config_byte(phba->pcidev, PCI_HEADER_TYPE, &hdrtype);
 
-	switch ((id >> 16) & 0xffff) {
+	switch (dev_id) {
 	case PCI_DEVICE_ID_FIREFLY:
-		strcpy(str, "LP6000 1");
+		model_str = "LP6000 1Gb PCI";
 		break;
 	case PCI_DEVICE_ID_SUPERFLY:
 		if (vp->rev.biuRev >= 1 && vp->rev.biuRev <= 3)
-			strcpy(str, "LP7000 1");
+			model_str = "LP7000 1Gb PCI";
 		else
-			strcpy(str, "LP7000E 1");
+			model_str = "LP7000E 1Gb PCI";
 		break;
 	case PCI_DEVICE_ID_DRAGONFLY:
-		strcpy(str, "LP8000 1");
+		model_str = "LP8000 1Gb PCI";
 		break;
 	case PCI_DEVICE_ID_CENTAUR:
 		if (FC_JEDEC_ID(vp->rev.biuRev) == CENTAUR_2G_JEDEC_ID)
-			strcpy(str, "LP9002 2");
+			model_str = "LP9002 2Gb PCI";
 		else
-			strcpy(str, "LP9000 1");
+			model_str = "LP9000 1Gb PCI";
 		break;
 	case PCI_DEVICE_ID_RFLY:
-		strcpy(str, "LP952 2");
+		model_str = "LP952 2Gb PCI";
 		break;
 	case PCI_DEVICE_ID_PEGASUS:
-		strcpy(str, "LP9802 2");
+		model_str = "LP9802 2Gb PCI-X";
 		break;
 	case PCI_DEVICE_ID_THOR:
 		if (hdrtype == 0x80)
-			strcpy(str, "LP10000DC 2");
+			model_str = "LP10000DC 2Gb 2-port PCI-X";
 		else
-			strcpy(str, "LP10000 2");
+			model_str = "LP10000 2Gb PCI-X";
 		break;
 	case PCI_DEVICE_ID_VIPER:
-		strcpy(str, "LPX1000 10");
+		model_str = "LPX1000 10Gb PCI-X";
 		break;
 	case PCI_DEVICE_ID_PFLY:
-		strcpy(str, "LP982 2");
+		model_str = "LP982 2Gb PCI-X";
 		break;
 	case PCI_DEVICE_ID_TFLY:
 		if (hdrtype == 0x80)
-			strcpy(str, "LP1050DC 2");
+			model_str = "LP1050DC 2Gb 2-port PCI-X";
 		else
-			strcpy(str, "LP1050 2");
+			model_str = "LP1050 2Gb PCI-X";
 		break;
 	case PCI_DEVICE_ID_HELIOS:
 		if (hdrtype == 0x80)
-			strcpy(str, "LP11002 4");
+			model_str = "LP11002 4Gb 2-port PCI-X2";
+		else
+			model_str = "LP11000 4Gb PCI-X2";
+		break;
+	case PCI_DEVICE_ID_HELIOS_SCSP:
+		model_str = "LP11000-SP 4Gb PCI-X2";
+		break;
+	case PCI_DEVICE_ID_HELIOS_DCSP:
+		model_str = "LP11002-SP 4Gb 2-port PCI-X2";
+		break;
+	case PCI_DEVICE_ID_NEPTUNE:
+		if (hdrtype == 0x80)
+			model_str = "LPe1002 4Gb 2-port";
 		else
-			strcpy(str, "LP11000 4");
+			model_str = "LPe1000 4Gb PCIe";
+		break;
+	case PCI_DEVICE_ID_NEPTUNE_SCSP:
+		model_str = "LPe1000-SP 4Gb PCIe";
+		break;
+	case PCI_DEVICE_ID_NEPTUNE_DCSP:
+		model_str = "LPe1002-SP 4Gb 2-port PCIe";
 		break;
 	case PCI_DEVICE_ID_BMID:
-		strcpy(str, "LP1150 4");
+		model_str = "LP1150 4Gb PCI-X2";
 		break;
 	case PCI_DEVICE_ID_BSMB:
-		strcpy(str, "LP111 4");
+		model_str = "LP111 4Gb PCI-X2";
 		break;
 	case PCI_DEVICE_ID_ZEPHYR:
 		if (hdrtype == 0x80)
-			strcpy(str, "LPe11002 4");
+			model_str = "LPe11002 4Gb 2-port PCIe";
 		else
-			strcpy(str, "LPe11000 4");
+			model_str = "LPe11000 4Gb PCIe";
+		break;
+	case PCI_DEVICE_ID_ZEPHYR_SCSP:
+		model_str = "LPe11000-SP 4Gb PCIe";
+		break;
+	case PCI_DEVICE_ID_ZEPHYR_DCSP:
+		model_str = "LPe11002-SP 4Gb 2-port PCIe";
 		break;
 	case PCI_DEVICE_ID_ZMID:
-		strcpy(str, "LPe1150 4");
+		model_str = "LPe1150 4Gb PCIe";
 		break;
 	case PCI_DEVICE_ID_ZSMB:
-		strcpy(str, "LPe111 4");
+		model_str = "LPe111 4Gb PCIe";
 		break;
 	case PCI_DEVICE_ID_LP101:
-		strcpy(str, "LP101 2");
+		model_str = "LP101 2Gb PCI-X";
 		break;
 	case PCI_DEVICE_ID_LP10000S:
-		strcpy(str, "LP10000-S 2");
+		model_str = "LP10000-S 2Gb PCI";
+		break;
+	case PCI_DEVICE_ID_LP11000S:
+	case PCI_DEVICE_ID_LPE11000S:
+		switch (dev_subid) {
+		case PCI_SUBSYSTEM_ID_LP11000S:
+			model_str = "LP11002-S 4Gb PCI-X2";
+			break;
+		case PCI_SUBSYSTEM_ID_LP11002S:
+			model_str = "LP11000-S 4Gb 2-port PCI-X2";
+			break;
+		case PCI_SUBSYSTEM_ID_LPE11000S:
+			model_str = "LPe11002-S 4Gb PCIe";
+			break;
+		case PCI_SUBSYSTEM_ID_LPE11002S:
+			model_str = "LPe11002-S 4Gb 2-port PCIe";
+			break;
+		case PCI_SUBSYSTEM_ID_LPE11010S:
+			model_str = "LPe11010-S 4Gb 10-port PCIe";
+			break;
+		default:
+			break;
+		}
 		break;
 	default:
-		memset(str, 0, 16);
 		break;
 	}
 	if (mdp)
-		sscanf(str, "%s", mdp);
+		sscanf(model_str, "%s", mdp);
 	if (descp)
-		sprintf(descp, "Emulex LightPulse %s Gigabit PCI Fibre "
-			"Channel Adapter", str);
+		sprintf(descp, "Emulex %s Fibre Channel Adapter", model_str);
 }
 
 /**************************************************/
@@ -1196,6 +1237,7 @@ lpfc_stop_timer(struct lpfc_hba * phba)
 		}
 	}
 
+	del_timer_sync(&phba->fcp_poll_timer);
 	del_timer_sync(&phba->fc_estabtmo);
 	del_timer_sync(&phba->fc_disctmo);
 	del_timer_sync(&phba->fc_fdmitmo);
@@ -1351,7 +1393,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
 		goto out_put_host;
 
 	host->unique_id = phba->brd_no;
-
+	init_MUTEX(&phba->hba_can_block);
 	INIT_LIST_HEAD(&phba->ctrspbuflist);
 	INIT_LIST_HEAD(&phba->rnidrspbuflist);
 	INIT_LIST_HEAD(&phba->freebufList);
@@ -1375,6 +1417,10 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
 	psli->mbox_tmo.function = lpfc_mbox_timeout;
 	psli->mbox_tmo.data = (unsigned long)phba;
 
+	init_timer(&phba->fcp_poll_timer);
+	phba->fcp_poll_timer.function = lpfc_poll_timeout;
+	phba->fcp_poll_timer.data = (unsigned long)phba;
+
 	/*
 	 * Get all the module params for configuring this host and then
 	 * establish the host parameters.
@@ -1489,6 +1535,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
 	host->max_cmd_len = 16;
 
 	/* Initialize the list of scsi buffers used by driver for scsi IO. */
+	spin_lock_init(&phba->scsi_buf_list_lock);
 	INIT_LIST_HEAD(&phba->lpfc_scsi_buf_list);
 
 	host->transportt = lpfc_transport_template;
@@ -1520,6 +1567,12 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
 	if (error)
 		goto out_free_irq;
 
+	if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
+		spin_lock_irq(phba->host->host_lock);
+		lpfc_poll_start_timer(phba);
+		spin_unlock_irq(phba->host->host_lock);
+	}
+
 	/*
 	 * set fixed host attributes
 	 * Must done after lpfc_sli_hba_setup()
@@ -1679,14 +1732,28 @@ static struct pci_device_id lpfc_id_table[] = {
 		PCI_ANY_ID, PCI_ANY_ID, },
 	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_PFLY,
 		PCI_ANY_ID, PCI_ANY_ID, },
+	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_NEPTUNE,
+		PCI_ANY_ID, PCI_ANY_ID, },
+	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_NEPTUNE_SCSP,
+		PCI_ANY_ID, PCI_ANY_ID, },
+	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_NEPTUNE_DCSP,
+		PCI_ANY_ID, PCI_ANY_ID, },
 	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_HELIOS,
 		PCI_ANY_ID, PCI_ANY_ID, },
+	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_HELIOS_SCSP,
+		PCI_ANY_ID, PCI_ANY_ID, },
+	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_HELIOS_DCSP,
+		PCI_ANY_ID, PCI_ANY_ID, },
 	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_BMID,
 		PCI_ANY_ID, PCI_ANY_ID, },
 	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_BSMB,
 		PCI_ANY_ID, PCI_ANY_ID, },
 	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_ZEPHYR,
 		PCI_ANY_ID, PCI_ANY_ID, },
+	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_ZEPHYR_SCSP,
+		PCI_ANY_ID, PCI_ANY_ID, },
+	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_ZEPHYR_DCSP,
+		PCI_ANY_ID, PCI_ANY_ID, },
 	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_ZMID,
 		PCI_ANY_ID, PCI_ANY_ID, },
 	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_ZSMB,
@@ -1697,6 +1764,10 @@ static struct pci_device_id lpfc_id_table[] = {
 		PCI_ANY_ID, PCI_ANY_ID, },
 	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LP10000S,
 		PCI_ANY_ID, PCI_ANY_ID, },
+	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LP11000S,
+		PCI_ANY_ID, PCI_ANY_ID, },
+	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LPE11000S,
+		PCI_ANY_ID, PCI_ANY_ID, },
 	{ 0 }
 };
 
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
index 507a6af56f42..fbead786031f 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -55,55 +55,76 @@ lpfc_check_adisc(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
 	return (1);
 }
 
-
 int
 lpfc_check_sparm(struct lpfc_hba * phba,
 		 struct lpfc_nodelist * ndlp, struct serv_parm * sp,
 		 uint32_t class)
 {
 	volatile struct serv_parm *hsp = &phba->fc_sparam;
-	/* First check for supported version */
-
-	/* Next check for class validity */
+	uint16_t hsp_value, ssp_value = 0;
+
+	/*
+	 * The receive data field size and buffer-to-buffer receive data field
+	 * size entries are 16 bits but are represented as two 8-bit fields in
+	 * the driver data structure to account for rsvd bits and other control
+	 * bits.  Reconstruct and compare the fields as a 16-bit values before
+	 * correcting the byte values.
+	 */
 	if (sp->cls1.classValid) {
-
-		if (sp->cls1.rcvDataSizeMsb > hsp->cls1.rcvDataSizeMsb)
-			sp->cls1.rcvDataSizeMsb = hsp->cls1.rcvDataSizeMsb;
-		if (sp->cls1.rcvDataSizeLsb > hsp->cls1.rcvDataSizeLsb)
+		hsp_value = (hsp->cls1.rcvDataSizeMsb << 8) |
+				hsp->cls1.rcvDataSizeLsb;
+		ssp_value = (sp->cls1.rcvDataSizeMsb << 8) |
+				sp->cls1.rcvDataSizeLsb;
+		if (ssp_value > hsp_value) {
 			sp->cls1.rcvDataSizeLsb = hsp->cls1.rcvDataSizeLsb;
+			sp->cls1.rcvDataSizeMsb = hsp->cls1.rcvDataSizeMsb;
+		}
 	} else if (class == CLASS1) {
-		return (0);
+		return 0;
 	}
 
 	if (sp->cls2.classValid) {
-
-		if (sp->cls2.rcvDataSizeMsb > hsp->cls2.rcvDataSizeMsb)
-			sp->cls2.rcvDataSizeMsb = hsp->cls2.rcvDataSizeMsb;
-		if (sp->cls2.rcvDataSizeLsb > hsp->cls2.rcvDataSizeLsb)
+		hsp_value = (hsp->cls2.rcvDataSizeMsb << 8) |
+				hsp->cls2.rcvDataSizeLsb;
+		ssp_value = (sp->cls2.rcvDataSizeMsb << 8) |
+				sp->cls2.rcvDataSizeLsb;
+		if (ssp_value > hsp_value) {
 			sp->cls2.rcvDataSizeLsb = hsp->cls2.rcvDataSizeLsb;
+			sp->cls2.rcvDataSizeMsb = hsp->cls2.rcvDataSizeMsb;
+		}
 	} else if (class == CLASS2) {
-		return (0);
+		return 0;
 	}
 
 	if (sp->cls3.classValid) {
-
-		if (sp->cls3.rcvDataSizeMsb > hsp->cls3.rcvDataSizeMsb)
-			sp->cls3.rcvDataSizeMsb = hsp->cls3.rcvDataSizeMsb;
-		if (sp->cls3.rcvDataSizeLsb > hsp->cls3.rcvDataSizeLsb)
+		hsp_value = (hsp->cls3.rcvDataSizeMsb << 8) |
+				hsp->cls3.rcvDataSizeLsb;
+		ssp_value = (sp->cls3.rcvDataSizeMsb << 8) |
+				sp->cls3.rcvDataSizeLsb;
+		if (ssp_value > hsp_value) {
 			sp->cls3.rcvDataSizeLsb = hsp->cls3.rcvDataSizeLsb;
+			sp->cls3.rcvDataSizeMsb = hsp->cls3.rcvDataSizeMsb;
+		}
 	} else if (class == CLASS3) {
-		return (0);
+		return 0;
 	}
 
-	if (sp->cmn.bbRcvSizeMsb > hsp->cmn.bbRcvSizeMsb)
-		sp->cmn.bbRcvSizeMsb = hsp->cmn.bbRcvSizeMsb;
-	if (sp->cmn.bbRcvSizeLsb > hsp->cmn.bbRcvSizeLsb)
+	/*
+	 * Preserve the upper four bits of the MSB from the PLOGI response.
+	 * These bits contain the Buffer-to-Buffer State Change Number
+	 * from the target and need to be passed to the FW.
+	 */
+	hsp_value = (hsp->cmn.bbRcvSizeMsb << 8) | hsp->cmn.bbRcvSizeLsb;
+	ssp_value = (sp->cmn.bbRcvSizeMsb << 8) | sp->cmn.bbRcvSizeLsb;
+	if (ssp_value > hsp_value) {
 		sp->cmn.bbRcvSizeLsb = hsp->cmn.bbRcvSizeLsb;
+		sp->cmn.bbRcvSizeMsb = (sp->cmn.bbRcvSizeMsb & 0xF0) |
+				       (hsp->cmn.bbRcvSizeMsb & 0x0F);
+	}
 
-	/* If check is good, copy wwpn wwnn into ndlp */
 	memcpy(&ndlp->nlp_nodename, &sp->nodeName, sizeof (struct lpfc_name));
 	memcpy(&ndlp->nlp_portname, &sp->portName, sizeof (struct lpfc_name));
-	return (1);
+	return 1;
 }
 
 static void *
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index c63275e66e2e..9ee8218404c0 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -41,6 +41,20 @@
 #define LPFC_ABORT_WAIT  2
 
 
+static inline void
+lpfc_block_requests(struct lpfc_hba * phba)
+{
+	down(&phba->hba_can_block);
+	scsi_block_requests(phba->host);
+}
+
+static inline void
+lpfc_unblock_requests(struct lpfc_hba * phba)
+{
+	scsi_unblock_requests(phba->host);
+	up(&phba->hba_can_block);
+}
+
 /*
  * This routine allocates a scsi buffer, which contains all the necessary
  * information needed to initiate a SCSI I/O.  The non-DMAable buffer region
@@ -137,18 +151,22 @@ lpfc_new_scsi_buf(struct lpfc_hba * phba)
 }
 
 struct  lpfc_scsi_buf*
-lpfc_sli_get_scsi_buf(struct lpfc_hba * phba)
+lpfc_get_scsi_buf(struct lpfc_hba * phba)
 {
 	struct  lpfc_scsi_buf * lpfc_cmd = NULL;
 	struct list_head *scsi_buf_list = &phba->lpfc_scsi_buf_list;
+	unsigned long iflag = 0;
 
+	spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag);
 	list_remove_head(scsi_buf_list, lpfc_cmd, struct lpfc_scsi_buf, list);
+	spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag);
 	return  lpfc_cmd;
 }
 
 static void
 lpfc_release_scsi_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * psb)
 {
+	unsigned long iflag = 0;
 	/*
 	 * There are only two special cases to consider.  (1) the scsi command
 	 * requested scatter-gather usage or (2) the scsi command allocated
@@ -166,8 +184,10 @@ lpfc_release_scsi_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * psb)
 		 }
 	}
 
+	spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag);
 	psb->pCmd = NULL;
 	list_add_tail(&psb->list, &phba->lpfc_scsi_buf_list);
+	spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag);
 }
 
 static int
@@ -389,7 +409,9 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
 	struct lpfc_rport_data *rdata = lpfc_cmd->rdata;
 	struct lpfc_nodelist *pnode = rdata->pnode;
 	struct scsi_cmnd *cmd = lpfc_cmd->pCmd;
-	unsigned long iflag;
+	int result;
+	struct scsi_device *sdev, *tmp_sdev;
+	int depth = 0;
 
 	lpfc_cmd->result = pIocbOut->iocb.un.ulpWord[4];
 	lpfc_cmd->status = pIocbOut->iocb.ulpStatus;
@@ -441,11 +463,64 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
 				*lp, *(lp + 3), cmd->retries, cmd->resid);
 	}
 
+	result = cmd->result;
+	sdev = cmd->device;
 	cmd->scsi_done(cmd);
 
-	spin_lock_irqsave(phba->host->host_lock, iflag);
+	if (!result &&
+	   ((jiffies - pnode->last_ramp_up_time) >
+		LPFC_Q_RAMP_UP_INTERVAL * HZ) &&
+	   ((jiffies - pnode->last_q_full_time) >
+		LPFC_Q_RAMP_UP_INTERVAL * HZ) &&
+	   (phba->cfg_lun_queue_depth > sdev->queue_depth)) {
+		shost_for_each_device(tmp_sdev, sdev->host) {
+			if (phba->cfg_lun_queue_depth > tmp_sdev->queue_depth) {
+				if (tmp_sdev->id != sdev->id)
+					continue;
+				if (tmp_sdev->ordered_tags)
+					scsi_adjust_queue_depth(tmp_sdev,
+						MSG_ORDERED_TAG,
+						tmp_sdev->queue_depth+1);
+				else
+					scsi_adjust_queue_depth(tmp_sdev,
+						MSG_SIMPLE_TAG,
+						tmp_sdev->queue_depth+1);
+
+				pnode->last_ramp_up_time = jiffies;
+			}
+		}
+	}
+
+	/*
+	 * Check for queue full.  If the lun is reporting queue full, then
+	 * back off the lun queue depth to prevent target overloads.
+	 */
+	if (result == SAM_STAT_TASK_SET_FULL) {
+		pnode->last_q_full_time = jiffies;
+
+		shost_for_each_device(tmp_sdev, sdev->host) {
+			if (tmp_sdev->id != sdev->id)
+				continue;
+			depth = scsi_track_queue_full(tmp_sdev,
+					tmp_sdev->queue_depth - 1);
+		}
+		/*
+ 		 * The queue depth cannot be lowered any more.
+		 * Modify the returned error code to store
+		 * the final depth value set by
+		 * scsi_track_queue_full.
+		 */
+		if (depth == -1)
+			depth = sdev->host->cmd_per_lun;
+
+		if (depth) {
+			lpfc_printf_log(phba, KERN_WARNING, LOG_FCP,
+				"%d:0711 detected queue full - lun queue depth "
+				" adjusted to %d.\n", phba->brd_no, depth);
+		}
+	}
+
 	lpfc_release_scsi_buf(phba, lpfc_cmd);
-	spin_unlock_irqrestore(phba->host->host_lock, iflag);
 }
 
 static void
@@ -693,6 +768,37 @@ lpfc_info(struct Scsi_Host *host)
 	return lpfcinfobuf;
 }
 
+static __inline__ void lpfc_poll_rearm_timer(struct lpfc_hba * phba)
+{
+	unsigned long  poll_tmo_expires =
+		(jiffies + msecs_to_jiffies(phba->cfg_poll_tmo));
+
+	if (phba->sli.ring[LPFC_FCP_RING].txcmplq_cnt)
+		mod_timer(&phba->fcp_poll_timer,
+			  poll_tmo_expires);
+}
+
+void lpfc_poll_start_timer(struct lpfc_hba * phba)
+{
+	lpfc_poll_rearm_timer(phba);
+}
+
+void lpfc_poll_timeout(unsigned long ptr)
+{
+	struct lpfc_hba *phba = (struct lpfc_hba *)ptr;
+	unsigned long iflag;
+
+	spin_lock_irqsave(phba->host->host_lock, iflag);
+
+	if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
+		lpfc_sli_poll_fcp_ring (phba);
+		if (phba->cfg_poll & DISABLE_FCP_RING_INT)
+			lpfc_poll_rearm_timer(phba);
+	}
+
+	spin_unlock_irqrestore(phba->host->host_lock, iflag);
+}
+
 static int
 lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
 {
@@ -719,10 +825,11 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
 		cmnd->result = ScsiResult(DID_BUS_BUSY, 0);
 		goto out_fail_command;
 	}
-	lpfc_cmd = lpfc_sli_get_scsi_buf (phba);
+	lpfc_cmd = lpfc_get_scsi_buf (phba);
 	if (lpfc_cmd == NULL) {
-		printk(KERN_WARNING "%s: No buffer available - list empty, "
-		       "total count %d\n", __FUNCTION__, phba->total_scsi_bufs);
+		lpfc_printf_log(phba, KERN_INFO, LOG_FCP,
+				"%d:0707 driver's buffer pool is empty, "
+				"IO busied\n", phba->brd_no);
 		goto out_host_busy;
 	}
 
@@ -746,11 +853,17 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
 				&lpfc_cmd->cur_iocbq, SLI_IOCB_RET_IOCB);
 	if (err)
 		goto out_host_busy_free_buf;
+
+	if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
+		lpfc_sli_poll_fcp_ring(phba);
+		if (phba->cfg_poll & DISABLE_FCP_RING_INT)
+			lpfc_poll_rearm_timer(phba);
+	}
+
 	return 0;
 
  out_host_busy_free_buf:
 	lpfc_release_scsi_buf(phba, lpfc_cmd);
-	cmnd->host_scribble = NULL;
  out_host_busy:
 	return SCSI_MLQUEUE_HOST_BUSY;
 
@@ -759,11 +872,12 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
 	return 0;
 }
 
+
 static int
-__lpfc_abort_handler(struct scsi_cmnd *cmnd)
+lpfc_abort_handler(struct scsi_cmnd *cmnd)
 {
-	struct lpfc_hba *phba =
-			(struct lpfc_hba *)cmnd->device->host->hostdata[0];
+	struct Scsi_Host *shost = cmnd->device->host;
+	struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata[0];
 	struct lpfc_sli_ring *pring = &phba->sli.ring[phba->sli.fcp_ring];
 	struct lpfc_iocbq *iocb;
 	struct lpfc_iocbq *abtsiocb;
@@ -772,6 +886,8 @@ __lpfc_abort_handler(struct scsi_cmnd *cmnd)
 	unsigned int loop_count = 0;
 	int ret = SUCCESS;
 
+	lpfc_block_requests(phba);
+	spin_lock_irq(shost->host_lock);
 
 	lpfc_cmd = (struct lpfc_scsi_buf *)cmnd->host_scribble;
 	BUG_ON(!lpfc_cmd);
@@ -821,9 +937,15 @@ __lpfc_abort_handler(struct scsi_cmnd *cmnd)
 		goto out;
 	}
 
+	if (phba->cfg_poll & DISABLE_FCP_RING_INT)
+		lpfc_sli_poll_fcp_ring (phba);
+
 	/* Wait for abort to complete */
 	while (lpfc_cmd->pCmd == cmnd)
 	{
+		if (phba->cfg_poll & DISABLE_FCP_RING_INT)
+			lpfc_sli_poll_fcp_ring (phba);
+
 		spin_unlock_irq(phba->host->host_lock);
 			schedule_timeout_uninterruptible(LPFC_ABORT_WAIT*HZ);
 		spin_lock_irq(phba->host->host_lock);
@@ -844,26 +966,19 @@ __lpfc_abort_handler(struct scsi_cmnd *cmnd)
 
  out:
 	lpfc_printf_log(phba, KERN_WARNING, LOG_FCP,
-			"%d:0749 SCSI layer issued abort device: ret %#x, "
-			"ID %d, LUN %d, snum %#lx\n",
+			"%d:0749 SCSI Layer I/O Abort Request "
+			"Status x%x ID %d LUN %d snum %#lx\n",
 			phba->brd_no, ret, cmnd->device->id,
 			cmnd->device->lun, cmnd->serial_number);
 
-	return ret;
-}
+	spin_unlock_irq(shost->host_lock);
+	lpfc_unblock_requests(phba);
 
-static int
-lpfc_abort_handler(struct scsi_cmnd *cmnd)
-{
-	int rc;
-	spin_lock_irq(cmnd->device->host->host_lock);
-	rc = __lpfc_abort_handler(cmnd);
-	spin_unlock_irq(cmnd->device->host->host_lock);
-	return rc;
+	return ret;
 }
 
 static int
-__lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
+lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
 {
 	struct Scsi_Host *shost = cmnd->device->host;
 	struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata[0];
@@ -871,9 +986,12 @@ __lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
 	struct lpfc_iocbq *iocbq, *iocbqrsp;
 	struct lpfc_rport_data *rdata = cmnd->device->hostdata;
 	struct lpfc_nodelist *pnode = rdata->pnode;
+	uint32_t cmd_result = 0, cmd_status = 0;
 	int ret = FAILED;
 	int cnt, loopcnt;
 
+	lpfc_block_requests(phba);
+	spin_lock_irq(shost->host_lock);
 	/*
 	 * If target is not in a MAPPED state, delay the reset until
 	 * target is rediscovered or nodev timeout expires.
@@ -891,7 +1009,7 @@ __lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
 			break;
 	}
 
-	lpfc_cmd = lpfc_sli_get_scsi_buf (phba);
+	lpfc_cmd = lpfc_get_scsi_buf (phba);
 	if (lpfc_cmd == NULL)
 		goto out;
 
@@ -916,26 +1034,28 @@ __lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
 	if (ret == IOCB_SUCCESS)
 		ret = SUCCESS;
 
-	lpfc_cmd->result = iocbqrsp->iocb.un.ulpWord[4];
-	lpfc_cmd->status = iocbqrsp->iocb.ulpStatus;
-	if (lpfc_cmd->status == IOSTAT_LOCAL_REJECT)
-		if (lpfc_cmd->result & IOERR_DRVR_MASK)
-			lpfc_cmd->status = IOSTAT_DRIVER_REJECT;
+
+	cmd_result = iocbqrsp->iocb.un.ulpWord[4];
+	cmd_status = iocbqrsp->iocb.ulpStatus;
+
+	lpfc_sli_release_iocbq(phba, iocbqrsp);
+	lpfc_release_scsi_buf(phba, lpfc_cmd);
 
 	/*
-	 * All outstanding txcmplq I/Os should have been aborted by the target.
+	 * All outstanding txcmplq I/Os should have been aborted by the device.
 	 * Unfortunately, some targets do not abide by this forcing the driver
 	 * to double check.
 	 */
-	lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring],
-			    cmnd->device->id, cmnd->device->lun, 0,
-			    LPFC_CTX_LUN);
-
+	cnt = lpfc_sli_sum_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring],
+				cmnd->device->id, cmnd->device->lun,
+				LPFC_CTX_LUN);
+	if (cnt)
+		lpfc_sli_abort_iocb(phba,
+				    &phba->sli.ring[phba->sli.fcp_ring],
+				    cmnd->device->id, cmnd->device->lun,
+				    0, LPFC_CTX_LUN);
 	loopcnt = 0;
-	while((cnt = lpfc_sli_sum_iocb(phba,
-				       &phba->sli.ring[phba->sli.fcp_ring],
-				       cmnd->device->id, cmnd->device->lun,
-				       LPFC_CTX_LUN))) {
+	while(cnt) {
 		spin_unlock_irq(phba->host->host_lock);
 		schedule_timeout_uninterruptible(LPFC_RESET_WAIT*HZ);
 		spin_lock_irq(phba->host->host_lock);
@@ -943,6 +1063,11 @@ __lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
 		if (++loopcnt
 		    > (2 * phba->cfg_nodev_tmo)/LPFC_RESET_WAIT)
 			break;
+
+		cnt = lpfc_sli_sum_iocb(phba,
+					&phba->sli.ring[phba->sli.fcp_ring],
+					cmnd->device->id, cmnd->device->lun,
+					LPFC_CTX_LUN);
 	}
 
 	if (cnt) {
@@ -952,35 +1077,21 @@ __lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
 		ret = FAILED;
 	}
 
-	lpfc_sli_release_iocbq(phba, iocbqrsp);
-
 out_free_scsi_buf:
 	lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
 			"%d:0713 SCSI layer issued LUN reset (%d, %d) "
 			"Data: x%x x%x x%x\n",
-			phba->brd_no, lpfc_cmd->pCmd->device->id,
-			lpfc_cmd->pCmd->device->lun, ret, lpfc_cmd->status,
-			lpfc_cmd->result);
-	lpfc_release_scsi_buf(phba, lpfc_cmd);
+			phba->brd_no, cmnd->device->id,cmnd->device->lun,
+			ret, cmd_status, cmd_result);
+
 out:
+	spin_unlock_irq(shost->host_lock);
+	lpfc_unblock_requests(phba);
 	return ret;
 }
 
 static int
-lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
-{
-	int rc;
-	spin_lock_irq(cmnd->device->host->host_lock);
-	rc = __lpfc_reset_lun_handler(cmnd);
-	spin_unlock_irq(cmnd->device->host->host_lock);
-	return rc;
-}
-
-/*
- * Note: midlayer calls this function with the host_lock held
- */
-static int
-__lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
+lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
 {
 	struct Scsi_Host *shost = cmnd->device->host;
 	struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata[0];
@@ -991,7 +1102,10 @@ __lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
 	unsigned int midlayer_id = 0;
 	struct lpfc_scsi_buf * lpfc_cmd;
 
-	lpfc_cmd = lpfc_sli_get_scsi_buf (phba);
+	lpfc_block_requests(phba);
+	spin_lock_irq(shost->host_lock);
+
+	lpfc_cmd = lpfc_get_scsi_buf(phba);
 	if (lpfc_cmd == NULL)
 		goto out;
 
@@ -1022,18 +1136,31 @@ __lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
 		lpfc_cmd->pCmd->device->hostdata = ndlp->rport->dd_data;
 		ret = lpfc_scsi_tgt_reset(lpfc_cmd, phba);
 		if (ret != SUCCESS) {
-			lpfc_printf_log(phba, KERN_INFO, LOG_FCP,
+			lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
 				"%d:0713 Bus Reset on target %d failed\n",
 				phba->brd_no, i);
 			err_count++;
 		}
 	}
 
+	if (err_count == 0)
+		ret = SUCCESS;
+
+	lpfc_release_scsi_buf(phba, lpfc_cmd);
+
+	/*
+	 * All outstanding txcmplq I/Os should have been aborted by
+	 * the targets.  Unfortunately, some targets do not abide by
+	 * this forcing the driver to double check.
+	 */
 	cmnd->device->id = midlayer_id;
+	cnt = lpfc_sli_sum_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring],
+				0, 0, LPFC_CTX_HOST);
+	if (cnt)
+		lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring],
+				    0, 0, 0, LPFC_CTX_HOST);
 	loopcnt = 0;
-	while((cnt = lpfc_sli_sum_iocb(phba,
-				&phba->sli.ring[phba->sli.fcp_ring],
-				0, 0, LPFC_CTX_HOST))) {
+	while(cnt) {
 		spin_unlock_irq(phba->host->host_lock);
 		schedule_timeout_uninterruptible(LPFC_RESET_WAIT*HZ);
 		spin_lock_irq(phba->host->host_lock);
@@ -1041,45 +1168,31 @@ __lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
 		if (++loopcnt
 		    > (2 * phba->cfg_nodev_tmo)/LPFC_RESET_WAIT)
 			break;
+
+		cnt = lpfc_sli_sum_iocb(phba,
+					&phba->sli.ring[phba->sli.fcp_ring],
+					0, 0, LPFC_CTX_HOST);
 	}
 
 	if (cnt) {
-		/* flush all outstanding commands on the host */
-		i = lpfc_sli_abort_iocb(phba,
-				&phba->sli.ring[phba->sli.fcp_ring], 0, 0, 0,
-				LPFC_CTX_HOST);
-
-		lpfc_printf_log(phba, KERN_INFO, LOG_FCP,
+		lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
 		   "%d:0715 Bus Reset I/O flush failure: cnt x%x left x%x\n",
 		   phba->brd_no, cnt, i);
-	}
-
-	if (cnt == 0)
-		ret = SUCCESS;
-	else
 		ret = FAILED;
+	}
 
-	lpfc_release_scsi_buf(phba, lpfc_cmd);
 	lpfc_printf_log(phba,
 			KERN_ERR,
 			LOG_FCP,
 			"%d:0714 SCSI layer issued Bus Reset Data: x%x\n",
 			phba->brd_no, ret);
 out:
+	spin_unlock_irq(shost->host_lock);
+	lpfc_unblock_requests(phba);
 	return ret;
 }
 
 static int
-lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
-{
-	int rc;
-	spin_lock_irq(cmnd->device->host->host_lock);
-	rc = __lpfc_reset_bus_handler(cmnd);
-	spin_unlock_irq(cmnd->device->host->host_lock);
-	return rc;
-}
-
-static int
 lpfc_slave_alloc(struct scsi_device *sdev)
 {
 	struct lpfc_hba *phba = (struct lpfc_hba *)sdev->host->hostdata[0];
@@ -1127,10 +1240,10 @@ lpfc_slave_alloc(struct scsi_device *sdev)
 			break;
 		}
 
-		spin_lock_irqsave(phba->host->host_lock, flags);
+		spin_lock_irqsave(&phba->scsi_buf_list_lock, flags);
 		phba->total_scsi_bufs++;
 		list_add_tail(&scsi_buf->list, &phba->lpfc_scsi_buf_list);
-		spin_unlock_irqrestore(phba->host->host_lock, flags);
+		spin_unlock_irqrestore(&phba->scsi_buf_list_lock, flags);
 	}
 	return 0;
 }
@@ -1154,6 +1267,12 @@ lpfc_slave_configure(struct scsi_device *sdev)
 	 */
 	rport->dev_loss_tmo = phba->cfg_nodev_tmo + 5;
 
+	if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
+		lpfc_sli_poll_fcp_ring(phba);
+		if (phba->cfg_poll & DISABLE_FCP_RING_INT)
+			lpfc_poll_rearm_timer(phba);
+	}
+
 	return 0;
 }
 
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index e2c08c5d83fb..7b785ade8b07 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -886,6 +886,182 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba * phba, struct lpfc_sli_ring * pring,
 	return rc;
 }
 
+static void lpfc_sli_rsp_pointers_error(struct lpfc_hba * phba,
+					struct lpfc_sli_ring * pring)
+{
+	struct lpfc_pgp *pgp = &phba->slim2p->mbx.us.s2.port[pring->ringno];
+	/*
+	 * Ring <ringno> handler: portRspPut <portRspPut> is bigger then
+	 * rsp ring <portRspMax>
+	 */
+	lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+			"%d:0312 Ring %d handler: portRspPut %d "
+			"is bigger then rsp ring %d\n",
+			phba->brd_no, pring->ringno,
+			le32_to_cpu(pgp->rspPutInx),
+			pring->numRiocb);
+
+	phba->hba_state = LPFC_HBA_ERROR;
+
+	/*
+	 * All error attention handlers are posted to
+	 * worker thread
+	 */
+	phba->work_ha |= HA_ERATT;
+	phba->work_hs = HS_FFER3;
+	if (phba->work_wait)
+		wake_up(phba->work_wait);
+
+	return;
+}
+
+void lpfc_sli_poll_fcp_ring(struct lpfc_hba * phba)
+{
+	struct lpfc_sli      * psli   = &phba->sli;
+	struct lpfc_sli_ring * pring = &psli->ring[LPFC_FCP_RING];
+	IOCB_t *irsp = NULL;
+	IOCB_t *entry = NULL;
+	struct lpfc_iocbq *cmdiocbq = NULL;
+	struct lpfc_iocbq rspiocbq;
+	struct lpfc_pgp *pgp;
+	uint32_t status;
+	uint32_t portRspPut, portRspMax;
+	int type;
+	uint32_t rsp_cmpl = 0;
+	void __iomem *to_slim;
+	uint32_t ha_copy;
+
+	pring->stats.iocb_event++;
+
+	/* The driver assumes SLI-2 mode */
+	pgp =  &phba->slim2p->mbx.us.s2.port[pring->ringno];
+
+	/*
+	 * The next available response entry should never exceed the maximum
+	 * entries.  If it does, treat it as an adapter hardware error.
+	 */
+	portRspMax = pring->numRiocb;
+	portRspPut = le32_to_cpu(pgp->rspPutInx);
+	if (unlikely(portRspPut >= portRspMax)) {
+		lpfc_sli_rsp_pointers_error(phba, pring);
+		return;
+	}
+
+	rmb();
+	while (pring->rspidx != portRspPut) {
+
+		entry = IOCB_ENTRY(pring->rspringaddr, pring->rspidx);
+
+		if (++pring->rspidx >= portRspMax)
+			pring->rspidx = 0;
+
+		lpfc_sli_pcimem_bcopy((uint32_t *) entry,
+				      (uint32_t *) &rspiocbq.iocb,
+				      sizeof (IOCB_t));
+		irsp = &rspiocbq.iocb;
+		type = lpfc_sli_iocb_cmd_type(irsp->ulpCommand & CMD_IOCB_MASK);
+		pring->stats.iocb_rsp++;
+		rsp_cmpl++;
+
+		if (unlikely(irsp->ulpStatus)) {
+			/* Rsp ring <ringno> error: IOCB */
+			lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
+					"%d:0326 Rsp Ring %d error: IOCB Data: "
+					"x%x x%x x%x x%x x%x x%x x%x x%x\n",
+					phba->brd_no, pring->ringno,
+					irsp->un.ulpWord[0],
+					irsp->un.ulpWord[1],
+					irsp->un.ulpWord[2],
+					irsp->un.ulpWord[3],
+					irsp->un.ulpWord[4],
+					irsp->un.ulpWord[5],
+					*(((uint32_t *) irsp) + 6),
+					*(((uint32_t *) irsp) + 7));
+		}
+
+		switch (type) {
+		case LPFC_ABORT_IOCB:
+		case LPFC_SOL_IOCB:
+			/*
+			 * Idle exchange closed via ABTS from port.  No iocb
+			 * resources need to be recovered.
+			 */
+			if (unlikely(irsp->ulpCommand == CMD_XRI_ABORTED_CX)) {
+				printk(KERN_INFO "%s: IOCB cmd 0x%x processed."
+				       " Skipping completion\n", __FUNCTION__,
+				       irsp->ulpCommand);
+				break;
+			}
+
+			cmdiocbq = lpfc_sli_iocbq_lookup(phba, pring,
+							 &rspiocbq);
+			if ((cmdiocbq) && (cmdiocbq->iocb_cmpl)) {
+				(cmdiocbq->iocb_cmpl)(phba, cmdiocbq,
+						      &rspiocbq);
+			}
+			break;
+		default:
+			if (irsp->ulpCommand == CMD_ADAPTER_MSG) {
+				char adaptermsg[LPFC_MAX_ADPTMSG];
+				memset(adaptermsg, 0, LPFC_MAX_ADPTMSG);
+				memcpy(&adaptermsg[0], (uint8_t *) irsp,
+				       MAX_MSG_DATA);
+				dev_warn(&((phba->pcidev)->dev), "lpfc%d: %s",
+					 phba->brd_no, adaptermsg);
+			} else {
+				/* Unknown IOCB command */
+				lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+						"%d:0321 Unknown IOCB command "
+						"Data: x%x, x%x x%x x%x x%x\n",
+						phba->brd_no, type,
+						irsp->ulpCommand,
+						irsp->ulpStatus,
+						irsp->ulpIoTag,
+						irsp->ulpContext);
+			}
+			break;
+		}
+
+		/*
+		 * The response IOCB has been processed.  Update the ring
+		 * pointer in SLIM.  If the port response put pointer has not
+		 * been updated, sync the pgp->rspPutInx and fetch the new port
+		 * response put pointer.
+		 */
+		to_slim = phba->MBslimaddr +
+			(SLIMOFF + (pring->ringno * 2) + 1) * 4;
+		writeb(pring->rspidx, to_slim);
+
+		if (pring->rspidx == portRspPut)
+			portRspPut = le32_to_cpu(pgp->rspPutInx);
+	}
+
+	ha_copy = readl(phba->HAregaddr);
+	ha_copy >>= (LPFC_FCP_RING * 4);
+
+	if ((rsp_cmpl > 0) && (ha_copy & HA_R0RE_REQ)) {
+		pring->stats.iocb_rsp_full++;
+		status = ((CA_R0ATT | CA_R0RE_RSP) << (LPFC_FCP_RING * 4));
+		writel(status, phba->CAregaddr);
+		readl(phba->CAregaddr);
+	}
+	if ((ha_copy & HA_R0CE_RSP) &&
+	    (pring->flag & LPFC_CALL_RING_AVAILABLE)) {
+		pring->flag &= ~LPFC_CALL_RING_AVAILABLE;
+		pring->stats.iocb_cmd_empty++;
+
+		/* Force update of the local copy of cmdGetInx */
+		pring->local_getidx = le32_to_cpu(pgp->cmdGetInx);
+		lpfc_sli_resume_iocb(phba, pring);
+
+		if ((pring->lpfc_sli_cmd_available))
+			(pring->lpfc_sli_cmd_available) (phba, pring);
+
+	}
+
+	return;
+}
+
 /*
  * This routine presumes LPFC_FCP_RING handling and doesn't bother
  * to check it explicitly.
@@ -917,24 +1093,7 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba * phba,
 	portRspMax = pring->numRiocb;
 	portRspPut = le32_to_cpu(pgp->rspPutInx);
 	if (unlikely(portRspPut >= portRspMax)) {
-		/*
-		 * Ring <ringno> handler: portRspPut <portRspPut> is bigger then
-		 * rsp ring <portRspMax>
-		 */
-		lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
-				"%d:0312 Ring %d handler: portRspPut %d "
-				"is bigger then rsp ring %d\n",
-				phba->brd_no, pring->ringno, portRspPut,
-				portRspMax);
-
-		phba->hba_state = LPFC_HBA_ERROR;
-
-		/* All error attention handlers are posted to worker thread */
-		phba->work_ha |= HA_ERATT;
-		phba->work_hs = HS_FFER3;
-		if (phba->work_wait)
-			wake_up(phba->work_wait);
-
+		lpfc_sli_rsp_pointers_error(phba, pring);
 		spin_unlock_irqrestore(phba->host->host_lock, iflag);
 		return 1;
 	}
@@ -947,6 +1106,10 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba * phba,
 		 * network byte order and pci byte orders are different.
 		 */
 		entry = IOCB_ENTRY(pring->rspringaddr, pring->rspidx);
+
+		if (++pring->rspidx >= portRspMax)
+			pring->rspidx = 0;
+
 		lpfc_sli_pcimem_bcopy((uint32_t *) entry,
 				      (uint32_t *) &rspiocbq.iocb,
 				      sizeof (IOCB_t));
@@ -1020,9 +1183,6 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba * phba,
 		 * been updated, sync the pgp->rspPutInx and fetch the new port
 		 * response put pointer.
 		 */
-		if (++pring->rspidx >= portRspMax)
-			pring->rspidx = 0;
-
 		to_slim = phba->MBslimaddr +
 			(SLIMOFF + (pring->ringno * 2) + 1) * 4;
 		writel(pring->rspidx, to_slim);
@@ -2615,6 +2775,7 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba * phba,
 	DECLARE_WAIT_QUEUE_HEAD(done_q);
 	long timeleft, timeout_req = 0;
 	int retval = IOCB_SUCCESS;
+	uint32_t creg_val;
 
 	/*
 	 * If the caller has provided a response iocbq buffer, then context2
@@ -2630,6 +2791,13 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba * phba,
 	piocb->context_un.wait_queue = &done_q;
 	piocb->iocb_flag &= ~LPFC_IO_WAKE;
 
+	if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
+		creg_val = readl(phba->HCregaddr);
+		creg_val |= (HC_R0INT_ENA << LPFC_FCP_RING);
+		writel(creg_val, phba->HCregaddr);
+		readl(phba->HCregaddr); /* flush */
+	}
+
 	retval = lpfc_sli_issue_iocb(phba, pring, piocb, 0);
 	if (retval == IOCB_SUCCESS) {
 		timeout_req = timeout * HZ;
@@ -2663,6 +2831,13 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba * phba,
 		retval = IOCB_ERROR;
 	}
 
+	if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
+		creg_val = readl(phba->HCregaddr);
+		creg_val &= ~(HC_R0INT_ENA << LPFC_FCP_RING);
+		writel(creg_val, phba->HCregaddr);
+		readl(phba->HCregaddr); /* flush */
+	}
+
 	if (prspiocbq)
 		piocb->context2 = NULL;
 
diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
index 4f0466fbd5f2..fa681a934ffe 100644
--- a/drivers/scsi/lpfc/lpfc_version.h
+++ b/drivers/scsi/lpfc/lpfc_version.h
@@ -18,7 +18,7 @@
  * included with this package.                                     *
  *******************************************************************/
 
-#define LPFC_DRIVER_VERSION "8.1.0"
+#define LPFC_DRIVER_VERSION "8.1.1"
 
 #define LPFC_DRIVER_NAME "lpfc"
 
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index 578143e93a6f..4a6feb1e5e3d 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -2,7 +2,7 @@
  *
  *			Linux MegaRAID device driver
  *
- * Copyright © 2002  LSI Logic Corporation.
+ * Copyright (c) 2002  LSI Logic Corporation.
  *
  *	   This program is free software; you can redistribute it and/or
  *	   modify it under the terms of the GNU General Public License
@@ -17,7 +17,8 @@
  * Copyright (c) 2003  Christoph Hellwig  <hch@lst.de>
  *	  - new-style, hotplug-aware pci probing and scsi registration
  *
- * Version : v2.00.3 (Feb 19, 2003) - Atul Mukker <Atul.Mukker@lsil.com>
+ * Version : v2.00.4 Mon Nov 14 14:02:43 EST 2005 - Seokmann Ju
+ * 						<Seokmann.Ju@lsil.com>
  *
  * Description: Linux device driver for LSI Logic MegaRAID controller
  *
@@ -51,10 +52,10 @@
 
 #include "megaraid.h"
 
-#define MEGARAID_MODULE_VERSION "2.00.3"
+#define MEGARAID_MODULE_VERSION "2.00.4"
 
-MODULE_AUTHOR ("LSI Logic Corporation");
-MODULE_DESCRIPTION ("LSI Logic MegaRAID driver");
+MODULE_AUTHOR ("sju@lsil.com");
+MODULE_DESCRIPTION ("LSI Logic MegaRAID legacy driver");
 MODULE_LICENSE ("GPL");
 MODULE_VERSION(MEGARAID_MODULE_VERSION);
 
@@ -4553,7 +4554,7 @@ mega_internal_done(Scsi_Cmnd *scmd)
 static struct scsi_host_template megaraid_template = {
 	.module				= THIS_MODULE,
 	.name				= "MegaRAID",
-	.proc_name			= "megaraid",
+	.proc_name			= "megaraid_legacy",
 	.info				= megaraid_info,
 	.queuecommand			= megaraid_queue,	
 	.bios_param			= megaraid_biosparam,
@@ -5037,22 +5038,12 @@ megaraid_shutdown(struct pci_dev *pdev)
 }
 
 static struct pci_device_id megaraid_pci_tbl[] = {
-	{PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DISCOVERY,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_PERC4_DI,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0, BOARD_64BIT},
-	{PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_PERC4_QC_VERDE,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0, BOARD_64BIT},
 	{PCI_VENDOR_ID_AMI, PCI_DEVICE_ID_AMI_MEGARAID,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{PCI_VENDOR_ID_AMI, PCI_DEVICE_ID_AMI_MEGARAID2,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_AMI, PCI_DEVICE_ID_AMI_MEGARAID3,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_AMI_MEGARAID3,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_AMI_MEGARAID3,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{0,}
 };
 MODULE_DEVICE_TABLE(pci, megaraid_pci_tbl);
@@ -5095,7 +5086,7 @@ static int __init megaraid_init(void)
 	 * First argument (major) to register_chrdev implies a dynamic
 	 * major number allocation.
 	 */
-	major = register_chrdev(0, "megadev", &megadev_fops);
+	major = register_chrdev(0, "megadev_legacy", &megadev_fops);
 	if (!major) {
 		printk(KERN_WARNING
 				"megaraid: failed to register char device\n");
@@ -5109,7 +5100,7 @@ static void __exit megaraid_exit(void)
 	/*
 	 * Unregister the character device interface to the driver.
 	 */
-	unregister_chrdev(major, "megadev");
+	unregister_chrdev(major, "megadev_legacy");
 
 	pci_unregister_driver(&megaraid_pci_driver);
 
diff --git a/drivers/scsi/megaraid/Kconfig.megaraid b/drivers/scsi/megaraid/Kconfig.megaraid
index 7363e12663ac..17419e30ffc8 100644
--- a/drivers/scsi/megaraid/Kconfig.megaraid
+++ b/drivers/scsi/megaraid/Kconfig.megaraid
@@ -64,7 +64,6 @@ config MEGARAID_MAILBOX
 	To compile this driver as a module, choose M here: the
 	module will be called megaraid_mbox
 
-if MEGARAID_NEWGEN=n
 config MEGARAID_LEGACY
 	tristate "LSI Logic Legacy MegaRAID Driver"
 	depends on PCI && SCSI
@@ -75,7 +74,6 @@ config MEGARAID_LEGACY
 
 	To compile this driver as a module, choose M here: the
 	module will be called megaraid
-endif
 
 config MEGARAID_SAS
 	tristate "LSI Logic MegaRAID SAS RAID Module"
diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c
index 4b5d420d2f4d..d18a4bc2498c 100644
--- a/drivers/scsi/megaraid/megaraid_mbox.c
+++ b/drivers/scsi/megaraid/megaraid_mbox.c
@@ -10,12 +10,13 @@
  *	   2 of the License, or (at your option) any later version.
  *
  * FILE		: megaraid_mbox.c
- * Version	: v2.20.4.6 (Mar 07 2005)
+ * Version	: v2.20.4.7 (Nov 14 2005)
  *
  * Authors:
  * 	Atul Mukker		<Atul.Mukker@lsil.com>
  * 	Sreenivas Bagalkote	<Sreenivas.Bagalkote@lsil.com>
  * 	Manoj Jose		<Manoj.Jose@lsil.com>
+ * 	Seokmann Ju		<Seokmann.Ju@lsil.com>
  *
  * List of supported controllers
  *
@@ -136,7 +137,7 @@ static int wait_till_fw_empty(adapter_t *);
 
 
 
-MODULE_AUTHOR("LSI Logic Corporation");
+MODULE_AUTHOR("sju@lsil.com");
 MODULE_DESCRIPTION("LSI Logic MegaRAID Mailbox Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(MEGARAID_VERSION);
@@ -278,68 +279,14 @@ static struct pci_device_id pci_id_table_g[] =  {
 	{
 		PCI_VENDOR_ID_AMI,
 		PCI_DEVICE_ID_AMI_MEGARAID3,
-		PCI_VENDOR_ID_DELL,
-		PCI_SUBSYS_ID_PERC3_QC,
-	},
-	{
-		PCI_VENDOR_ID_AMI,
-		PCI_DEVICE_ID_AMI_MEGARAID3,
-		PCI_VENDOR_ID_DELL,
-		PCI_SUBSYS_ID_PERC3_DC,
-	},
-	{
-		PCI_VENDOR_ID_AMI,
-		PCI_DEVICE_ID_AMI_MEGARAID3,
-		PCI_VENDOR_ID_DELL,
-		PCI_SUBSYS_ID_PERC3_SC,
-	},
-	{
-		PCI_VENDOR_ID_AMI,
-		PCI_DEVICE_ID_AMI_MEGARAID3,
-		PCI_VENDOR_ID_AMI,
-		PCI_SUBSYS_ID_PERC3_SC,
-	},
-	{
-		PCI_VENDOR_ID_AMI,
-		PCI_DEVICE_ID_AMI_MEGARAID3,
-		PCI_VENDOR_ID_AMI,
-		PCI_SUBSYS_ID_PERC3_DC,
-	},
-	{
-		PCI_VENDOR_ID_LSI_LOGIC,
-		PCI_DEVICE_ID_MEGARAID_SCSI_320_0,
-		PCI_VENDOR_ID_LSI_LOGIC,
-		PCI_SUBSYS_ID_MEGARAID_SCSI_320_0,
-	},
-	{
-		PCI_VENDOR_ID_LSI_LOGIC,
-		PCI_DEVICE_ID_MEGARAID_SCSI_320_1,
-		PCI_VENDOR_ID_LSI_LOGIC,
-		PCI_SUBSYS_ID_MEGARAID_SCSI_320_1,
-	},
-	{
-		PCI_VENDOR_ID_LSI_LOGIC,
-		PCI_DEVICE_ID_MEGARAID_SCSI_320_2,
-		PCI_VENDOR_ID_LSI_LOGIC,
-		PCI_SUBSYS_ID_MEGARAID_SCSI_320_2,
-	},
-	{
-		PCI_VENDOR_ID_LSI_LOGIC,
-		PCI_DEVICE_ID_MEGARAID_I4_133_RAID,
-		PCI_VENDOR_ID_LSI_LOGIC,
-		PCI_SUBSYS_ID_MEGARAID_I4_133_RAID,
-	},
-	{
-		PCI_VENDOR_ID_LSI_LOGIC,
-		PCI_DEVICE_ID_MEGARAID_SATA_150_4,
-		PCI_VENDOR_ID_LSI_LOGIC,
-		PCI_SUBSYS_ID_MEGARAID_SATA_150_4,
+		PCI_ANY_ID,
+		PCI_ANY_ID,
 	},
 	{
 		PCI_VENDOR_ID_LSI_LOGIC,
-		PCI_DEVICE_ID_MEGARAID_SATA_150_6,
-		PCI_VENDOR_ID_LSI_LOGIC,
-		PCI_SUBSYS_ID_MEGARAID_SATA_150_6,
+		PCI_DEVICE_ID_AMI_MEGARAID3,
+		PCI_ANY_ID,
+		PCI_ANY_ID,
 	},
 	{
 		PCI_VENDOR_ID_LSI_LOGIC,
@@ -347,18 +294,6 @@ static struct pci_device_id pci_id_table_g[] =  {
 		PCI_ANY_ID,
 		PCI_ANY_ID,
 	},
-	{
-		PCI_VENDOR_ID_LSI_LOGIC,
-		PCI_DEVICE_ID_INTEL_RAID_SRCS16,
-		PCI_VENDOR_ID_INTEL,
-		PCI_SUBSYS_ID_INTEL_RAID_SRCS16,
-	},
-	{
-		PCI_VENDOR_ID_LSI_LOGIC,
-		PCI_DEVICE_ID_INTEL_RAID_SRCU41L_LAKE_SHETEK,
-		PCI_VENDOR_ID_INTEL,
-		PCI_SUBSYS_ID_INTEL_RAID_SRCU41L_LAKE_SHETEK,
-	},
 	{0}	/* Terminating entry */
 };
 MODULE_DEVICE_TABLE(pci, pci_id_table_g);
@@ -2985,6 +2920,7 @@ mbox_post_sync_cmd_fast(adapter_t *adapter, uint8_t raw_mbox[])
 
 	for (i = 0; i < 0xFFFFF; i++) {
 		if (mbox->numstatus != 0xFF) break;
+		rmb();
 	}
 
 	if (i == 0xFFFFF) {
diff --git a/drivers/scsi/megaraid/megaraid_mbox.h b/drivers/scsi/megaraid/megaraid_mbox.h
index 644b91bdb028..882fb1a0b575 100644
--- a/drivers/scsi/megaraid/megaraid_mbox.h
+++ b/drivers/scsi/megaraid/megaraid_mbox.h
@@ -21,8 +21,8 @@
 #include "megaraid_ioctl.h"
 
 
-#define MEGARAID_VERSION	"2.20.4.6"
-#define MEGARAID_EXT_VERSION	"(Release Date: Mon Mar 07 12:27:22 EST 2005)"
+#define MEGARAID_VERSION	"2.20.4.7"
+#define MEGARAID_EXT_VERSION	"(Release Date: Mon Nov 14 12:27:22 EST 2005)"
 
 
 /*
diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c
index 243470936fab..32350707b940 100644
--- a/drivers/scsi/ncr53c8xx.c
+++ b/drivers/scsi/ncr53c8xx.c
@@ -131,7 +131,739 @@
 #define NAME53C			"ncr53c"
 #define NAME53C8XX		"ncr53c8xx"
 
-#include "sym53c8xx_comm.h"
+
+/*==========================================================
+**
+**	Debugging tags
+**
+**==========================================================
+*/
+
+#define DEBUG_ALLOC    (0x0001)
+#define DEBUG_PHASE    (0x0002)
+#define DEBUG_QUEUE    (0x0008)
+#define DEBUG_RESULT   (0x0010)
+#define DEBUG_POINTER  (0x0020)
+#define DEBUG_SCRIPT   (0x0040)
+#define DEBUG_TINY     (0x0080)
+#define DEBUG_TIMING   (0x0100)
+#define DEBUG_NEGO     (0x0200)
+#define DEBUG_TAGS     (0x0400)
+#define DEBUG_SCATTER  (0x0800)
+#define DEBUG_IC        (0x1000)
+
+/*
+**    Enable/Disable debug messages.
+**    Can be changed at runtime too.
+*/
+
+#ifdef SCSI_NCR_DEBUG_INFO_SUPPORT
+static int ncr_debug = SCSI_NCR_DEBUG_FLAGS;
+	#define DEBUG_FLAGS ncr_debug
+#else
+	#define DEBUG_FLAGS	SCSI_NCR_DEBUG_FLAGS
+#endif
+
+static inline struct list_head *ncr_list_pop(struct list_head *head)
+{
+	if (!list_empty(head)) {
+		struct list_head *elem = head->next;
+
+		list_del(elem);
+		return elem;
+	}
+
+	return NULL;
+}
+
+/*==========================================================
+**
+**	Simple power of two buddy-like allocator.
+**
+**	This simple code is not intended to be fast, but to 
+**	provide power of 2 aligned memory allocations.
+**	Since the SCRIPTS processor only supplies 8 bit 
+**	arithmetic, this allocator allows simple and fast 
+**	address calculations  from the SCRIPTS code.
+**	In addition, cache line alignment is guaranteed for 
+**	power of 2 cache line size.
+**	Enhanced in linux-2.3.44 to provide a memory pool 
+**	per pcidev to support dynamic dma mapping. (I would 
+**	have preferred a real bus astraction, btw).
+**
+**==========================================================
+*/
+
+#define MEMO_SHIFT	4	/* 16 bytes minimum memory chunk */
+#if PAGE_SIZE >= 8192
+#define MEMO_PAGE_ORDER	0	/* 1 PAGE  maximum */
+#else
+#define MEMO_PAGE_ORDER	1	/* 2 PAGES maximum */
+#endif
+#define MEMO_FREE_UNUSED	/* Free unused pages immediately */
+#define MEMO_WARN	1
+#define MEMO_GFP_FLAGS	GFP_ATOMIC
+#define MEMO_CLUSTER_SHIFT	(PAGE_SHIFT+MEMO_PAGE_ORDER)
+#define MEMO_CLUSTER_SIZE	(1UL << MEMO_CLUSTER_SHIFT)
+#define MEMO_CLUSTER_MASK	(MEMO_CLUSTER_SIZE-1)
+
+typedef u_long m_addr_t;	/* Enough bits to bit-hack addresses */
+typedef struct device *m_bush_t;	/* Something that addresses DMAable */
+
+typedef struct m_link {		/* Link between free memory chunks */
+	struct m_link *next;
+} m_link_s;
+
+typedef struct m_vtob {		/* Virtual to Bus address translation */
+	struct m_vtob *next;
+	m_addr_t vaddr;
+	m_addr_t baddr;
+} m_vtob_s;
+#define VTOB_HASH_SHIFT		5
+#define VTOB_HASH_SIZE		(1UL << VTOB_HASH_SHIFT)
+#define VTOB_HASH_MASK		(VTOB_HASH_SIZE-1)
+#define VTOB_HASH_CODE(m)	\
+	((((m_addr_t) (m)) >> MEMO_CLUSTER_SHIFT) & VTOB_HASH_MASK)
+
+typedef struct m_pool {		/* Memory pool of a given kind */
+	m_bush_t bush;
+	m_addr_t (*getp)(struct m_pool *);
+	void (*freep)(struct m_pool *, m_addr_t);
+	int nump;
+	m_vtob_s *(vtob[VTOB_HASH_SIZE]);
+	struct m_pool *next;
+	struct m_link h[PAGE_SHIFT-MEMO_SHIFT+MEMO_PAGE_ORDER+1];
+} m_pool_s;
+
+static void *___m_alloc(m_pool_s *mp, int size)
+{
+	int i = 0;
+	int s = (1 << MEMO_SHIFT);
+	int j;
+	m_addr_t a;
+	m_link_s *h = mp->h;
+
+	if (size > (PAGE_SIZE << MEMO_PAGE_ORDER))
+		return NULL;
+
+	while (size > s) {
+		s <<= 1;
+		++i;
+	}
+
+	j = i;
+	while (!h[j].next) {
+		if (s == (PAGE_SIZE << MEMO_PAGE_ORDER)) {
+			h[j].next = (m_link_s *)mp->getp(mp);
+			if (h[j].next)
+				h[j].next->next = NULL;
+			break;
+		}
+		++j;
+		s <<= 1;
+	}
+	a = (m_addr_t) h[j].next;
+	if (a) {
+		h[j].next = h[j].next->next;
+		while (j > i) {
+			j -= 1;
+			s >>= 1;
+			h[j].next = (m_link_s *) (a+s);
+			h[j].next->next = NULL;
+		}
+	}
+#ifdef DEBUG
+	printk("___m_alloc(%d) = %p\n", size, (void *) a);
+#endif
+	return (void *) a;
+}
+
+static void ___m_free(m_pool_s *mp, void *ptr, int size)
+{
+	int i = 0;
+	int s = (1 << MEMO_SHIFT);
+	m_link_s *q;
+	m_addr_t a, b;
+	m_link_s *h = mp->h;
+
+#ifdef DEBUG
+	printk("___m_free(%p, %d)\n", ptr, size);
+#endif
+
+	if (size > (PAGE_SIZE << MEMO_PAGE_ORDER))
+		return;
+
+	while (size > s) {
+		s <<= 1;
+		++i;
+	}
+
+	a = (m_addr_t) ptr;
+
+	while (1) {
+#ifdef MEMO_FREE_UNUSED
+		if (s == (PAGE_SIZE << MEMO_PAGE_ORDER)) {
+			mp->freep(mp, a);
+			break;
+		}
+#endif
+		b = a ^ s;
+		q = &h[i];
+		while (q->next && q->next != (m_link_s *) b) {
+			q = q->next;
+		}
+		if (!q->next) {
+			((m_link_s *) a)->next = h[i].next;
+			h[i].next = (m_link_s *) a;
+			break;
+		}
+		q->next = q->next->next;
+		a = a & b;
+		s <<= 1;
+		++i;
+	}
+}
+
+static DEFINE_SPINLOCK(ncr53c8xx_lock);
+
+static void *__m_calloc2(m_pool_s *mp, int size, char *name, int uflags)
+{
+	void *p;
+
+	p = ___m_alloc(mp, size);
+
+	if (DEBUG_FLAGS & DEBUG_ALLOC)
+		printk ("new %-10s[%4d] @%p.\n", name, size, p);
+
+	if (p)
+		memset(p, 0, size);
+	else if (uflags & MEMO_WARN)
+		printk (NAME53C8XX ": failed to allocate %s[%d]\n", name, size);
+
+	return p;
+}
+
+#define __m_calloc(mp, s, n)	__m_calloc2(mp, s, n, MEMO_WARN)
+
+static void __m_free(m_pool_s *mp, void *ptr, int size, char *name)
+{
+	if (DEBUG_FLAGS & DEBUG_ALLOC)
+		printk ("freeing %-10s[%4d] @%p.\n", name, size, ptr);
+
+	___m_free(mp, ptr, size);
+
+}
+
+/*
+ * With pci bus iommu support, we use a default pool of unmapped memory 
+ * for memory we donnot need to DMA from/to and one pool per pcidev for 
+ * memory accessed by the PCI chip. `mp0' is the default not DMAable pool.
+ */
+
+static m_addr_t ___mp0_getp(m_pool_s *mp)
+{
+	m_addr_t m = __get_free_pages(MEMO_GFP_FLAGS, MEMO_PAGE_ORDER);
+	if (m)
+		++mp->nump;
+	return m;
+}
+
+static void ___mp0_freep(m_pool_s *mp, m_addr_t m)
+{
+	free_pages(m, MEMO_PAGE_ORDER);
+	--mp->nump;
+}
+
+static m_pool_s mp0 = {NULL, ___mp0_getp, ___mp0_freep};
+
+/*
+ * DMAable pools.
+ */
+
+/*
+ * With pci bus iommu support, we maintain one pool per pcidev and a 
+ * hashed reverse table for virtual to bus physical address translations.
+ */
+static m_addr_t ___dma_getp(m_pool_s *mp)
+{
+	m_addr_t vp;
+	m_vtob_s *vbp;
+
+	vbp = __m_calloc(&mp0, sizeof(*vbp), "VTOB");
+	if (vbp) {
+		dma_addr_t daddr;
+		vp = (m_addr_t) dma_alloc_coherent(mp->bush,
+						PAGE_SIZE<<MEMO_PAGE_ORDER,
+						&daddr, GFP_ATOMIC);
+		if (vp) {
+			int hc = VTOB_HASH_CODE(vp);
+			vbp->vaddr = vp;
+			vbp->baddr = daddr;
+			vbp->next = mp->vtob[hc];
+			mp->vtob[hc] = vbp;
+			++mp->nump;
+			return vp;
+		}
+	}
+	if (vbp)
+		__m_free(&mp0, vbp, sizeof(*vbp), "VTOB");
+	return 0;
+}
+
+static void ___dma_freep(m_pool_s *mp, m_addr_t m)
+{
+	m_vtob_s **vbpp, *vbp;
+	int hc = VTOB_HASH_CODE(m);
+
+	vbpp = &mp->vtob[hc];
+	while (*vbpp && (*vbpp)->vaddr != m)
+		vbpp = &(*vbpp)->next;
+	if (*vbpp) {
+		vbp = *vbpp;
+		*vbpp = (*vbpp)->next;
+		dma_free_coherent(mp->bush, PAGE_SIZE<<MEMO_PAGE_ORDER,
+				  (void *)vbp->vaddr, (dma_addr_t)vbp->baddr);
+		__m_free(&mp0, vbp, sizeof(*vbp), "VTOB");
+		--mp->nump;
+	}
+}
+
+static inline m_pool_s *___get_dma_pool(m_bush_t bush)
+{
+	m_pool_s *mp;
+	for (mp = mp0.next; mp && mp->bush != bush; mp = mp->next);
+	return mp;
+}
+
+static m_pool_s *___cre_dma_pool(m_bush_t bush)
+{
+	m_pool_s *mp;
+	mp = __m_calloc(&mp0, sizeof(*mp), "MPOOL");
+	if (mp) {
+		memset(mp, 0, sizeof(*mp));
+		mp->bush = bush;
+		mp->getp = ___dma_getp;
+		mp->freep = ___dma_freep;
+		mp->next = mp0.next;
+		mp0.next = mp;
+	}
+	return mp;
+}
+
+static void ___del_dma_pool(m_pool_s *p)
+{
+	struct m_pool **pp = &mp0.next;
+
+	while (*pp && *pp != p)
+		pp = &(*pp)->next;
+	if (*pp) {
+		*pp = (*pp)->next;
+		__m_free(&mp0, p, sizeof(*p), "MPOOL");
+	}
+}
+
+static void *__m_calloc_dma(m_bush_t bush, int size, char *name)
+{
+	u_long flags;
+	struct m_pool *mp;
+	void *m = NULL;
+
+	spin_lock_irqsave(&ncr53c8xx_lock, flags);
+	mp = ___get_dma_pool(bush);
+	if (!mp)
+		mp = ___cre_dma_pool(bush);
+	if (mp)
+		m = __m_calloc(mp, size, name);
+	if (mp && !mp->nump)
+		___del_dma_pool(mp);
+	spin_unlock_irqrestore(&ncr53c8xx_lock, flags);
+
+	return m;
+}
+
+static void __m_free_dma(m_bush_t bush, void *m, int size, char *name)
+{
+	u_long flags;
+	struct m_pool *mp;
+
+	spin_lock_irqsave(&ncr53c8xx_lock, flags);
+	mp = ___get_dma_pool(bush);
+	if (mp)
+		__m_free(mp, m, size, name);
+	if (mp && !mp->nump)
+		___del_dma_pool(mp);
+	spin_unlock_irqrestore(&ncr53c8xx_lock, flags);
+}
+
+static m_addr_t __vtobus(m_bush_t bush, void *m)
+{
+	u_long flags;
+	m_pool_s *mp;
+	int hc = VTOB_HASH_CODE(m);
+	m_vtob_s *vp = NULL;
+	m_addr_t a = ((m_addr_t) m) & ~MEMO_CLUSTER_MASK;
+
+	spin_lock_irqsave(&ncr53c8xx_lock, flags);
+	mp = ___get_dma_pool(bush);
+	if (mp) {
+		vp = mp->vtob[hc];
+		while (vp && (m_addr_t) vp->vaddr != a)
+			vp = vp->next;
+	}
+	spin_unlock_irqrestore(&ncr53c8xx_lock, flags);
+	return vp ? vp->baddr + (((m_addr_t) m) - a) : 0;
+}
+
+#define _m_calloc_dma(np, s, n)		__m_calloc_dma(np->dev, s, n)
+#define _m_free_dma(np, p, s, n)	__m_free_dma(np->dev, p, s, n)
+#define m_calloc_dma(s, n)		_m_calloc_dma(np, s, n)
+#define m_free_dma(p, s, n)		_m_free_dma(np, p, s, n)
+#define _vtobus(np, p)			__vtobus(np->dev, p)
+#define vtobus(p)			_vtobus(np, p)
+
+/*
+ *  Deal with DMA mapping/unmapping.
+ */
+
+/* To keep track of the dma mapping (sg/single) that has been set */
+#define __data_mapped	SCp.phase
+#define __data_mapping	SCp.have_data_in
+
+static void __unmap_scsi_data(struct device *dev, struct scsi_cmnd *cmd)
+{
+	switch(cmd->__data_mapped) {
+	case 2:
+		dma_unmap_sg(dev, cmd->buffer, cmd->use_sg,
+				cmd->sc_data_direction);
+		break;
+	case 1:
+		dma_unmap_single(dev, cmd->__data_mapping,
+				 cmd->request_bufflen,
+				 cmd->sc_data_direction);
+		break;
+	}
+	cmd->__data_mapped = 0;
+}
+
+static u_long __map_scsi_single_data(struct device *dev, struct scsi_cmnd *cmd)
+{
+	dma_addr_t mapping;
+
+	if (cmd->request_bufflen == 0)
+		return 0;
+
+	mapping = dma_map_single(dev, cmd->request_buffer,
+				 cmd->request_bufflen,
+				 cmd->sc_data_direction);
+	cmd->__data_mapped = 1;
+	cmd->__data_mapping = mapping;
+
+	return mapping;
+}
+
+static int __map_scsi_sg_data(struct device *dev, struct scsi_cmnd *cmd)
+{
+	int use_sg;
+
+	if (cmd->use_sg == 0)
+		return 0;
+
+	use_sg = dma_map_sg(dev, cmd->buffer, cmd->use_sg,
+			cmd->sc_data_direction);
+	cmd->__data_mapped = 2;
+	cmd->__data_mapping = use_sg;
+
+	return use_sg;
+}
+
+#define unmap_scsi_data(np, cmd)	__unmap_scsi_data(np->dev, cmd)
+#define map_scsi_single_data(np, cmd)	__map_scsi_single_data(np->dev, cmd)
+#define map_scsi_sg_data(np, cmd)	__map_scsi_sg_data(np->dev, cmd)
+
+/*==========================================================
+**
+**	Driver setup.
+**
+**	This structure is initialized from linux config 
+**	options. It can be overridden at boot-up by the boot 
+**	command line.
+**
+**==========================================================
+*/
+static struct ncr_driver_setup
+	driver_setup			= SCSI_NCR_DRIVER_SETUP;
+
+#ifdef	SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT
+static struct ncr_driver_setup
+	driver_safe_setup __initdata	= SCSI_NCR_DRIVER_SAFE_SETUP;
+#endif
+
+#define initverbose (driver_setup.verbose)
+#define bootverbose (np->verbose)
+
+
+/*===================================================================
+**
+**	Driver setup from the boot command line
+**
+**===================================================================
+*/
+
+#ifdef MODULE
+#define	ARG_SEP	' '
+#else
+#define	ARG_SEP	','
+#endif
+
+#define OPT_TAGS		1
+#define OPT_MASTER_PARITY	2
+#define OPT_SCSI_PARITY		3
+#define OPT_DISCONNECTION	4
+#define OPT_SPECIAL_FEATURES	5
+#define OPT_UNUSED_1		6
+#define OPT_FORCE_SYNC_NEGO	7
+#define OPT_REVERSE_PROBE	8
+#define OPT_DEFAULT_SYNC	9
+#define OPT_VERBOSE		10
+#define OPT_DEBUG		11
+#define OPT_BURST_MAX		12
+#define OPT_LED_PIN		13
+#define OPT_MAX_WIDE		14
+#define OPT_SETTLE_DELAY	15
+#define OPT_DIFF_SUPPORT	16
+#define OPT_IRQM		17
+#define OPT_PCI_FIX_UP		18
+#define OPT_BUS_CHECK		19
+#define OPT_OPTIMIZE		20
+#define OPT_RECOVERY		21
+#define OPT_SAFE_SETUP		22
+#define OPT_USE_NVRAM		23
+#define OPT_EXCLUDE		24
+#define OPT_HOST_ID		25
+
+#ifdef SCSI_NCR_IARB_SUPPORT
+#define OPT_IARB		26
+#endif
+
+static char setup_token[] __initdata = 
+	"tags:"   "mpar:"
+	"spar:"   "disc:"
+	"specf:"  "ultra:"
+	"fsn:"    "revprob:"
+	"sync:"   "verb:"
+	"debug:"  "burst:"
+	"led:"    "wide:"
+	"settle:" "diff:"
+	"irqm:"   "pcifix:"
+	"buschk:" "optim:"
+	"recovery:"
+	"safe:"   "nvram:"
+	"excl:"   "hostid:"
+#ifdef SCSI_NCR_IARB_SUPPORT
+	"iarb:"
+#endif
+	;	/* DONNOT REMOVE THIS ';' */
+
+#ifdef MODULE
+#define	ARG_SEP	' '
+#else
+#define	ARG_SEP	','
+#endif
+
+static int __init get_setup_token(char *p)
+{
+	char *cur = setup_token;
+	char *pc;
+	int i = 0;
+
+	while (cur != NULL && (pc = strchr(cur, ':')) != NULL) {
+		++pc;
+		++i;
+		if (!strncmp(p, cur, pc - cur))
+			return i;
+		cur = pc;
+	}
+	return 0;
+}
+
+
+static int __init sym53c8xx__setup(char *str)
+{
+#ifdef SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT
+	char *cur = str;
+	char *pc, *pv;
+	int i, val, c;
+	int xi = 0;
+
+	while (cur != NULL && (pc = strchr(cur, ':')) != NULL) {
+		char *pe;
+
+		val = 0;
+		pv = pc;
+		c = *++pv;
+
+		if	(c == 'n')
+			val = 0;
+		else if	(c == 'y')
+			val = 1;
+		else
+			val = (int) simple_strtoul(pv, &pe, 0);
+
+		switch (get_setup_token(cur)) {
+		case OPT_TAGS:
+			driver_setup.default_tags = val;
+			if (pe && *pe == '/') {
+				i = 0;
+				while (*pe && *pe != ARG_SEP && 
+					i < sizeof(driver_setup.tag_ctrl)-1) {
+					driver_setup.tag_ctrl[i++] = *pe++;
+				}
+				driver_setup.tag_ctrl[i] = '\0';
+			}
+			break;
+		case OPT_MASTER_PARITY:
+			driver_setup.master_parity = val;
+			break;
+		case OPT_SCSI_PARITY:
+			driver_setup.scsi_parity = val;
+			break;
+		case OPT_DISCONNECTION:
+			driver_setup.disconnection = val;
+			break;
+		case OPT_SPECIAL_FEATURES:
+			driver_setup.special_features = val;
+			break;
+		case OPT_FORCE_SYNC_NEGO:
+			driver_setup.force_sync_nego = val;
+			break;
+		case OPT_REVERSE_PROBE:
+			driver_setup.reverse_probe = val;
+			break;
+		case OPT_DEFAULT_SYNC:
+			driver_setup.default_sync = val;
+			break;
+		case OPT_VERBOSE:
+			driver_setup.verbose = val;
+			break;
+		case OPT_DEBUG:
+			driver_setup.debug = val;
+			break;
+		case OPT_BURST_MAX:
+			driver_setup.burst_max = val;
+			break;
+		case OPT_LED_PIN:
+			driver_setup.led_pin = val;
+			break;
+		case OPT_MAX_WIDE:
+			driver_setup.max_wide = val? 1:0;
+			break;
+		case OPT_SETTLE_DELAY:
+			driver_setup.settle_delay = val;
+			break;
+		case OPT_DIFF_SUPPORT:
+			driver_setup.diff_support = val;
+			break;
+		case OPT_IRQM:
+			driver_setup.irqm = val;
+			break;
+		case OPT_PCI_FIX_UP:
+			driver_setup.pci_fix_up	= val;
+			break;
+		case OPT_BUS_CHECK:
+			driver_setup.bus_check = val;
+			break;
+		case OPT_OPTIMIZE:
+			driver_setup.optimize = val;
+			break;
+		case OPT_RECOVERY:
+			driver_setup.recovery = val;
+			break;
+		case OPT_USE_NVRAM:
+			driver_setup.use_nvram = val;
+			break;
+		case OPT_SAFE_SETUP:
+			memcpy(&driver_setup, &driver_safe_setup,
+				sizeof(driver_setup));
+			break;
+		case OPT_EXCLUDE:
+			if (xi < SCSI_NCR_MAX_EXCLUDES)
+				driver_setup.excludes[xi++] = val;
+			break;
+		case OPT_HOST_ID:
+			driver_setup.host_id = val;
+			break;
+#ifdef SCSI_NCR_IARB_SUPPORT
+		case OPT_IARB:
+			driver_setup.iarb = val;
+			break;
+#endif
+		default:
+			printk("sym53c8xx_setup: unexpected boot option '%.*s' ignored\n", (int)(pc-cur+1), cur);
+			break;
+		}
+
+		if ((cur = strchr(cur, ARG_SEP)) != NULL)
+			++cur;
+	}
+#endif /* SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT */
+	return 1;
+}
+
+/*===================================================================
+**
+**	Get device queue depth from boot command line.
+**
+**===================================================================
+*/
+#define DEF_DEPTH	(driver_setup.default_tags)
+#define ALL_TARGETS	-2
+#define NO_TARGET	-1
+#define ALL_LUNS	-2
+#define NO_LUN		-1
+
+static int device_queue_depth(int unit, int target, int lun)
+{
+	int c, h, t, u, v;
+	char *p = driver_setup.tag_ctrl;
+	char *ep;
+
+	h = -1;
+	t = NO_TARGET;
+	u = NO_LUN;
+	while ((c = *p++) != 0) {
+		v = simple_strtoul(p, &ep, 0);
+		switch(c) {
+		case '/':
+			++h;
+			t = ALL_TARGETS;
+			u = ALL_LUNS;
+			break;
+		case 't':
+			if (t != target)
+				t = (target == v) ? v : NO_TARGET;
+			u = ALL_LUNS;
+			break;
+		case 'u':
+			if (u != lun)
+				u = (lun == v) ? v : NO_LUN;
+			break;
+		case 'q':
+			if (h == unit &&
+				(t == ALL_TARGETS || t == target) &&
+				(u == ALL_LUNS    || u == lun))
+				return v;
+			break;
+		case '-':
+			t = ALL_TARGETS;
+			u = ALL_LUNS;
+			break;
+		default:
+			break;
+		}
+		p = ep;
+	}
+	return DEF_DEPTH;
+}
 
 
 /*==========================================================
@@ -2971,21 +3703,10 @@ struct host_data {
 
 static void ncr_print_msg(struct ccb *cp, char *label, u_char *msg)
 {
-	int i;
 	PRINT_ADDR(cp->cmd, "%s: ", label);
 
-	printk ("%x",*msg);
-	if (*msg == M_EXTENDED) {
-		for (i = 1; i < 8; i++) {
-			if (i - 1 > msg[1])
-				break;
-			printk ("-%x",msg[i]);
-		}
-	} else if ((*msg & 0xf0) == 0x20) {
-		printk ("-%x",msg[1]);
-	}
-
-	printk(".\n");
+	spi_print_msg(msg);
+	printk("\n");
 }
 
 /*==========================================================
diff --git a/drivers/scsi/ncr53c8xx.h b/drivers/scsi/ncr53c8xx.h
index 05c7b83cef09..6a7bef2e6118 100644
--- a/drivers/scsi/ncr53c8xx.h
+++ b/drivers/scsi/ncr53c8xx.h
@@ -2,6 +2,7 @@
 **  Device driver for the PCI-SCSI NCR538XX controller family.
 **
 **  Copyright (C) 1994  Wolfgang Stanglmeier
+**  Copyright (C) 1998-2001  Gerard Roudier <groudier@free.fr>
 **
 **  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
@@ -36,15 +37,1275 @@
 **  And has been ported to NetBSD by
 **          Charles M. Hannum           <mycroft@gnu.ai.mit.edu>
 **
+**  NVRAM detection and reading.
+**    Copyright (C) 1997 Richard Waltham <dormouse@farsrobt.demon.co.uk>
+**
+**  Added support for MIPS big endian systems.
+**    Carsten Langgaard, carstenl@mips.com
+**    Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+**
+**  Added support for HP PARISC big endian systems.
+**    Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+**
 *******************************************************************************
 */
 
 #ifndef NCR53C8XX_H
 #define NCR53C8XX_H
 
+#include <linux/config.h>
 #include <scsi/scsi_host.h>
 
-#include "sym53c8xx_defs.h"
+/*
+**	If you want a driver as small as possible, do not define the 
+**	following options.
+*/
+#define SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT
+#define SCSI_NCR_DEBUG_INFO_SUPPORT
+
+/*
+**	To disable integrity checking, do not define the 
+**	following option.
+*/
+#ifdef	CONFIG_SCSI_NCR53C8XX_INTEGRITY_CHECK
+#	define SCSI_NCR_ENABLE_INTEGRITY_CHECK
+#endif
+
+/* ---------------------------------------------------------------------
+** Take into account kernel configured parameters.
+** Most of these options can be overridden at startup by a command line.
+** ---------------------------------------------------------------------
+*/
+
+/*
+ * For Ultra2 and Ultra3 SCSI support option, use special features. 
+ *
+ * Value (default) means:
+ *	bit 0 : all features enabled, except:
+ *		bit 1 : PCI Write And Invalidate.
+ *		bit 2 : Data Phase Mismatch handling from SCRIPTS.
+ *
+ * Use boot options ncr53c8xx=specf:1 if you want all chip features to be 
+ * enabled by the driver.
+ */
+#define	SCSI_NCR_SETUP_SPECIAL_FEATURES		(3)
+
+#define SCSI_NCR_MAX_SYNC			(80)
+
+/*
+ * Allow tags from 2 to 256, default 8
+ */
+#ifdef	CONFIG_SCSI_NCR53C8XX_MAX_TAGS
+#if	CONFIG_SCSI_NCR53C8XX_MAX_TAGS < 2
+#define SCSI_NCR_MAX_TAGS	(2)
+#elif	CONFIG_SCSI_NCR53C8XX_MAX_TAGS > 256
+#define SCSI_NCR_MAX_TAGS	(256)
+#else
+#define	SCSI_NCR_MAX_TAGS	CONFIG_SCSI_NCR53C8XX_MAX_TAGS
+#endif
+#else
+#define SCSI_NCR_MAX_TAGS	(8)
+#endif
+
+/*
+ * Allow tagged command queuing support if configured with default number 
+ * of tags set to max (see above).
+ */
+#ifdef	CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS
+#define	SCSI_NCR_SETUP_DEFAULT_TAGS	CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS
+#elif	defined CONFIG_SCSI_NCR53C8XX_TAGGED_QUEUE
+#define	SCSI_NCR_SETUP_DEFAULT_TAGS	SCSI_NCR_MAX_TAGS
+#else
+#define	SCSI_NCR_SETUP_DEFAULT_TAGS	(0)
+#endif
+
+/*
+ * Immediate arbitration
+ */
+#if defined(CONFIG_SCSI_NCR53C8XX_IARB)
+#define SCSI_NCR_IARB_SUPPORT
+#endif
+
+/*
+ * Sync transfer frequency at startup.
+ * Allow from 5Mhz to 80Mhz default 20 Mhz.
+ */
+#ifndef	CONFIG_SCSI_NCR53C8XX_SYNC
+#define	CONFIG_SCSI_NCR53C8XX_SYNC	(20)
+#elif	CONFIG_SCSI_NCR53C8XX_SYNC > SCSI_NCR_MAX_SYNC
+#undef	CONFIG_SCSI_NCR53C8XX_SYNC
+#define	CONFIG_SCSI_NCR53C8XX_SYNC	SCSI_NCR_MAX_SYNC
+#endif
+
+#if	CONFIG_SCSI_NCR53C8XX_SYNC == 0
+#define	SCSI_NCR_SETUP_DEFAULT_SYNC	(255)
+#elif	CONFIG_SCSI_NCR53C8XX_SYNC <= 5
+#define	SCSI_NCR_SETUP_DEFAULT_SYNC	(50)
+#elif	CONFIG_SCSI_NCR53C8XX_SYNC <= 20
+#define	SCSI_NCR_SETUP_DEFAULT_SYNC	(250/(CONFIG_SCSI_NCR53C8XX_SYNC))
+#elif	CONFIG_SCSI_NCR53C8XX_SYNC <= 33
+#define	SCSI_NCR_SETUP_DEFAULT_SYNC	(11)
+#elif	CONFIG_SCSI_NCR53C8XX_SYNC <= 40
+#define	SCSI_NCR_SETUP_DEFAULT_SYNC	(10)
+#else
+#define	SCSI_NCR_SETUP_DEFAULT_SYNC 	(9)
+#endif
+
+/*
+ * Disallow disconnections at boot-up
+ */
+#ifdef CONFIG_SCSI_NCR53C8XX_NO_DISCONNECT
+#define SCSI_NCR_SETUP_DISCONNECTION	(0)
+#else
+#define SCSI_NCR_SETUP_DISCONNECTION	(1)
+#endif
+
+/*
+ * Force synchronous negotiation for all targets
+ */
+#ifdef CONFIG_SCSI_NCR53C8XX_FORCE_SYNC_NEGO
+#define SCSI_NCR_SETUP_FORCE_SYNC_NEGO	(1)
+#else
+#define SCSI_NCR_SETUP_FORCE_SYNC_NEGO	(0)
+#endif
+
+/*
+ * Disable master parity checking (flawed hardwares need that)
+ */
+#ifdef CONFIG_SCSI_NCR53C8XX_DISABLE_MPARITY_CHECK
+#define SCSI_NCR_SETUP_MASTER_PARITY	(0)
+#else
+#define SCSI_NCR_SETUP_MASTER_PARITY	(1)
+#endif
+
+/*
+ * Disable scsi parity checking (flawed devices may need that)
+ */
+#ifdef CONFIG_SCSI_NCR53C8XX_DISABLE_PARITY_CHECK
+#define SCSI_NCR_SETUP_SCSI_PARITY	(0)
+#else
+#define SCSI_NCR_SETUP_SCSI_PARITY	(1)
+#endif
+
+/*
+ * Settle time after reset at boot-up
+ */
+#define SCSI_NCR_SETUP_SETTLE_TIME	(2)
+
+/*
+**	Bridge quirks work-around option defaulted to 1.
+*/
+#ifndef	SCSI_NCR_PCIQ_WORK_AROUND_OPT
+#define	SCSI_NCR_PCIQ_WORK_AROUND_OPT	1
+#endif
+
+/*
+**	Work-around common bridge misbehaviour.
+**
+**	- Do not flush posted writes in the opposite 
+**	  direction on read.
+**	- May reorder DMA writes to memory.
+**
+**	This option should not affect performances 
+**	significantly, so it is the default.
+*/
+#if	SCSI_NCR_PCIQ_WORK_AROUND_OPT == 1
+#define	SCSI_NCR_PCIQ_MAY_NOT_FLUSH_PW_UPSTREAM
+#define	SCSI_NCR_PCIQ_MAY_REORDER_WRITES
+#define	SCSI_NCR_PCIQ_MAY_MISS_COMPLETIONS
+
+/*
+**	Same as option 1, but also deal with 
+**	misconfigured interrupts.
+**
+**	- Edge triggerred instead of level sensitive.
+**	- No interrupt line connected.
+**	- IRQ number misconfigured.
+**	
+**	If no interrupt is delivered, the driver will 
+**	catch the interrupt conditions 10 times per 
+**	second. No need to say that this option is 
+**	not recommended.
+*/
+#elif	SCSI_NCR_PCIQ_WORK_AROUND_OPT == 2
+#define	SCSI_NCR_PCIQ_MAY_NOT_FLUSH_PW_UPSTREAM
+#define	SCSI_NCR_PCIQ_MAY_REORDER_WRITES
+#define	SCSI_NCR_PCIQ_MAY_MISS_COMPLETIONS
+#define	SCSI_NCR_PCIQ_BROKEN_INTR
+
+/*
+**	Some bridge designers decided to flush 
+**	everything prior to deliver the interrupt.
+**	This option tries to deal with such a 
+**	behaviour.
+*/
+#elif	SCSI_NCR_PCIQ_WORK_AROUND_OPT == 3
+#define	SCSI_NCR_PCIQ_SYNC_ON_INTR
+#endif
+
+/*
+**	Other parameters not configurable with "make config"
+**	Avoid to change these constants, unless you know what you are doing.
+*/
+
+#define SCSI_NCR_ALWAYS_SIMPLE_TAG
+#define SCSI_NCR_MAX_SCATTER	(127)
+#define SCSI_NCR_MAX_TARGET	(16)
+
+/*
+**   Compute some desirable value for CAN_QUEUE 
+**   and CMD_PER_LUN.
+**   The driver will use lower values if these 
+**   ones appear to be too large.
+*/
+#define SCSI_NCR_CAN_QUEUE	(8*SCSI_NCR_MAX_TAGS + 2*SCSI_NCR_MAX_TARGET)
+#define SCSI_NCR_CMD_PER_LUN	(SCSI_NCR_MAX_TAGS)
+
+#define SCSI_NCR_SG_TABLESIZE	(SCSI_NCR_MAX_SCATTER)
+#define SCSI_NCR_TIMER_INTERVAL	(HZ)
+
+#if 1 /* defined CONFIG_SCSI_MULTI_LUN */
+#define SCSI_NCR_MAX_LUN	(16)
+#else
+#define SCSI_NCR_MAX_LUN	(1)
+#endif
+
+/*
+ *  IO functions definition for big/little endian CPU support.
+ *  For now, the NCR is only supported in little endian addressing mode, 
+ */
+
+#ifdef	__BIG_ENDIAN
+
+#define	inw_l2b		inw
+#define	inl_l2b		inl
+#define	outw_b2l	outw
+#define	outl_b2l	outl
+
+#define	readb_raw	readb
+#define	writeb_raw	writeb
+
+#if defined(SCSI_NCR_BIG_ENDIAN)
+#define	readw_l2b	__raw_readw
+#define	readl_l2b	__raw_readl
+#define	writew_b2l	__raw_writew
+#define	writel_b2l	__raw_writel
+#define	readw_raw	__raw_readw
+#define	readl_raw	__raw_readl
+#define	writew_raw	__raw_writew
+#define	writel_raw	__raw_writel
+#else	/* Other big-endian */
+#define	readw_l2b	readw
+#define	readl_l2b	readl
+#define	writew_b2l	writew
+#define	writel_b2l	writel
+#define	readw_raw	readw
+#define	readl_raw	readl
+#define	writew_raw	writew
+#define	writel_raw	writel
+#endif
+
+#else	/* little endian */
+
+#define	inw_raw		inw
+#define	inl_raw		inl
+#define	outw_raw	outw
+#define	outl_raw	outl
+
+#define	readb_raw	readb
+#define	readw_raw	readw
+#define	readl_raw	readl
+#define	writeb_raw	writeb
+#define	writew_raw	writew
+#define	writel_raw	writel
+
+#endif
+
+#if !defined(__hppa__) && !defined(__mips__)
+#ifdef	SCSI_NCR_BIG_ENDIAN
+#error	"The NCR in BIG ENDIAN addressing mode is not (yet) supported"
+#endif
+#endif
+
+#define MEMORY_BARRIER()	mb()
+
+
+/*
+ *  If the NCR uses big endian addressing mode over the 
+ *  PCI, actual io register addresses for byte and word 
+ *  accesses must be changed according to lane routing.
+ *  Btw, ncr_offb() and ncr_offw() macros only apply to 
+ *  constants and so donnot generate bloated code.
+ */
+
+#if	defined(SCSI_NCR_BIG_ENDIAN)
+
+#define ncr_offb(o)	(((o)&~3)+((~((o)&3))&3))
+#define ncr_offw(o)	(((o)&~3)+((~((o)&3))&2))
+
+#else
+
+#define ncr_offb(o)	(o)
+#define ncr_offw(o)	(o)
+
+#endif
+
+/*
+ *  If the CPU and the NCR use same endian-ness addressing,
+ *  no byte reordering is needed for script patching.
+ *  Macro cpu_to_scr() is to be used for script patching.
+ *  Macro scr_to_cpu() is to be used for getting a DWORD 
+ *  from the script.
+ */
+
+#if	defined(__BIG_ENDIAN) && !defined(SCSI_NCR_BIG_ENDIAN)
+
+#define cpu_to_scr(dw)	cpu_to_le32(dw)
+#define scr_to_cpu(dw)	le32_to_cpu(dw)
+
+#elif	defined(__LITTLE_ENDIAN) && defined(SCSI_NCR_BIG_ENDIAN)
+
+#define cpu_to_scr(dw)	cpu_to_be32(dw)
+#define scr_to_cpu(dw)	be32_to_cpu(dw)
+
+#else
+
+#define cpu_to_scr(dw)	(dw)
+#define scr_to_cpu(dw)	(dw)
+
+#endif
+
+/*
+ *  Access to the controller chip.
+ *
+ *  If the CPU and the NCR use same endian-ness addressing,
+ *  no byte reordering is needed for accessing chip io 
+ *  registers. Functions suffixed by '_raw' are assumed 
+ *  to access the chip over the PCI without doing byte 
+ *  reordering. Functions suffixed by '_l2b' are 
+ *  assumed to perform little-endian to big-endian byte 
+ *  reordering, those suffixed by '_b2l' blah, blah,
+ *  blah, ...
+ */
+
+/*
+ *  MEMORY mapped IO input / output
+ */
+
+#define INB_OFF(o)		readb_raw((char __iomem *)np->reg + ncr_offb(o))
+#define OUTB_OFF(o, val)	writeb_raw((val), (char __iomem *)np->reg + ncr_offb(o))
+
+#if	defined(__BIG_ENDIAN) && !defined(SCSI_NCR_BIG_ENDIAN)
+
+#define INW_OFF(o)		readw_l2b((char __iomem *)np->reg + ncr_offw(o))
+#define INL_OFF(o)		readl_l2b((char __iomem *)np->reg + (o))
+
+#define OUTW_OFF(o, val)	writew_b2l((val), (char __iomem *)np->reg + ncr_offw(o))
+#define OUTL_OFF(o, val)	writel_b2l((val), (char __iomem *)np->reg + (o))
+
+#elif	defined(__LITTLE_ENDIAN) && defined(SCSI_NCR_BIG_ENDIAN)
+
+#define INW_OFF(o)		readw_b2l((char __iomem *)np->reg + ncr_offw(o))
+#define INL_OFF(o)		readl_b2l((char __iomem *)np->reg + (o))
+
+#define OUTW_OFF(o, val)	writew_l2b((val), (char __iomem *)np->reg + ncr_offw(o))
+#define OUTL_OFF(o, val)	writel_l2b((val), (char __iomem *)np->reg + (o))
+
+#else
+
+#ifdef CONFIG_SCSI_NCR53C8XX_NO_WORD_TRANSFERS
+/* Only 8 or 32 bit transfers allowed */
+#define INW_OFF(o)		(readb((char __iomem *)np->reg + ncr_offw(o)) << 8 | readb((char __iomem *)np->reg + ncr_offw(o) + 1))
+#else
+#define INW_OFF(o)		readw_raw((char __iomem *)np->reg + ncr_offw(o))
+#endif
+#define INL_OFF(o)		readl_raw((char __iomem *)np->reg + (o))
+
+#ifdef CONFIG_SCSI_NCR53C8XX_NO_WORD_TRANSFERS
+/* Only 8 or 32 bit transfers allowed */
+#define OUTW_OFF(o, val)	do { writeb((char)((val) >> 8), (char __iomem *)np->reg + ncr_offw(o)); writeb((char)(val), (char __iomem *)np->reg + ncr_offw(o) + 1); } while (0)
+#else
+#define OUTW_OFF(o, val)	writew_raw((val), (char __iomem *)np->reg + ncr_offw(o))
+#endif
+#define OUTL_OFF(o, val)	writel_raw((val), (char __iomem *)np->reg + (o))
+
+#endif
+
+#define INB(r)		INB_OFF (offsetof(struct ncr_reg,r))
+#define INW(r)		INW_OFF (offsetof(struct ncr_reg,r))
+#define INL(r)		INL_OFF (offsetof(struct ncr_reg,r))
+
+#define OUTB(r, val)	OUTB_OFF (offsetof(struct ncr_reg,r), (val))
+#define OUTW(r, val)	OUTW_OFF (offsetof(struct ncr_reg,r), (val))
+#define OUTL(r, val)	OUTL_OFF (offsetof(struct ncr_reg,r), (val))
+
+/*
+ *  Set bit field ON, OFF 
+ */
+
+#define OUTONB(r, m)	OUTB(r, INB(r) | (m))
+#define OUTOFFB(r, m)	OUTB(r, INB(r) & ~(m))
+#define OUTONW(r, m)	OUTW(r, INW(r) | (m))
+#define OUTOFFW(r, m)	OUTW(r, INW(r) & ~(m))
+#define OUTONL(r, m)	OUTL(r, INL(r) | (m))
+#define OUTOFFL(r, m)	OUTL(r, INL(r) & ~(m))
+
+/*
+ *  We normally want the chip to have a consistent view
+ *  of driver internal data structures when we restart it.
+ *  Thus these macros.
+ */
+#define OUTL_DSP(v)				\
+	do {					\
+		MEMORY_BARRIER();		\
+		OUTL (nc_dsp, (v));		\
+	} while (0)
+
+#define OUTONB_STD()				\
+	do {					\
+		MEMORY_BARRIER();		\
+		OUTONB (nc_dcntl, (STD|NOCOM));	\
+	} while (0)
+
+
+/*
+**   NCR53C8XX devices features table.
+*/
+struct ncr_chip {
+	unsigned short	revision_id;
+	unsigned char	burst_max;	/* log-base-2 of max burst */
+	unsigned char	offset_max;
+	unsigned char	nr_divisor;
+	unsigned int	features;
+#define FE_LED0		(1<<0)
+#define FE_WIDE		(1<<1)    /* Wide data transfers */
+#define FE_ULTRA	(1<<2)	  /* Ultra speed 20Mtrans/sec */
+#define FE_DBLR		(1<<4)	  /* Clock doubler present */
+#define FE_QUAD		(1<<5)	  /* Clock quadrupler present */
+#define FE_ERL		(1<<6)    /* Enable read line */
+#define FE_CLSE		(1<<7)    /* Cache line size enable */
+#define FE_WRIE		(1<<8)    /* Write & Invalidate enable */
+#define FE_ERMP		(1<<9)    /* Enable read multiple */
+#define FE_BOF		(1<<10)   /* Burst opcode fetch */
+#define FE_DFS		(1<<11)   /* DMA fifo size */
+#define FE_PFEN		(1<<12)   /* Prefetch enable */
+#define FE_LDSTR	(1<<13)   /* Load/Store supported */
+#define FE_RAM		(1<<14)   /* On chip RAM present */
+#define FE_VARCLK	(1<<15)   /* SCSI clock may vary */
+#define FE_RAM8K	(1<<16)   /* On chip RAM sized 8Kb */
+#define FE_64BIT	(1<<17)   /* Have a 64-bit PCI interface */
+#define FE_IO256	(1<<18)   /* Requires full 256 bytes in PCI space */
+#define FE_NOPM		(1<<19)   /* Scripts handles phase mismatch */
+#define FE_LEDC		(1<<20)   /* Hardware control of LED */
+#define FE_DIFF		(1<<21)   /* Support Differential SCSI */
+#define FE_66MHZ 	(1<<23)   /* 66MHz PCI Support */
+#define FE_DAC	 	(1<<24)   /* Support DAC cycles (64 bit addressing) */
+#define FE_ISTAT1 	(1<<25)   /* Have ISTAT1, MBOX0, MBOX1 registers */
+#define FE_DAC_IN_USE	(1<<26)	  /* Platform does DAC cycles */
+#define FE_EHP		(1<<27)   /* 720: Even host parity */
+#define FE_MUX		(1<<28)   /* 720: Multiplexed bus */
+#define FE_EA		(1<<29)   /* 720: Enable Ack */
+
+#define FE_CACHE_SET	(FE_ERL|FE_CLSE|FE_WRIE|FE_ERMP)
+#define FE_SCSI_SET	(FE_WIDE|FE_ULTRA|FE_DBLR|FE_QUAD|F_CLK80)
+#define FE_SPECIAL_SET	(FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM)
+};
+
+
+/*
+**	Driver setup structure.
+**
+**	This structure is initialized from linux config options.
+**	It can be overridden at boot-up by the boot command line.
+*/
+#define SCSI_NCR_MAX_EXCLUDES 8
+struct ncr_driver_setup {
+	u8	master_parity;
+	u8	scsi_parity;
+	u8	disconnection;
+	u8	special_features;
+	u8	force_sync_nego;
+	u8	reverse_probe;
+	u8	pci_fix_up;
+	u8	use_nvram;
+	u8	verbose;
+	u8	default_tags;
+	u16	default_sync;
+	u16	debug;
+	u8	burst_max;
+	u8	led_pin;
+	u8	max_wide;
+	u8	settle_delay;
+	u8	diff_support;
+	u8	irqm;
+	u8	bus_check;
+	u8	optimize;
+	u8	recovery;
+	u8	host_id;
+	u16	iarb;
+	u32	excludes[SCSI_NCR_MAX_EXCLUDES];
+	char	tag_ctrl[100];
+};
+
+/*
+**	Initial setup.
+**	Can be overriden at startup by a command line.
+*/
+#define SCSI_NCR_DRIVER_SETUP			\
+{						\
+	SCSI_NCR_SETUP_MASTER_PARITY,		\
+	SCSI_NCR_SETUP_SCSI_PARITY,		\
+	SCSI_NCR_SETUP_DISCONNECTION,		\
+	SCSI_NCR_SETUP_SPECIAL_FEATURES,	\
+	SCSI_NCR_SETUP_FORCE_SYNC_NEGO,		\
+	0,					\
+	0,					\
+	1,					\
+	0,					\
+	SCSI_NCR_SETUP_DEFAULT_TAGS,		\
+	SCSI_NCR_SETUP_DEFAULT_SYNC,		\
+	0x00,					\
+	7,					\
+	0,					\
+	1,					\
+	SCSI_NCR_SETUP_SETTLE_TIME,		\
+	0,					\
+	0,					\
+	1,					\
+	0,					\
+	0,					\
+	255,					\
+	0x00					\
+}
+
+/*
+**	Boot fail safe setup.
+**	Override initial setup from boot command line:
+**	ncr53c8xx=safe:y
+*/
+#define SCSI_NCR_DRIVER_SAFE_SETUP		\
+{						\
+	0,					\
+	1,					\
+	0,					\
+	0,					\
+	0,					\
+	0,					\
+	0,					\
+	1,					\
+	2,					\
+	0,					\
+	255,					\
+	0x00,					\
+	255,					\
+	0,					\
+	0,					\
+	10,					\
+	1,					\
+	1,					\
+	1,					\
+	0,					\
+	0,					\
+	255					\
+}
+
+/**************** ORIGINAL CONTENT of ncrreg.h from FreeBSD ******************/
+
+/*-----------------------------------------------------------------
+**
+**	The ncr 53c810 register structure.
+**
+**-----------------------------------------------------------------
+*/
+
+struct ncr_reg {
+/*00*/  u8	nc_scntl0;    /* full arb., ena parity, par->ATN  */
+
+/*01*/  u8	nc_scntl1;    /* no reset                         */
+        #define   ISCON   0x10  /* connected to scsi		    */
+        #define   CRST    0x08  /* force reset                      */
+        #define   IARB    0x02  /* immediate arbitration            */
+
+/*02*/  u8	nc_scntl2;    /* no disconnect expected           */
+	#define   SDU     0x80  /* cmd: disconnect will raise error */
+	#define   CHM     0x40  /* sta: chained mode                */
+	#define   WSS     0x08  /* sta: wide scsi send           [W]*/
+	#define   WSR     0x01  /* sta: wide scsi received       [W]*/
+
+/*03*/  u8	nc_scntl3;    /* cnf system clock dependent       */
+	#define   EWS     0x08  /* cmd: enable wide scsi         [W]*/
+	#define   ULTRA   0x80  /* cmd: ULTRA enable                */
+				/* bits 0-2, 7 rsvd for C1010       */
+
+/*04*/  u8	nc_scid;	/* cnf host adapter scsi address    */
+	#define   RRE     0x40  /* r/w:e enable response to resel.  */
+	#define   SRE     0x20  /* r/w:e enable response to select  */
+
+/*05*/  u8	nc_sxfer;	/* ### Sync speed and count         */
+				/* bits 6-7 rsvd for C1010          */
+
+/*06*/  u8	nc_sdid;	/* ### Destination-ID               */
+
+/*07*/  u8	nc_gpreg;	/* ??? IO-Pins                      */
+
+/*08*/  u8	nc_sfbr;	/* ### First byte in phase          */
+
+/*09*/  u8	nc_socl;
+	#define   CREQ	  0x80	/* r/w: SCSI-REQ                    */
+	#define   CACK	  0x40	/* r/w: SCSI-ACK                    */
+	#define   CBSY	  0x20	/* r/w: SCSI-BSY                    */
+	#define   CSEL	  0x10	/* r/w: SCSI-SEL                    */
+	#define   CATN	  0x08	/* r/w: SCSI-ATN                    */
+	#define   CMSG	  0x04	/* r/w: SCSI-MSG                    */
+	#define   CC_D	  0x02	/* r/w: SCSI-C_D                    */
+	#define   CI_O	  0x01	/* r/w: SCSI-I_O                    */
+
+/*0a*/  u8	nc_ssid;
+
+/*0b*/  u8	nc_sbcl;
+
+/*0c*/  u8	nc_dstat;
+        #define   DFE     0x80  /* sta: dma fifo empty              */
+        #define   MDPE    0x40  /* int: master data parity error    */
+        #define   BF      0x20  /* int: script: bus fault           */
+        #define   ABRT    0x10  /* int: script: command aborted     */
+        #define   SSI     0x08  /* int: script: single step         */
+        #define   SIR     0x04  /* int: script: interrupt instruct. */
+        #define   IID     0x01  /* int: script: illegal instruct.   */
+
+/*0d*/  u8	nc_sstat0;
+        #define   ILF     0x80  /* sta: data in SIDL register lsb   */
+        #define   ORF     0x40  /* sta: data in SODR register lsb   */
+        #define   OLF     0x20  /* sta: data in SODL register lsb   */
+        #define   AIP     0x10  /* sta: arbitration in progress     */
+        #define   LOA     0x08  /* sta: arbitration lost            */
+        #define   WOA     0x04  /* sta: arbitration won             */
+        #define   IRST    0x02  /* sta: scsi reset signal           */
+        #define   SDP     0x01  /* sta: scsi parity signal          */
+
+/*0e*/  u8	nc_sstat1;
+	#define   FF3210  0xf0	/* sta: bytes in the scsi fifo      */
+
+/*0f*/  u8	nc_sstat2;
+        #define   ILF1    0x80  /* sta: data in SIDL register msb[W]*/
+        #define   ORF1    0x40  /* sta: data in SODR register msb[W]*/
+        #define   OLF1    0x20  /* sta: data in SODL register msb[W]*/
+        #define   DM      0x04  /* sta: DIFFSENS mismatch (895/6 only) */
+        #define   LDSC    0x02  /* sta: disconnect & reconnect      */
+
+/*10*/  u8	nc_dsa;	/* --> Base page                    */
+/*11*/  u8	nc_dsa1;
+/*12*/  u8	nc_dsa2;
+/*13*/  u8	nc_dsa3;
+
+/*14*/  u8	nc_istat;	/* --> Main Command and status      */
+        #define   CABRT   0x80  /* cmd: abort current operation     */
+        #define   SRST    0x40  /* mod: reset chip                  */
+        #define   SIGP    0x20  /* r/w: message from host to ncr    */
+        #define   SEM     0x10  /* r/w: message between host + ncr  */
+        #define   CON     0x08  /* sta: connected to scsi           */
+        #define   INTF    0x04  /* sta: int on the fly (reset by wr)*/
+        #define   SIP     0x02  /* sta: scsi-interrupt              */
+        #define   DIP     0x01  /* sta: host/script interrupt       */
+
+/*15*/  u8	nc_istat1;	/* 896 and later cores only */
+        #define   FLSH    0x04  /* sta: chip is flushing            */
+        #define   SRUN    0x02  /* sta: scripts are running         */
+        #define   SIRQD   0x01  /* r/w: disable INT pin             */
+
+/*16*/  u8	nc_mbox0;	/* 896 and later cores only */
+/*17*/  u8	nc_mbox1;	/* 896 and later cores only */
+
+/*18*/	u8	nc_ctest0;
+	#define   EHP     0x04	/* 720 even host parity             */
+/*19*/  u8	nc_ctest1;
+
+/*1a*/  u8	nc_ctest2;
+	#define   CSIGP   0x40
+				/* bits 0-2,7 rsvd for C1010        */
+
+/*1b*/  u8	nc_ctest3;
+	#define   FLF     0x08  /* cmd: flush dma fifo              */
+	#define   CLF	  0x04	/* cmd: clear dma fifo		    */
+	#define   FM      0x02  /* mod: fetch pin mode              */
+	#define   WRIE    0x01  /* mod: write and invalidate enable */
+				/* bits 4-7 rsvd for C1010          */
+
+/*1c*/  u32    nc_temp;	/* ### Temporary stack              */
+
+/*20*/	u8	nc_dfifo;
+/*21*/  u8	nc_ctest4;
+	#define   MUX     0x80  /* 720 host bus multiplex mode      */
+	#define   BDIS    0x80  /* mod: burst disable               */
+	#define   MPEE    0x08  /* mod: master parity error enable  */
+
+/*22*/  u8	nc_ctest5;
+	#define   DFS     0x20  /* mod: dma fifo size               */
+				/* bits 0-1, 3-7 rsvd for C1010          */
+/*23*/  u8	nc_ctest6;
+
+/*24*/  u32    nc_dbc;	/* ### Byte count and command       */
+/*28*/  u32    nc_dnad;	/* ### Next command register        */
+/*2c*/  u32    nc_dsp;	/* --> Script Pointer               */
+/*30*/  u32    nc_dsps;	/* --> Script pointer save/opcode#2 */
+
+/*34*/  u8	nc_scratcha;  /* Temporary register a            */
+/*35*/  u8	nc_scratcha1;
+/*36*/  u8	nc_scratcha2;
+/*37*/  u8	nc_scratcha3;
+
+/*38*/  u8	nc_dmode;
+	#define   BL_2    0x80  /* mod: burst length shift value +2 */
+	#define   BL_1    0x40  /* mod: burst length shift value +1 */
+	#define   ERL     0x08  /* mod: enable read line            */
+	#define   ERMP    0x04  /* mod: enable read multiple        */
+	#define   BOF     0x02  /* mod: burst op code fetch         */
+
+/*39*/  u8	nc_dien;
+/*3a*/  u8	nc_sbr;
+
+/*3b*/  u8	nc_dcntl;	/* --> Script execution control     */
+	#define   CLSE    0x80  /* mod: cache line size enable      */
+	#define   PFF     0x40  /* cmd: pre-fetch flush             */
+	#define   PFEN    0x20  /* mod: pre-fetch enable            */
+	#define   EA      0x20  /* mod: 720 enable-ack              */
+	#define   SSM     0x10  /* mod: single step mode            */
+	#define   IRQM    0x08  /* mod: irq mode (1 = totem pole !) */
+	#define   STD     0x04  /* cmd: start dma mode              */
+	#define   IRQD    0x02  /* mod: irq disable                 */
+ 	#define	  NOCOM   0x01	/* cmd: protect sfbr while reselect */
+				/* bits 0-1 rsvd for C1010          */
+
+/*3c*/  u32	nc_adder;
+
+/*40*/  u16	nc_sien;	/* -->: interrupt enable            */
+/*42*/  u16	nc_sist;	/* <--: interrupt status            */
+        #define   SBMC    0x1000/* sta: SCSI Bus Mode Change (895/6 only) */
+        #define   STO     0x0400/* sta: timeout (select)            */
+        #define   GEN     0x0200/* sta: timeout (general)           */
+        #define   HTH     0x0100/* sta: timeout (handshake)         */
+        #define   MA      0x80  /* sta: phase mismatch              */
+        #define   CMP     0x40  /* sta: arbitration complete        */
+        #define   SEL     0x20  /* sta: selected by another device  */
+        #define   RSL     0x10  /* sta: reselected by another device*/
+        #define   SGE     0x08  /* sta: gross error (over/underflow)*/
+        #define   UDC     0x04  /* sta: unexpected disconnect       */
+        #define   RST     0x02  /* sta: scsi bus reset detected     */
+        #define   PAR     0x01  /* sta: scsi parity error           */
+
+/*44*/  u8	nc_slpar;
+/*45*/  u8	nc_swide;
+/*46*/  u8	nc_macntl;
+/*47*/  u8	nc_gpcntl;
+/*48*/  u8	nc_stime0;    /* cmd: timeout for select&handshake*/
+/*49*/  u8	nc_stime1;    /* cmd: timeout user defined        */
+/*4a*/  u16   nc_respid;    /* sta: Reselect-IDs                */
+
+/*4c*/  u8	nc_stest0;
+
+/*4d*/  u8	nc_stest1;
+	#define   SCLK    0x80	/* Use the PCI clock as SCSI clock	*/
+	#define   DBLEN   0x08	/* clock doubler running		*/
+	#define   DBLSEL  0x04	/* clock doubler selected		*/
+  
+
+/*4e*/  u8	nc_stest2;
+	#define   ROF     0x40	/* reset scsi offset (after gross error!) */
+	#define   DIF     0x20  /* 720 SCSI differential mode             */
+	#define   EXT     0x02  /* extended filtering                     */
+
+/*4f*/  u8	nc_stest3;
+	#define   TE     0x80	/* c: tolerAnt enable */
+	#define   HSC    0x20	/* c: Halt SCSI Clock */
+	#define   CSF    0x02	/* c: clear scsi fifo */
+
+/*50*/  u16   nc_sidl;	/* Lowlevel: latched from scsi data */
+/*52*/  u8	nc_stest4;
+	#define   SMODE  0xc0	/* SCSI bus mode      (895/6 only) */
+	#define    SMODE_HVD 0x40	/* High Voltage Differential       */
+	#define    SMODE_SE  0x80	/* Single Ended                    */
+	#define    SMODE_LVD 0xc0	/* Low Voltage Differential        */
+	#define   LCKFRQ 0x20	/* Frequency Lock (895/6 only)     */
+				/* bits 0-5 rsvd for C1010          */
+
+/*53*/  u8	nc_53_;
+/*54*/  u16	nc_sodl;	/* Lowlevel: data out to scsi data  */
+/*56*/	u8	nc_ccntl0;	/* Chip Control 0 (896)             */
+	#define   ENPMJ  0x80	/* Enable Phase Mismatch Jump       */
+	#define   PMJCTL 0x40	/* Phase Mismatch Jump Control      */
+	#define   ENNDJ  0x20	/* Enable Non Data PM Jump          */
+	#define   DISFC  0x10	/* Disable Auto FIFO Clear          */
+	#define   DILS   0x02	/* Disable Internal Load/Store      */
+	#define   DPR    0x01	/* Disable Pipe Req                 */
+
+/*57*/	u8	nc_ccntl1;	/* Chip Control 1 (896)             */
+	#define   ZMOD   0x80	/* High Impedance Mode              */
+	#define	  DIC	 0x10	/* Disable Internal Cycles	    */
+	#define   DDAC   0x08	/* Disable Dual Address Cycle       */
+	#define   XTIMOD 0x04	/* 64-bit Table Ind. Indexing Mode  */
+	#define   EXTIBMV 0x02	/* Enable 64-bit Table Ind. BMOV    */
+	#define   EXDBMV 0x01	/* Enable 64-bit Direct BMOV        */
+
+/*58*/  u16	nc_sbdl;	/* Lowlevel: data from scsi data    */
+/*5a*/  u16	nc_5a_;
+
+/*5c*/  u8	nc_scr0;	/* Working register B               */
+/*5d*/  u8	nc_scr1;	/*                                  */
+/*5e*/  u8	nc_scr2;	/*                                  */
+/*5f*/  u8	nc_scr3;	/*                                  */
+
+/*60*/  u8	nc_scrx[64];	/* Working register C-R             */
+/*a0*/	u32	nc_mmrs;	/* Memory Move Read Selector        */
+/*a4*/	u32	nc_mmws;	/* Memory Move Write Selector       */
+/*a8*/	u32	nc_sfs;		/* Script Fetch Selector            */
+/*ac*/	u32	nc_drs;		/* DSA Relative Selector            */
+/*b0*/	u32	nc_sbms;	/* Static Block Move Selector       */
+/*b4*/	u32	nc_dbms;	/* Dynamic Block Move Selector      */
+/*b8*/	u32	nc_dnad64;	/* DMA Next Address 64              */
+/*bc*/	u16	nc_scntl4;	/* C1010 only                       */
+	#define   U3EN   0x80	/* Enable Ultra 3                   */
+	#define   AIPEN	 0x40   /* Allow check upper byte lanes     */
+	#define   XCLKH_DT 0x08 /* Extra clock of data hold on DT
+					transfer edge	            */
+	#define   XCLKH_ST 0x04 /* Extra clock of data hold on ST
+					transfer edge	            */
+
+/*be*/  u8	nc_aipcntl0;	/* Epat Control 1 C1010 only        */
+/*bf*/  u8	nc_aipcntl1;	/* AIP Control C1010_66 Only        */
+
+/*c0*/	u32	nc_pmjad1;	/* Phase Mismatch Jump Address 1    */
+/*c4*/	u32	nc_pmjad2;	/* Phase Mismatch Jump Address 2    */
+/*c8*/	u8	nc_rbc;		/* Remaining Byte Count             */
+/*c9*/	u8	nc_rbc1;	/*                                  */
+/*ca*/	u8	nc_rbc2;	/*                                  */
+/*cb*/	u8	nc_rbc3;	/*                                  */
+
+/*cc*/	u8	nc_ua;		/* Updated Address                  */
+/*cd*/	u8	nc_ua1;		/*                                  */
+/*ce*/	u8	nc_ua2;		/*                                  */
+/*cf*/	u8	nc_ua3;		/*                                  */
+/*d0*/	u32	nc_esa;		/* Entry Storage Address            */
+/*d4*/	u8	nc_ia;		/* Instruction Address              */
+/*d5*/	u8	nc_ia1;
+/*d6*/	u8	nc_ia2;
+/*d7*/	u8	nc_ia3;
+/*d8*/	u32	nc_sbc;		/* SCSI Byte Count (3 bytes only)   */
+/*dc*/	u32	nc_csbc;	/* Cumulative SCSI Byte Count       */
+
+				/* Following for C1010 only         */
+/*e0*/  u16	nc_crcpad;	/* CRC Value                        */
+/*e2*/  u8	nc_crccntl0;	/* CRC control register             */
+	#define   SNDCRC  0x10	/* Send CRC Request                 */
+/*e3*/  u8	nc_crccntl1;	/* CRC control register             */
+/*e4*/  u32	nc_crcdata;	/* CRC data register                */ 
+/*e8*/  u32	nc_e8_;		/* rsvd 			    */
+/*ec*/  u32	nc_ec_;		/* rsvd 			    */
+/*f0*/  u16	nc_dfbc;	/* DMA FIFO byte count              */ 
+
+};
+
+/*-----------------------------------------------------------
+**
+**	Utility macros for the script.
+**
+**-----------------------------------------------------------
+*/
+
+#define REGJ(p,r) (offsetof(struct ncr_reg, p ## r))
+#define REG(r) REGJ (nc_, r)
+
+typedef u32 ncrcmd;
+
+/*-----------------------------------------------------------
+**
+**	SCSI phases
+**
+**	DT phases illegal for ncr driver.
+**
+**-----------------------------------------------------------
+*/
+
+#define	SCR_DATA_OUT	0x00000000
+#define	SCR_DATA_IN	0x01000000
+#define	SCR_COMMAND	0x02000000
+#define	SCR_STATUS	0x03000000
+#define SCR_DT_DATA_OUT	0x04000000
+#define SCR_DT_DATA_IN	0x05000000
+#define SCR_MSG_OUT	0x06000000
+#define SCR_MSG_IN      0x07000000
+
+#define SCR_ILG_OUT	0x04000000
+#define SCR_ILG_IN	0x05000000
+
+/*-----------------------------------------------------------
+**
+**	Data transfer via SCSI.
+**
+**-----------------------------------------------------------
+**
+**	MOVE_ABS (LEN)
+**	<<start address>>
+**
+**	MOVE_IND (LEN)
+**	<<dnad_offset>>
+**
+**	MOVE_TBL
+**	<<dnad_offset>>
+**
+**-----------------------------------------------------------
+*/
+
+#define OPC_MOVE          0x08000000
+
+#define SCR_MOVE_ABS(l) ((0x00000000 | OPC_MOVE) | (l))
+#define SCR_MOVE_IND(l) ((0x20000000 | OPC_MOVE) | (l))
+#define SCR_MOVE_TBL     (0x10000000 | OPC_MOVE)
+
+#define SCR_CHMOV_ABS(l) ((0x00000000) | (l))
+#define SCR_CHMOV_IND(l) ((0x20000000) | (l))
+#define SCR_CHMOV_TBL     (0x10000000)
+
+struct scr_tblmove {
+        u32  size;
+        u32  addr;
+};
+
+/*-----------------------------------------------------------
+**
+**	Selection
+**
+**-----------------------------------------------------------
+**
+**	SEL_ABS | SCR_ID (0..15)    [ | REL_JMP]
+**	<<alternate_address>>
+**
+**	SEL_TBL | << dnad_offset>>  [ | REL_JMP]
+**	<<alternate_address>>
+**
+**-----------------------------------------------------------
+*/
+
+#define	SCR_SEL_ABS	0x40000000
+#define	SCR_SEL_ABS_ATN	0x41000000
+#define	SCR_SEL_TBL	0x42000000
+#define	SCR_SEL_TBL_ATN	0x43000000
+
+
+#ifdef SCSI_NCR_BIG_ENDIAN
+struct scr_tblsel {
+        u8	sel_scntl3;
+        u8	sel_id;
+        u8	sel_sxfer;
+        u8	sel_scntl4;	
+};
+#else
+struct scr_tblsel {
+        u8	sel_scntl4;	
+        u8	sel_sxfer;
+        u8	sel_id;
+        u8	sel_scntl3;
+};
+#endif
+
+#define SCR_JMP_REL     0x04000000
+#define SCR_ID(id)	(((u32)(id)) << 16)
+
+/*-----------------------------------------------------------
+**
+**	Waiting for Disconnect or Reselect
+**
+**-----------------------------------------------------------
+**
+**	WAIT_DISC
+**	dummy: <<alternate_address>>
+**
+**	WAIT_RESEL
+**	<<alternate_address>>
+**
+**-----------------------------------------------------------
+*/
+
+#define	SCR_WAIT_DISC	0x48000000
+#define SCR_WAIT_RESEL  0x50000000
+
+/*-----------------------------------------------------------
+**
+**	Bit Set / Reset
+**
+**-----------------------------------------------------------
+**
+**	SET (flags {|.. })
+**
+**	CLR (flags {|.. })
+**
+**-----------------------------------------------------------
+*/
+
+#define SCR_SET(f)     (0x58000000 | (f))
+#define SCR_CLR(f)     (0x60000000 | (f))
+
+#define	SCR_CARRY	0x00000400
+#define	SCR_TRG		0x00000200
+#define	SCR_ACK		0x00000040
+#define	SCR_ATN		0x00000008
+
+
+
+
+/*-----------------------------------------------------------
+**
+**	Memory to memory move
+**
+**-----------------------------------------------------------
+**
+**	COPY (bytecount)
+**	<< source_address >>
+**	<< destination_address >>
+**
+**	SCR_COPY   sets the NO FLUSH option by default.
+**	SCR_COPY_F does not set this option.
+**
+**	For chips which do not support this option,
+**	ncr_copy_and_bind() will remove this bit.
+**-----------------------------------------------------------
+*/
+
+#define SCR_NO_FLUSH 0x01000000
+
+#define SCR_COPY(n) (0xc0000000 | SCR_NO_FLUSH | (n))
+#define SCR_COPY_F(n) (0xc0000000 | (n))
+
+/*-----------------------------------------------------------
+**
+**	Register move and binary operations
+**
+**-----------------------------------------------------------
+**
+**	SFBR_REG (reg, op, data)        reg  = SFBR op data
+**	<< 0 >>
+**
+**	REG_SFBR (reg, op, data)        SFBR = reg op data
+**	<< 0 >>
+**
+**	REG_REG  (reg, op, data)        reg  = reg op data
+**	<< 0 >>
+**
+**-----------------------------------------------------------
+**	On 810A, 860, 825A, 875, 895 and 896 chips the content 
+**	of SFBR register can be used as data (SCR_SFBR_DATA).
+**	The 896 has additionnal IO registers starting at 
+**	offset 0x80. Bit 7 of register offset is stored in 
+**	bit 7 of the SCRIPTS instruction first DWORD.
+**-----------------------------------------------------------
+*/
+
+#define SCR_REG_OFS(ofs) ((((ofs) & 0x7f) << 16ul) + ((ofs) & 0x80)) 
+
+#define SCR_SFBR_REG(reg,op,data) \
+        (0x68000000 | (SCR_REG_OFS(REG(reg))) | (op) | (((data)&0xff)<<8ul))
+
+#define SCR_REG_SFBR(reg,op,data) \
+        (0x70000000 | (SCR_REG_OFS(REG(reg))) | (op) | (((data)&0xff)<<8ul))
+
+#define SCR_REG_REG(reg,op,data) \
+        (0x78000000 | (SCR_REG_OFS(REG(reg))) | (op) | (((data)&0xff)<<8ul))
+
+
+#define      SCR_LOAD   0x00000000
+#define      SCR_SHL    0x01000000
+#define      SCR_OR     0x02000000
+#define      SCR_XOR    0x03000000
+#define      SCR_AND    0x04000000
+#define      SCR_SHR    0x05000000
+#define      SCR_ADD    0x06000000
+#define      SCR_ADDC   0x07000000
+
+#define      SCR_SFBR_DATA   (0x00800000>>8ul)	/* Use SFBR as data */
+
+/*-----------------------------------------------------------
+**
+**	FROM_REG (reg)		  SFBR = reg
+**	<< 0 >>
+**
+**	TO_REG	 (reg)		  reg  = SFBR
+**	<< 0 >>
+**
+**	LOAD_REG (reg, data)	  reg  = <data>
+**	<< 0 >>
+**
+**	LOAD_SFBR(data) 	  SFBR = <data>
+**	<< 0 >>
+**
+**-----------------------------------------------------------
+*/
+
+#define	SCR_FROM_REG(reg) \
+	SCR_REG_SFBR(reg,SCR_OR,0)
+
+#define	SCR_TO_REG(reg) \
+	SCR_SFBR_REG(reg,SCR_OR,0)
+
+#define	SCR_LOAD_REG(reg,data) \
+	SCR_REG_REG(reg,SCR_LOAD,data)
+
+#define SCR_LOAD_SFBR(data) \
+        (SCR_REG_SFBR (gpreg, SCR_LOAD, data))
+
+/*-----------------------------------------------------------
+**
+**	LOAD  from memory   to register.
+**	STORE from register to memory.
+**
+**	Only supported by 810A, 860, 825A, 875, 895 and 896.
+**
+**-----------------------------------------------------------
+**
+**	LOAD_ABS (LEN)
+**	<<start address>>
+**
+**	LOAD_REL (LEN)        (DSA relative)
+**	<<dsa_offset>>
+**
+**-----------------------------------------------------------
+*/
+
+#define SCR_REG_OFS2(ofs) (((ofs) & 0xff) << 16ul)
+#define SCR_NO_FLUSH2	0x02000000
+#define SCR_DSA_REL2	0x10000000
+
+#define SCR_LOAD_R(reg, how, n) \
+        (0xe1000000 | how | (SCR_REG_OFS2(REG(reg))) | (n))
+
+#define SCR_STORE_R(reg, how, n) \
+        (0xe0000000 | how | (SCR_REG_OFS2(REG(reg))) | (n))
+
+#define SCR_LOAD_ABS(reg, n)	SCR_LOAD_R(reg, SCR_NO_FLUSH2, n)
+#define SCR_LOAD_REL(reg, n)	SCR_LOAD_R(reg, SCR_NO_FLUSH2|SCR_DSA_REL2, n)
+#define SCR_LOAD_ABS_F(reg, n)	SCR_LOAD_R(reg, 0, n)
+#define SCR_LOAD_REL_F(reg, n)	SCR_LOAD_R(reg, SCR_DSA_REL2, n)
+
+#define SCR_STORE_ABS(reg, n)	SCR_STORE_R(reg, SCR_NO_FLUSH2, n)
+#define SCR_STORE_REL(reg, n)	SCR_STORE_R(reg, SCR_NO_FLUSH2|SCR_DSA_REL2,n)
+#define SCR_STORE_ABS_F(reg, n)	SCR_STORE_R(reg, 0, n)
+#define SCR_STORE_REL_F(reg, n)	SCR_STORE_R(reg, SCR_DSA_REL2, n)
+
+
+/*-----------------------------------------------------------
+**
+**	Waiting for Disconnect or Reselect
+**
+**-----------------------------------------------------------
+**
+**	JUMP            [ | IFTRUE/IFFALSE ( ... ) ]
+**	<<address>>
+**
+**	JUMPR           [ | IFTRUE/IFFALSE ( ... ) ]
+**	<<distance>>
+**
+**	CALL            [ | IFTRUE/IFFALSE ( ... ) ]
+**	<<address>>
+**
+**	CALLR           [ | IFTRUE/IFFALSE ( ... ) ]
+**	<<distance>>
+**
+**	RETURN          [ | IFTRUE/IFFALSE ( ... ) ]
+**	<<dummy>>
+**
+**	INT             [ | IFTRUE/IFFALSE ( ... ) ]
+**	<<ident>>
+**
+**	INT_FLY         [ | IFTRUE/IFFALSE ( ... ) ]
+**	<<ident>>
+**
+**	Conditions:
+**	     WHEN (phase)
+**	     IF   (phase)
+**	     CARRYSET
+**	     DATA (data, mask)
+**
+**-----------------------------------------------------------
+*/
+
+#define SCR_NO_OP       0x80000000
+#define SCR_JUMP        0x80080000
+#define SCR_JUMP64      0x80480000
+#define SCR_JUMPR       0x80880000
+#define SCR_CALL        0x88080000
+#define SCR_CALLR       0x88880000
+#define SCR_RETURN      0x90080000
+#define SCR_INT         0x98080000
+#define SCR_INT_FLY     0x98180000
+
+#define IFFALSE(arg)   (0x00080000 | (arg))
+#define IFTRUE(arg)    (0x00000000 | (arg))
+
+#define WHEN(phase)    (0x00030000 | (phase))
+#define IF(phase)      (0x00020000 | (phase))
+
+#define DATA(D)        (0x00040000 | ((D) & 0xff))
+#define MASK(D,M)      (0x00040000 | (((M ^ 0xff) & 0xff) << 8ul)|((D) & 0xff))
+
+#define CARRYSET       (0x00200000)
+
+/*-----------------------------------------------------------
+**
+**	SCSI  constants.
+**
+**-----------------------------------------------------------
+*/
+
+/*
+**	Messages
+*/
+
+#define	M_COMPLETE	COMMAND_COMPLETE
+#define	M_EXTENDED	EXTENDED_MESSAGE
+#define	M_SAVE_DP	SAVE_POINTERS
+#define	M_RESTORE_DP	RESTORE_POINTERS
+#define	M_DISCONNECT	DISCONNECT
+#define	M_ID_ERROR	INITIATOR_ERROR
+#define	M_ABORT		ABORT_TASK_SET
+#define	M_REJECT	MESSAGE_REJECT
+#define	M_NOOP		NOP
+#define	M_PARITY	MSG_PARITY_ERROR
+#define	M_LCOMPLETE	LINKED_CMD_COMPLETE
+#define	M_FCOMPLETE	LINKED_FLG_CMD_COMPLETE
+#define	M_RESET		TARGET_RESET
+#define	M_ABORT_TAG	ABORT_TASK
+#define	M_CLEAR_QUEUE	CLEAR_TASK_SET
+#define	M_INIT_REC	INITIATE_RECOVERY
+#define	M_REL_REC	RELEASE_RECOVERY
+#define	M_TERMINATE	(0x11)
+#define	M_SIMPLE_TAG	SIMPLE_QUEUE_TAG
+#define	M_HEAD_TAG	HEAD_OF_QUEUE_TAG
+#define	M_ORDERED_TAG	ORDERED_QUEUE_TAG
+#define	M_IGN_RESIDUE	IGNORE_WIDE_RESIDUE
+#define	M_IDENTIFY   	(0x80)
+
+#define	M_X_MODIFY_DP	EXTENDED_MODIFY_DATA_POINTER
+#define	M_X_SYNC_REQ	EXTENDED_SDTR
+#define	M_X_WIDE_REQ	EXTENDED_WDTR
+#define	M_X_PPR_REQ	EXTENDED_PPR
+
+/*
+**	Status
+*/
+
+#define	S_GOOD		(0x00)
+#define	S_CHECK_COND	(0x02)
+#define	S_COND_MET	(0x04)
+#define	S_BUSY		(0x08)
+#define	S_INT		(0x10)
+#define	S_INT_COND_MET	(0x14)
+#define	S_CONFLICT	(0x18)
+#define	S_TERMINATED	(0x20)
+#define	S_QUEUE_FULL	(0x28)
+#define	S_ILLEGAL	(0xff)
+#define	S_SENSE		(0x80)
+
+/*
+ * End of ncrreg from FreeBSD
+ */
 
 /*
 	Build a scatter/gather entry.
diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c
index 7c5306499832..0c9edb7051f4 100644
--- a/drivers/scsi/pcmcia/aha152x_stub.c
+++ b/drivers/scsi/pcmcia/aha152x_stub.c
@@ -95,27 +95,21 @@ typedef struct scsi_info_t {
 } scsi_info_t;
 
 static void aha152x_release_cs(dev_link_t *link);
-static int aha152x_event(event_t event, int priority,
-			 event_callback_args_t *args);
-
-static dev_link_t *aha152x_attach(void);
-static void aha152x_detach(dev_link_t *);
+static void aha152x_detach(struct pcmcia_device *p_dev);
+static void aha152x_config_cs(dev_link_t *link);
 
 static dev_link_t *dev_list;
-static dev_info_t dev_info = "aha152x_cs";
 
-static dev_link_t *aha152x_attach(void)
+static int aha152x_attach(struct pcmcia_device *p_dev)
 {
     scsi_info_t *info;
-    client_reg_t client_reg;
     dev_link_t *link;
-    int ret;
     
     DEBUG(0, "aha152x_attach()\n");
 
     /* Create new SCSI device */
     info = kmalloc(sizeof(*info), GFP_KERNEL);
-    if (!info) return NULL;
+    if (!info) return -ENOMEM;
     memset(info, 0, sizeof(*info));
     link = &info->link; link->priv = info;
 
@@ -129,26 +123,20 @@ static dev_link_t *aha152x_attach(void)
     link->conf.IntType = INT_MEMORY_AND_IO;
     link->conf.Present = PRESENT_OPTION;
 
-    /* Register with Card Services */
-    link->next = dev_list;
-    dev_list = link;
-    client_reg.dev_info = &dev_info;
-    client_reg.Version = 0x0210;
-    client_reg.event_callback_args.client_data = link;
-    ret = pcmcia_register_client(&link->handle, &client_reg);
-    if (ret != 0) {
-	cs_error(link->handle, RegisterClient, ret);
-	aha152x_detach(link);
-	return NULL;
-    }
-    
-    return link;
+    link->handle = p_dev;
+    p_dev->instance = link;
+
+    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+    aha152x_config_cs(link);
+
+    return 0;
 } /* aha152x_attach */
 
 /*====================================================================*/
 
-static void aha152x_detach(dev_link_t *link)
+static void aha152x_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     dev_link_t **linkp;
 
     DEBUG(0, "aha152x_detach(0x%p)\n", link);
@@ -162,9 +150,6 @@ static void aha152x_detach(dev_link_t *link)
     if (link->state & DEV_CONFIG)
 	aha152x_release_cs(link);
 
-    if (link->handle)
-	pcmcia_deregister_client(link->handle);
-    
     /* Unlink device structure, free bits */
     *linkp = link->next;
     kfree(link->priv);
@@ -272,44 +257,31 @@ static void aha152x_release_cs(dev_link_t *link)
 	link->state &= ~DEV_CONFIG;
 }
 
-static int aha152x_event(event_t event, int priority,
-			 event_callback_args_t *args)
+static int aha152x_suspend(struct pcmcia_device *dev)
 {
-    dev_link_t *link = args->client_data;
-    scsi_info_t *info = link->priv;
-    
-    DEBUG(0, "aha152x_event(0x%06x)\n", event);
-    
-    switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-	link->state &= ~DEV_PRESENT;
-	if (link->state & DEV_CONFIG)
-	    aha152x_release_cs(link);
-	break;
-    case CS_EVENT_CARD_INSERTION:
-	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-	aha152x_config_cs(link);
-	break;
-    case CS_EVENT_PM_SUSPEND:
+	dev_link_t *link = dev_to_instance(dev);
+
 	link->state |= DEV_SUSPEND;
-	/* Fall through... */
-    case CS_EVENT_RESET_PHYSICAL:
 	if (link->state & DEV_CONFIG)
-	    pcmcia_release_configuration(link->handle);
-	break;
-    case CS_EVENT_PM_RESUME:
+		pcmcia_release_configuration(link->handle);
+
+	return 0;
+}
+
+static int aha152x_resume(struct pcmcia_device *dev)
+{
+	dev_link_t *link = dev_to_instance(dev);
+	scsi_info_t *info = link->priv;
+
 	link->state &= ~DEV_SUSPEND;
-	/* Fall through... */
-    case CS_EVENT_CARD_RESET:
 	if (link->state & DEV_CONFIG) {
-	    Scsi_Cmnd tmp;
-	    pcmcia_request_configuration(link->handle, &link->conf);
-	    tmp.device->host = info->host;
-	    aha152x_host_reset(&tmp);
+		Scsi_Cmnd tmp;
+		pcmcia_request_configuration(link->handle, &link->conf);
+		tmp.device->host = info->host;
+		aha152x_host_reset(&tmp);
 	}
-	break;
-    }
-    return 0;
+
+	return 0;
 }
 
 static struct pcmcia_device_id aha152x_ids[] = {
@@ -327,10 +299,11 @@ static struct pcmcia_driver aha152x_cs_driver = {
 	.drv		= {
 		.name	= "aha152x_cs",
 	},
-	.attach		= aha152x_attach,
-	.event		= aha152x_event,
-	.detach		= aha152x_detach,
+	.probe		= aha152x_attach,
+	.remove		= aha152x_detach,
 	.id_table       = aha152x_ids,
+	.suspend	= aha152x_suspend,
+	.resume		= aha152x_resume,
 };
 
 static int __init init_aha152x_cs(void)
diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c
index db8f5cd85ffe..788c58d805f3 100644
--- a/drivers/scsi/pcmcia/fdomain_stub.c
+++ b/drivers/scsi/pcmcia/fdomain_stub.c
@@ -80,29 +80,19 @@ typedef struct scsi_info_t {
 
 
 static void fdomain_release(dev_link_t *link);
-static int fdomain_event(event_t event, int priority,
-			event_callback_args_t *args);
+static void fdomain_detach(struct pcmcia_device *p_dev);
+static void fdomain_config(dev_link_t *link);
 
-static dev_link_t *fdomain_attach(void);
-static void fdomain_detach(dev_link_t *);
-
-
-static dev_link_t *dev_list = NULL;
-
-static dev_info_t dev_info = "fdomain_cs";
-
-static dev_link_t *fdomain_attach(void)
+static int fdomain_attach(struct pcmcia_device *p_dev)
 {
     scsi_info_t *info;
-    client_reg_t client_reg;
     dev_link_t *link;
-    int ret;
-    
+
     DEBUG(0, "fdomain_attach()\n");
 
     /* Create new SCSI device */
     info = kmalloc(sizeof(*info), GFP_KERNEL);
-    if (!info) return NULL;
+    if (!info) return -ENOMEM;
     memset(info, 0, sizeof(*info));
     link = &info->link; link->priv = info;
     link->io.NumPorts1 = 0x10;
@@ -115,46 +105,27 @@ static dev_link_t *fdomain_attach(void)
     link->conf.IntType = INT_MEMORY_AND_IO;
     link->conf.Present = PRESENT_OPTION;
 
-    /* Register with Card Services */
-    link->next = dev_list;
-    dev_list = link;
-    client_reg.dev_info = &dev_info;
-    client_reg.Version = 0x0210;
-    client_reg.event_callback_args.client_data = link;
-    ret = pcmcia_register_client(&link->handle, &client_reg);
-    if (ret != 0) {
-	cs_error(link->handle, RegisterClient, ret);
-	fdomain_detach(link);
-	return NULL;
-    }
-    
-    return link;
+    link->handle = p_dev;
+    p_dev->instance = link;
+
+    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+    fdomain_config(link);
+
+    return 0;
 } /* fdomain_attach */
 
 /*====================================================================*/
 
-static void fdomain_detach(dev_link_t *link)
+static void fdomain_detach(struct pcmcia_device *p_dev)
 {
-    dev_link_t **linkp;
+	dev_link_t *link = dev_to_instance(p_dev);
 
-    DEBUG(0, "fdomain_detach(0x%p)\n", link);
-    
-    /* Locate device structure */
-    for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
-	if (*linkp == link) break;
-    if (*linkp == NULL)
-	return;
+	DEBUG(0, "fdomain_detach(0x%p)\n", link);
 
-    if (link->state & DEV_CONFIG)
-	fdomain_release(link);
+	if (link->state & DEV_CONFIG)
+		fdomain_release(link);
 
-    if (link->handle)
-	pcmcia_deregister_client(link->handle);
-    
-    /* Unlink device structure, free bits */
-    *linkp = link->next;
-    kfree(link->priv);
-    
+	kfree(link->priv);
 } /* fdomain_detach */
 
 /*====================================================================*/
@@ -256,43 +227,29 @@ static void fdomain_release(dev_link_t *link)
 
 /*====================================================================*/
 
-static int fdomain_event(event_t event, int priority,
-			event_callback_args_t *args)
+static int fdomain_suspend(struct pcmcia_device *dev)
 {
-    dev_link_t *link = args->client_data;
+	dev_link_t *link = dev_to_instance(dev);
 
-    DEBUG(1, "fdomain_event(0x%06x)\n", event);
-    
-    switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-	link->state &= ~DEV_PRESENT;
-	if (link->state & DEV_CONFIG)
-	    fdomain_release(link);
-	break;
-    case CS_EVENT_CARD_INSERTION:
-	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-	fdomain_config(link);
-	break;
-    case CS_EVENT_PM_SUSPEND:
 	link->state |= DEV_SUSPEND;
-	/* Fall through... */
-    case CS_EVENT_RESET_PHYSICAL:
 	if (link->state & DEV_CONFIG)
-	    pcmcia_release_configuration(link->handle);
-	break;
-    case CS_EVENT_PM_RESUME:
+		pcmcia_release_configuration(link->handle);
+
+	return 0;
+}
+
+static int fdomain_resume(struct pcmcia_device *dev)
+{
+	dev_link_t *link = dev_to_instance(dev);
+
 	link->state &= ~DEV_SUSPEND;
-	/* Fall through... */
-    case CS_EVENT_CARD_RESET:
 	if (link->state & DEV_CONFIG) {
-	    pcmcia_request_configuration(link->handle, &link->conf);
-	    fdomain_16x0_bus_reset(NULL);
+		pcmcia_request_configuration(link->handle, &link->conf);
+		fdomain_16x0_bus_reset(NULL);
 	}
-	break;
-    }
-    return 0;
-} /* fdomain_event */
 
+	return 0;
+}
 
 static struct pcmcia_device_id fdomain_ids[] = {
 	PCMCIA_DEVICE_PROD_ID12("IBM Corp.", "SCSI PCMCIA Card", 0xe3736c88, 0x859cad20),
@@ -307,10 +264,11 @@ static struct pcmcia_driver fdomain_cs_driver = {
 	.drv		= {
 		.name	= "fdomain_cs",
 	},
-	.attach		= fdomain_attach,
-	.event		= fdomain_event,
-	.detach		= fdomain_detach,
+	.probe		= fdomain_attach,
+	.remove		= fdomain_detach,
 	.id_table       = fdomain_ids,
+	.suspend	= fdomain_suspend,
+	.resume		= fdomain_resume,
 };
 
 static int __init init_fdomain_cs(void)
@@ -321,7 +279,6 @@ static int __init init_fdomain_cs(void)
 static void __exit exit_fdomain_cs(void)
 {
 	pcmcia_unregister_driver(&fdomain_cs_driver);
-	BUG_ON(dev_list != NULL);
 }
 
 module_init(init_fdomain_cs);
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
index 050ea13ff80b..9e3ab3fd5355 100644
--- a/drivers/scsi/pcmcia/nsp_cs.c
+++ b/drivers/scsi/pcmcia/nsp_cs.c
@@ -104,9 +104,6 @@ static struct scsi_host_template nsp_driver_template = {
 #endif
 };
 
-static dev_link_t *dev_list = NULL;
-static dev_info_t dev_info  = {"nsp_cs"};
-
 static nsp_hw_data nsp_data_base; /* attach <-> detect glue */
 
 
@@ -1596,19 +1593,17 @@ static int nsp_eh_host_reset(Scsi_Cmnd *SCpnt)
     configure the card at this point -- we wait until we receive a
     card insertion event.
 ======================================================================*/
-static dev_link_t *nsp_cs_attach(void)
+static int nsp_cs_attach(struct pcmcia_device *p_dev)
 {
 	scsi_info_t  *info;
-	client_reg_t  client_reg;
 	dev_link_t   *link;
-	int	      ret;
 	nsp_hw_data  *data = &nsp_data_base;
 
 	nsp_dbg(NSP_DEBUG_INIT, "in");
 
 	/* Create new SCSI device */
 	info = kmalloc(sizeof(*info), GFP_KERNEL);
-	if (info == NULL) { return NULL; }
+	if (info == NULL) { return -ENOMEM; }
 	memset(info, 0, sizeof(*info));
 	link = &info->link;
 	link->priv = info;
@@ -1636,23 +1631,14 @@ static dev_link_t *nsp_cs_attach(void)
 	link->conf.IntType	 = INT_MEMORY_AND_IO;
 	link->conf.Present	 = PRESENT_OPTION;
 
+	link->handle = p_dev;
+	p_dev->instance = link;
 
-	/* Register with Card Services */
-	link->next               = dev_list;
-	dev_list                 = link;
-	client_reg.dev_info	 = &dev_info;
-	client_reg.Version	 = 0x0210;
-	client_reg.event_callback_args.client_data = link;
-	ret = pcmcia_register_client(&link->handle, &client_reg);
-	if (ret != CS_SUCCESS) {
-		cs_error(link->handle, RegisterClient, ret);
-		nsp_cs_detach(link);
-		return NULL;
-	}
-
+	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+	nsp_cs_config(link);
 
 	nsp_dbg(NSP_DEBUG_INIT, "link=0x%p", link);
-	return link;
+	return 0;
 } /* nsp_cs_attach */
 
 
@@ -1662,35 +1648,19 @@ static dev_link_t *nsp_cs_attach(void)
     structures are freed.  Otherwise, the structures will be freed
     when the device is released.
 ======================================================================*/
-static void nsp_cs_detach(dev_link_t *link)
+static void nsp_cs_detach(struct pcmcia_device *p_dev)
 {
-	dev_link_t **linkp;
+	dev_link_t *link = dev_to_instance(p_dev);
 
 	nsp_dbg(NSP_DEBUG_INIT, "in, link=0x%p", link);
 
-	/* Locate device structure */
-	for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) {
-		if (*linkp == link) {
-			break;
-		}
-	}
-	if (*linkp == NULL) {
-		return;
-	}
-
-	if (link->state & DEV_CONFIG)
+	if (link->state & DEV_CONFIG) {
+		((scsi_info_t *)link->priv)->stop = 1;
 		nsp_cs_release(link);
-
-	/* Break the link with Card Services */
-	if (link->handle) {
-		pcmcia_deregister_client(link->handle);
 	}
 
-	/* Unlink device structure, free bits */
-	*linkp = link->next;
 	kfree(link->priv);
 	link->priv = NULL;
-
 } /* nsp_cs_detach */
 
 
@@ -2021,99 +1991,58 @@ static void nsp_cs_release(dev_link_t *link)
 #endif
 } /* nsp_cs_release */
 
-/*======================================================================
-
-    The card status event handler.  Mostly, this schedules other
-    stuff to run after an event is received.  A CARD_REMOVAL event
-    also sets some flags to discourage the net drivers from trying
-    to talk to the card any more.
-
-    When a CARD_REMOVAL event is received, we immediately set a flag
-    to block future accesses to this device.  All the functions that
-    actually access the device should check this flag to make sure
-    the card is still present.
-
-======================================================================*/
-static int nsp_cs_event(event_t		       event,
-			int		       priority,
-			event_callback_args_t *args)
+static int nsp_cs_suspend(struct pcmcia_device *dev)
 {
-	dev_link_t  *link = args->client_data;
+	dev_link_t *link = dev_to_instance(dev);
 	scsi_info_t *info = link->priv;
 	nsp_hw_data *data;
 
-	nsp_dbg(NSP_DEBUG_INIT, "in, event=0x%08x", event);
+	link->state |= DEV_SUSPEND;
 
-	switch (event) {
-	case CS_EVENT_CARD_REMOVAL:
-		nsp_dbg(NSP_DEBUG_INIT, "event: remove");
-		link->state &= ~DEV_PRESENT;
-		if (link->state & DEV_CONFIG) {
-			((scsi_info_t *)link->priv)->stop = 1;
-			nsp_cs_release(link);
-		}
-		break;
+	nsp_dbg(NSP_DEBUG_INIT, "event: suspend");
 
-	case CS_EVENT_CARD_INSERTION:
-		nsp_dbg(NSP_DEBUG_INIT, "event: insert");
-		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,68))
-		info->bus    =  args->bus;
-#endif
-		nsp_cs_config(link);
-		break;
+	if (info->host != NULL) {
+		nsp_msg(KERN_INFO, "clear SDTR status");
 
-	case CS_EVENT_PM_SUSPEND:
-		nsp_dbg(NSP_DEBUG_INIT, "event: suspend");
-		link->state |= DEV_SUSPEND;
-		/* Fall through... */
-	case CS_EVENT_RESET_PHYSICAL:
-		/* Mark the device as stopped, to block IO until later */
-		nsp_dbg(NSP_DEBUG_INIT, "event: reset physical");
+		data = (nsp_hw_data *)info->host->hostdata;
 
-		if (info->host != NULL) {
-			nsp_msg(KERN_INFO, "clear SDTR status");
+		nsphw_init_sync(data);
+	}
 
-			data = (nsp_hw_data *)info->host->hostdata;
+	info->stop = 1;
 
-			nsphw_init_sync(data);
-		}
+	if (link->state & DEV_CONFIG)
+		pcmcia_release_configuration(link->handle);
 
-		info->stop = 1;
-		if (link->state & DEV_CONFIG) {
-			pcmcia_release_configuration(link->handle);
-		}
-		break;
+	return 0;
+}
 
-	case CS_EVENT_PM_RESUME:
-		nsp_dbg(NSP_DEBUG_INIT, "event: resume");
-		link->state &= ~DEV_SUSPEND;
-		/* Fall through... */
-	case CS_EVENT_CARD_RESET:
-		nsp_dbg(NSP_DEBUG_INIT, "event: reset");
-		if (link->state & DEV_CONFIG) {
-			pcmcia_request_configuration(link->handle, &link->conf);
-		}
-		info->stop = 0;
+static int nsp_cs_resume(struct pcmcia_device *dev)
+{
+	dev_link_t *link = dev_to_instance(dev);
+	scsi_info_t *info = link->priv;
+	nsp_hw_data *data;
 
-		if (info->host != NULL) {
-			nsp_msg(KERN_INFO, "reset host and bus");
+	nsp_dbg(NSP_DEBUG_INIT, "event: resume");
 
-			data = (nsp_hw_data *)info->host->hostdata;
+	link->state &= ~DEV_SUSPEND;
 
-			nsphw_init   (data);
-			nsp_bus_reset(data);
-		}
+	if (link->state & DEV_CONFIG)
+		pcmcia_request_configuration(link->handle, &link->conf);
 
-		break;
+	info->stop = 0;
 
-	default:
-		nsp_dbg(NSP_DEBUG_INIT, "event: unknown");
-		break;
+	if (info->host != NULL) {
+		nsp_msg(KERN_INFO, "reset host and bus");
+
+		data = (nsp_hw_data *)info->host->hostdata;
+
+		nsphw_init   (data);
+		nsp_bus_reset(data);
 	}
-	nsp_dbg(NSP_DEBUG_INIT, "end");
+
 	return 0;
-} /* nsp_cs_event */
+}
 
 /*======================================================================*
  *	module entry point
@@ -2136,10 +2065,11 @@ static struct pcmcia_driver nsp_driver = {
 	.drv		= {
 		.name	= "nsp_cs",
 	},
-	.attach		= nsp_cs_attach,
-	.event		= nsp_cs_event,
-	.detach		= nsp_cs_detach,
+	.probe		= nsp_cs_attach,
+	.remove		= nsp_cs_detach,
 	.id_table	= nsp_cs_ids,
+	.suspend	= nsp_cs_suspend,
+	.resume		= nsp_cs_resume,
 };
 #endif
 
@@ -2171,7 +2101,6 @@ static void __exit nsp_cs_exit(void)
 
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,68))
 	pcmcia_unregister_driver(&nsp_driver);
-	BUG_ON(dev_list != NULL);
 #else
 	unregister_pcmcia_driver(&dev_info);
 	/* XXX: this really needs to move into generic code.. */
diff --git a/drivers/scsi/pcmcia/nsp_cs.h b/drivers/scsi/pcmcia/nsp_cs.h
index f8b943082717..b66b140a745e 100644
--- a/drivers/scsi/pcmcia/nsp_cs.h
+++ b/drivers/scsi/pcmcia/nsp_cs.h
@@ -296,11 +296,9 @@ typedef struct _nsp_hw_data {
  */
 
 /* Card service functions */
-static dev_link_t *nsp_cs_attach (void);
-static void        nsp_cs_detach (dev_link_t *link);
+static void        nsp_cs_detach (struct pcmcia_device *p_dev);
 static void        nsp_cs_release(dev_link_t *link);
 static void        nsp_cs_config (dev_link_t *link);
-static int         nsp_cs_event  (event_t event, int priority, event_callback_args_t *args);
 
 /* Linux SCSI subsystem specific functions */
 static struct Scsi_Host *nsp_detect     (struct scsi_host_template *sht);
diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c
index bb091a45a880..dce7e687fd4a 100644
--- a/drivers/scsi/pcmcia/qlogic_stub.c
+++ b/drivers/scsi/pcmcia/qlogic_stub.c
@@ -98,15 +98,8 @@ typedef struct scsi_info_t {
 } scsi_info_t;
 
 static void qlogic_release(dev_link_t *link);
-static int qlogic_event(event_t event, int priority, event_callback_args_t * args);
-
-static dev_link_t *qlogic_attach(void);
-static void qlogic_detach(dev_link_t *);
-
-
-static dev_link_t *dev_list = NULL;
-
-static dev_info_t dev_info = "qlogic_cs";
+static void qlogic_detach(struct pcmcia_device *p_dev);
+static void qlogic_config(dev_link_t * link);
 
 static struct Scsi_Host *qlogic_detect(struct scsi_host_template *host,
 				dev_link_t *link, int qbase, int qlirq)
@@ -163,19 +156,17 @@ free_scsi_host:
 err:
 	return NULL;
 }
-static dev_link_t *qlogic_attach(void)
+static int qlogic_attach(struct pcmcia_device *p_dev)
 {
 	scsi_info_t *info;
-	client_reg_t client_reg;
 	dev_link_t *link;
-	int ret;
 
 	DEBUG(0, "qlogic_attach()\n");
 
 	/* Create new SCSI device */
 	info = kmalloc(sizeof(*info), GFP_KERNEL);
 	if (!info)
-		return NULL;
+		return -ENOMEM;
 	memset(info, 0, sizeof(*info));
 	link = &info->link;
 	link->priv = info;
@@ -189,45 +180,26 @@ static dev_link_t *qlogic_attach(void)
 	link->conf.IntType = INT_MEMORY_AND_IO;
 	link->conf.Present = PRESENT_OPTION;
 
-	/* Register with Card Services */
-	link->next = dev_list;
-	dev_list = link;
-	client_reg.dev_info = &dev_info;
-	client_reg.Version = 0x0210;
-	client_reg.event_callback_args.client_data = link;
-	ret = pcmcia_register_client(&link->handle, &client_reg);
-	if (ret != 0) {
-		cs_error(link->handle, RegisterClient, ret);
-		qlogic_detach(link);
-		return NULL;
-	}
+	link->handle = p_dev;
+	p_dev->instance = link;
 
-	return link;
+	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+	qlogic_config(link);
+
+	return 0;
 }				/* qlogic_attach */
 
 /*====================================================================*/
 
-static void qlogic_detach(dev_link_t * link)
+static void qlogic_detach(struct pcmcia_device *p_dev)
 {
-	dev_link_t **linkp;
+	dev_link_t *link = dev_to_instance(p_dev);
 
 	DEBUG(0, "qlogic_detach(0x%p)\n", link);
 
-	/* Locate device structure */
-	for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
-		if (*linkp == link)
-			break;
-	if (*linkp == NULL)
-		return;
-
 	if (link->state & DEV_CONFIG)
 		qlogic_release(link);
 
-	if (link->handle)
-		pcmcia_deregister_client(link->handle);
-
-	/* Unlink device structure, free bits */
-	*linkp = link->next;
 	kfree(link->priv);
 
 }				/* qlogic_detach */
@@ -349,48 +321,39 @@ static void qlogic_release(dev_link_t *link)
 
 /*====================================================================*/
 
-static int qlogic_event(event_t event, int priority, event_callback_args_t * args)
+static int qlogic_suspend(struct pcmcia_device *dev)
 {
-	dev_link_t *link = args->client_data;
-
-	DEBUG(1, "qlogic_event(0x%06x)\n", event);
-
-	switch (event) {
-	case CS_EVENT_CARD_REMOVAL:
-		link->state &= ~DEV_PRESENT;
-		if (link->state & DEV_CONFIG)
-			qlogic_release(link);
-		break;
-	case CS_EVENT_CARD_INSERTION:
-		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-		qlogic_config(link);
-		break;
-	case CS_EVENT_PM_SUSPEND:
-		link->state |= DEV_SUSPEND;
-		/* Fall through... */
-	case CS_EVENT_RESET_PHYSICAL:
-		if (link->state & DEV_CONFIG)
-			pcmcia_release_configuration(link->handle);
-		break;
-	case CS_EVENT_PM_RESUME:
-		link->state &= ~DEV_SUSPEND;
-		/* Fall through... */
-	case CS_EVENT_CARD_RESET:
-		if (link->state & DEV_CONFIG) {
-			scsi_info_t *info = link->priv;
-			pcmcia_request_configuration(link->handle, &link->conf);
-			if ((info->manf_id == MANFID_MACNICA) || (info->manf_id == MANFID_PIONEER) || (info->manf_id == 0x0098)) {
-				outb(0x80, link->io.BasePort1 + 0xd);
-				outb(0x24, link->io.BasePort1 + 0x9);
-				outb(0x04, link->io.BasePort1 + 0xd);
-			}
-			/* Ugggglllyyyy!!! */
-			qlogicfas408_bus_reset(NULL);
+	dev_link_t *link = dev_to_instance(dev);
+
+	link->state |= DEV_SUSPEND;
+	if (link->state & DEV_CONFIG)
+		pcmcia_release_configuration(link->handle);
+
+	return 0;
+}
+
+static int qlogic_resume(struct pcmcia_device *dev)
+{
+	dev_link_t *link = dev_to_instance(dev);
+
+	link->state &= ~DEV_SUSPEND;
+	if (link->state & DEV_CONFIG) {
+		scsi_info_t *info = link->priv;
+
+		pcmcia_request_configuration(link->handle, &link->conf);
+		if ((info->manf_id == MANFID_MACNICA) ||
+		    (info->manf_id == MANFID_PIONEER) ||
+		    (info->manf_id == 0x0098)) {
+			outb(0x80, link->io.BasePort1 + 0xd);
+			outb(0x24, link->io.BasePort1 + 0x9);
+			outb(0x04, link->io.BasePort1 + 0xd);
 		}
-		break;
+		/* Ugggglllyyyy!!! */
+		qlogicfas408_bus_reset(NULL);
 	}
+
 	return 0;
-}				/* qlogic_event */
+}
 
 static struct pcmcia_device_id qlogic_ids[] = {
 	PCMCIA_DEVICE_PROD_ID12("EIger Labs", "PCMCIA-to-SCSI Adapter", 0x88395fa7, 0x33b7a5e6),
@@ -419,10 +382,11 @@ static struct pcmcia_driver qlogic_cs_driver = {
 	.drv		= {
 	.name		= "qlogic_cs",
 	},
-	.attach		= qlogic_attach,
-	.event		= qlogic_event,
-	.detach		= qlogic_detach,
+	.probe		= qlogic_attach,
+	.remove		= qlogic_detach,
 	.id_table       = qlogic_ids,
+	.suspend	= qlogic_suspend,
+	.resume		= qlogic_resume,
 };
 
 static int __init init_qlogic_cs(void)
@@ -433,7 +397,6 @@ static int __init init_qlogic_cs(void)
 static void __exit exit_qlogic_cs(void)
 {
 	pcmcia_unregister_driver(&qlogic_cs_driver);
-	BUG_ON(dev_list != NULL);
 }
 
 MODULE_AUTHOR("Tom Zerucha, Michael Griffith");
diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c
index 98b64b2aa8ee..3a4dd6f5b81f 100644
--- a/drivers/scsi/pcmcia/sym53c500_cs.c
+++ b/drivers/scsi/pcmcia/sym53c500_cs.c
@@ -228,15 +228,6 @@ enum Phase {
 
 /* ================================================================== */
 
-/*
-*  Global (within this module) variables other than
-*  sym53c500_driver_template (the scsi_host_template).
-*/
-static dev_link_t *dev_list;
-static dev_info_t dev_info = "sym53c500_cs";
-
-/* ================================================================== */
-
 static void
 chip_init(int io_port)
 {
@@ -872,96 +863,70 @@ cs_failed:
 	return;
 } /* SYM53C500_config */
 
-static int
-SYM53C500_event(event_t event, int priority, event_callback_args_t *args)
+static int sym53c500_suspend(struct pcmcia_device *dev)
 {
-	dev_link_t *link = args->client_data;
-	struct scsi_info_t *info = link->priv;
+	dev_link_t *link = dev_to_instance(dev);
 
-	DEBUG(1, "SYM53C500_event(0x%06x)\n", event);
+	link->state |= DEV_SUSPEND;
+	if (link->state & DEV_CONFIG)
+		pcmcia_release_configuration(link->handle);
 
-	switch (event) {
-	case CS_EVENT_CARD_REMOVAL:
-		link->state &= ~DEV_PRESENT;
-		if (link->state & DEV_CONFIG)
-			SYM53C500_release(link);
-		break;
-	case CS_EVENT_CARD_INSERTION:
-		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-		SYM53C500_config(link);
-		break;
-	case CS_EVENT_PM_SUSPEND:
-		link->state |= DEV_SUSPEND;
-		/* Fall through... */
-	case CS_EVENT_RESET_PHYSICAL:
-		if (link->state & DEV_CONFIG)
-			pcmcia_release_configuration(link->handle);
-		break;
-	case CS_EVENT_PM_RESUME:
-		link->state &= ~DEV_SUSPEND;
-		/* Fall through... */
-	case CS_EVENT_CARD_RESET:
-		if (link->state & DEV_CONFIG) {
-			pcmcia_request_configuration(link->handle, &link->conf);
-			/* See earlier comment about manufacturer IDs. */
-			if ((info->manf_id == MANFID_MACNICA) ||
-			    (info->manf_id == MANFID_PIONEER) ||
-			    (info->manf_id == 0x0098)) {
-				outb(0x80, link->io.BasePort1 + 0xd);
-				outb(0x24, link->io.BasePort1 + 0x9);
-				outb(0x04, link->io.BasePort1 + 0xd);
-			}
-			/*
-			*  If things don't work after a "resume",
-			*  this is a good place to start looking.
-			*/
-			SYM53C500_int_host_reset(link->io.BasePort1);
+	return 0;
+}
+
+static int sym53c500_resume(struct pcmcia_device *dev)
+{
+	dev_link_t *link = dev_to_instance(dev);
+	struct scsi_info_t *info = link->priv;
+
+	link->state &= ~DEV_SUSPEND;
+	if (link->state & DEV_CONFIG) {
+		pcmcia_request_configuration(link->handle, &link->conf);
+
+		/* See earlier comment about manufacturer IDs. */
+		if ((info->manf_id == MANFID_MACNICA) ||
+		    (info->manf_id == MANFID_PIONEER) ||
+		    (info->manf_id == 0x0098)) {
+			outb(0x80, link->io.BasePort1 + 0xd);
+			outb(0x24, link->io.BasePort1 + 0x9);
+			outb(0x04, link->io.BasePort1 + 0xd);
 		}
-		break;
+		/*
+		 *  If things don't work after a "resume",
+		 *  this is a good place to start looking.
+		 */
+		SYM53C500_int_host_reset(link->io.BasePort1);
 	}
+
 	return 0;
-} /* SYM53C500_event */
+}
 
 static void
-SYM53C500_detach(dev_link_t *link)
+SYM53C500_detach(struct pcmcia_device *p_dev)
 {
-	dev_link_t **linkp;
+	dev_link_t *link = dev_to_instance(p_dev);
 
 	DEBUG(0, "SYM53C500_detach(0x%p)\n", link);
 
-	/* Locate device structure */
-	for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
-		if (*linkp == link)
-			break;
-	if (*linkp == NULL)
-		return;
-
 	if (link->state & DEV_CONFIG)
 		SYM53C500_release(link);
 
-	if (link->handle)
-		pcmcia_deregister_client(link->handle);
-
-	/* Unlink device structure, free bits. */
-	*linkp = link->next;
 	kfree(link->priv);
 	link->priv = NULL;
 } /* SYM53C500_detach */
 
-static dev_link_t *
-SYM53C500_attach(void)
+static int
+SYM53C500_attach(struct pcmcia_device *p_dev)
 {
 	struct scsi_info_t *info;
-	client_reg_t client_reg;
 	dev_link_t *link;
-	int ret;
 
 	DEBUG(0, "SYM53C500_attach()\n");
 
 	/* Create new SCSI device */
 	info = kmalloc(sizeof(*info), GFP_KERNEL);
 	if (!info)
-		return NULL;
+		return -ENOMEM;
 	memset(info, 0, sizeof(*info));
 	link = &info->link;
 	link->priv = info;
@@ -975,20 +940,13 @@ SYM53C500_attach(void)
 	link->conf.IntType = INT_MEMORY_AND_IO;
 	link->conf.Present = PRESENT_OPTION;
 
-	/* Register with Card Services */
-	link->next = dev_list;
-	dev_list = link;
-	client_reg.dev_info = &dev_info;
-	client_reg.Version = 0x0210;
-	client_reg.event_callback_args.client_data = link;
-	ret = pcmcia_register_client(&link->handle, &client_reg);
-	if (ret != 0) {
-		cs_error(link->handle, RegisterClient, ret);
-		SYM53C500_detach(link);
-		return NULL;
-	}
+	link->handle = p_dev;
+	p_dev->instance = link;
+
+	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+	SYM53C500_config(link);
 
-	return link;
+	return 0;
 } /* SYM53C500_attach */
 
 MODULE_AUTHOR("Bob Tracy <rct@frus.com>");
@@ -1008,10 +966,11 @@ static struct pcmcia_driver sym53c500_cs_driver = {
 	.drv		= {
 		.name	= "sym53c500_cs",
 	},
-	.attach		= SYM53C500_attach,
-	.event		= SYM53C500_event,
-	.detach		= SYM53C500_detach,
+	.probe		= SYM53C500_attach,
+	.remove		= SYM53C500_detach,
 	.id_table       = sym53c500_ids,
+	.suspend	= sym53c500_suspend,
+	.resume		= sym53c500_resume,
 };
 
 static int __init
diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c
index f557f17ca00c..e8df0c9ec1e6 100644
--- a/drivers/scsi/pdc_adma.c
+++ b/drivers/scsi/pdc_adma.c
@@ -464,14 +464,12 @@ static inline unsigned int adma_intr_pkt(struct ata_host_set *host_set)
 			continue;
 		qc = ata_qc_from_tag(ap, ap->active_tag);
 		if (qc && (!(qc->tf.ctl & ATA_NIEN))) {
-			unsigned int err_mask = 0;
-
 			if ((status & (aPERR | aPSD | aUIRQ)))
-				err_mask = AC_ERR_OTHER;
+				qc->err_mask |= AC_ERR_OTHER;
 			else if (pp->pkt[0] != cDONE)
-				err_mask = AC_ERR_OTHER;
+				qc->err_mask |= AC_ERR_OTHER;
 
-			ata_qc_complete(qc, err_mask);
+			ata_qc_complete(qc);
 		}
 	}
 	return handled;
@@ -501,7 +499,8 @@ static inline unsigned int adma_intr_mmio(struct ata_host_set *host_set)
 		
 				/* complete taskfile transaction */
 				pp->state = adma_state_idle;
-				ata_qc_complete(qc, ac_err_mask(status));
+				qc->err_mask |= ac_err_mask(status);
+				ata_qc_complete(qc);
 				handled = 1;
 			}
 		}
diff --git a/drivers/scsi/qla2xxx/Kconfig b/drivers/scsi/qla2xxx/Kconfig
index c1c1c687bcbd..5205c4e7d6ff 100644
--- a/drivers/scsi/qla2xxx/Kconfig
+++ b/drivers/scsi/qla2xxx/Kconfig
@@ -1,55 +1,70 @@
 config SCSI_QLA2XXX
-	tristate
-	default (SCSI && PCI)
-	depends on SCSI && PCI
+	tristate "QLogic QLA2XXX Fibre Channel Support"
+	depends on PCI && SCSI
+	select SCSI_FC_ATTRS
+	select FW_LOADER
+	---help---
+	This qla2xxx driver supports all QLogic Fibre Channel
+	PCI and PCIe host adapters.
 
-config SCSI_QLA21XX
-	tristate "QLogic ISP2100 host adapter family support"
+	By default, firmware for the ISP parts will be loaded
+	via the Firmware Loader interface.
+
+	ISP             Firmware Filename
+	----------      -----------------
+	21xx            ql2100_fw.bin
+	22xx            ql2200_fw.bin
+	2300, 2312      ql2300_fw.bin
+	2322            ql2322_fw.bin
+	6312, 6322      ql6312_fw.bin
+	24xx            ql2400_fw.bin
+
+	Upon request, the driver caches the firmware image until
+	the driver is unloaded.
+
+	NOTE: The original method of building firmware-loader
+	modules has been deprecated as the firmware-images will
+	be removed from the kernel sources.
+
+config SCSI_QLA2XXX_EMBEDDED_FIRMWARE
+	bool "  Use firmware-loader modules (DEPRECATED)"
 	depends on SCSI_QLA2XXX
-        select SCSI_FC_ATTRS
-	select FW_LOADER
+
+config SCSI_QLA21XX
+	tristate "  Build QLogic ISP2100 firmware-module"
+	depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE
 	---help---
 	This driver supports the QLogic 21xx (ISP2100) host adapter family.
 
 config SCSI_QLA22XX
-	tristate "QLogic ISP2200 host adapter family support"
-	depends on SCSI_QLA2XXX
-        select SCSI_FC_ATTRS
-	select FW_LOADER
+	tristate "  Build QLogic ISP2200 firmware-module"
+	depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE
 	---help---
 	This driver supports the QLogic 22xx (ISP2200) host adapter family.
 
 config SCSI_QLA2300
-	tristate "QLogic ISP2300 host adapter family support"
-	depends on SCSI_QLA2XXX
-        select SCSI_FC_ATTRS
-	select FW_LOADER
+	tristate "  Build QLogic ISP2300 firmware-module"
+	depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE
 	---help---
 	This driver supports the QLogic 2300 (ISP2300 and ISP2312) host
 	adapter family.
 
 config SCSI_QLA2322
-	tristate "QLogic ISP2322 host adapter family support"
-	depends on SCSI_QLA2XXX
-        select SCSI_FC_ATTRS
-	select FW_LOADER
+	tristate "  Build QLogic ISP2322 firmware-module"
+	depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE
 	---help---
 	This driver supports the QLogic 2322 (ISP2322) host adapter family.
 
 config SCSI_QLA6312
-	tristate "QLogic ISP63xx host adapter family support"
-	depends on SCSI_QLA2XXX
-        select SCSI_FC_ATTRS
-	select FW_LOADER
+	tristate "  Build QLogic ISP63xx firmware-module"
+	depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE
 	---help---
 	This driver supports the QLogic 63xx (ISP6312 and ISP6322) host
 	adapter family.
 
 config SCSI_QLA24XX
-	tristate "QLogic ISP24xx host adapter family support"
-	depends on SCSI_QLA2XXX
-	select SCSI_FC_ATTRS
-	select FW_LOADER
+	tristate "  Build QLogic ISP24xx firmware-module"
+	depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE
 	---help---
 	This driver supports the QLogic 24xx (ISP2422 and ISP2432) host
 	adapter family.
diff --git a/drivers/scsi/qla2xxx/Makefile b/drivers/scsi/qla2xxx/Makefile
index b169687d08ff..40c0de125889 100644
--- a/drivers/scsi/qla2xxx/Makefile
+++ b/drivers/scsi/qla2xxx/Makefile
@@ -3,15 +3,18 @@ EXTRA_CFLAGS += -DUNIQUE_FW_NAME
 qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \
 		qla_dbg.o qla_sup.o qla_rscn.o qla_attr.o
 
+obj-$(CONFIG_SCSI_QLA2XXX) += qla2xxx.o
+
 qla2100-y := ql2100.o ql2100_fw.o
 qla2200-y := ql2200.o ql2200_fw.o
 qla2300-y := ql2300.o ql2300_fw.o
 qla2322-y := ql2322.o ql2322_fw.o
 qla6312-y := ql6312.o ql6312_fw.o
+qla2400-y := ql2400.o ql2400_fw.o
 
 obj-$(CONFIG_SCSI_QLA21XX) += qla2xxx.o qla2100.o
 obj-$(CONFIG_SCSI_QLA22XX) += qla2xxx.o qla2200.o
 obj-$(CONFIG_SCSI_QLA2300) += qla2xxx.o qla2300.o
 obj-$(CONFIG_SCSI_QLA2322) += qla2xxx.o qla2322.o
 obj-$(CONFIG_SCSI_QLA6312) += qla2xxx.o qla6312.o
-obj-$(CONFIG_SCSI_QLA24XX) += qla2xxx.o
+obj-$(CONFIG_SCSI_QLA24XX) += qla2xxx.o qla2400.o
diff --git a/drivers/scsi/qla2xxx/ql2400.c b/drivers/scsi/qla2xxx/ql2400.c
new file mode 100644
index 000000000000..6c7165f47e29
--- /dev/null
+++ b/drivers/scsi/qla2xxx/ql2400.c
@@ -0,0 +1,111 @@
+/*
+ * QLogic Fibre Channel HBA Driver
+ * Copyright (c)  2003-2005 QLogic Corporation
+ *
+ * See LICENSE.qla2xxx for copyright and licensing details.
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+
+#include "qla_def.h"
+
+static char qla_driver_name[] = "qla2400";
+
+extern uint32_t fw2400_version_str[];
+extern uint32_t fw2400_addr01;
+extern uint32_t fw2400_code01[];
+extern uint32_t fw2400_length01;
+extern uint32_t fw2400_addr02;
+extern uint32_t fw2400_code02[];
+extern uint32_t fw2400_length02;
+
+static struct qla_fw_info qla_fw_tbl[] = {
+	{
+		.addressing	= FW_INFO_ADDR_EXTENDED,
+		.fwcode		= (unsigned short *)&fw2400_code01[0],
+		.fwlen		= (unsigned short *)&fw2400_length01,
+		.lfwstart	= (unsigned long *)&fw2400_addr01,
+	},
+	{
+		.addressing	= FW_INFO_ADDR_EXTENDED,
+		.fwcode		= (unsigned short *)&fw2400_code02[0],
+		.fwlen		= (unsigned short *)&fw2400_length02,
+		.lfwstart	= (unsigned long *)&fw2400_addr02,
+	},
+	{ FW_INFO_ADDR_NOMORE, },
+};
+
+static struct qla_board_info qla_board_tbl[] = {
+	{
+		.drv_name	= qla_driver_name,
+		.isp_name	= "ISP2422",
+		.fw_info	= qla_fw_tbl,
+		.fw_fname	= "ql2400_fw.bin",
+	},
+	{
+		.drv_name	= qla_driver_name,
+		.isp_name	= "ISP2432",
+		.fw_info	= qla_fw_tbl,
+		.fw_fname	= "ql2400_fw.bin",
+	},
+};
+
+static struct pci_device_id qla24xx_pci_tbl[] = {
+	{
+		.vendor		= PCI_VENDOR_ID_QLOGIC,
+		.device		= PCI_DEVICE_ID_QLOGIC_ISP2422,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.driver_data	= (unsigned long)&qla_board_tbl[0],
+	},
+	{
+		.vendor		= PCI_VENDOR_ID_QLOGIC,
+		.device		= PCI_DEVICE_ID_QLOGIC_ISP2432,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.driver_data	= (unsigned long)&qla_board_tbl[1],
+	},
+	{0, 0},
+};
+MODULE_DEVICE_TABLE(pci, qla24xx_pci_tbl);
+
+static int __devinit
+qla24xx_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+	return qla2x00_probe_one(pdev,
+	    (struct qla_board_info *)id->driver_data);
+}
+
+static void __devexit
+qla24xx_remove_one(struct pci_dev *pdev)
+{
+	qla2x00_remove_one(pdev);
+}
+
+static struct pci_driver qla24xx_pci_driver = {
+	.name		= "qla2400",
+	.id_table	= qla24xx_pci_tbl,
+	.probe		= qla24xx_probe_one,
+	.remove		= __devexit_p(qla24xx_remove_one),
+};
+
+static int __init
+qla24xx_init(void)
+{
+	return pci_module_init(&qla24xx_pci_driver);
+}
+
+static void __exit
+qla24xx_exit(void)
+{
+	pci_unregister_driver(&qla24xx_pci_driver);
+}
+
+module_init(qla24xx_init);
+module_exit(qla24xx_exit);
+
+MODULE_AUTHOR("QLogic Corporation");
+MODULE_DESCRIPTION("QLogic ISP24xx FC-SCSI Host Bus Adapter driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(QLA2XXX_VERSION);
diff --git a/drivers/scsi/qla2xxx/ql2400_fw.c b/drivers/scsi/qla2xxx/ql2400_fw.c
new file mode 100644
index 000000000000..5977795854f8
--- /dev/null
+++ b/drivers/scsi/qla2xxx/ql2400_fw.c
@@ -0,0 +1,12376 @@
+/*
+ * QLogic Fibre Channel HBA Driver
+ * Copyright (c)  2003-2005 QLogic Corporation
+ *
+ * See LICENSE.qla2xxx for copyright and licensing details.
+ */
+#include <linux/types.h>
+
+/*
+ *	Firmware Version 4.00.16 (08:09 Oct 26, 2005)
+ */
+
+#ifdef UNIQUE_FW_NAME
+uint32_t fw2400_version = 4*1024+0;
+#else
+uint32_t risc_code_version = 4*1024+0;
+#endif
+
+#ifdef UNIQUE_FW_NAME
+uint32_t fw2400_version_str[] = {4, 0,16};
+#else
+uint32_t firmware_version[] = {4, 0,16};
+#endif
+
+#ifdef UNIQUE_FW_NAME
+#define fw2400_VERSION_STRING "4.00.16"
+#else
+#define FW_VERSION_STRING "4.00.16"
+#endif
+
+#ifdef UNIQUE_FW_NAME
+uint32_t fw2400_addr01 = 0x00100000 ;
+#else
+uint32_t risc_code_addr01 = 0x00100000 ;
+#endif
+
+#ifdef UNIQUE_FW_NAME
+uint32_t fw2400_code01[] = {
+#else
+uint32_t risc_code01[] = {
+#endif
+	0x0401f17c, 0x0010e000, 0x00100000, 0x0000ab4a,
+	0x00000004, 0x00000000, 0x00000010, 0x00000002,
+	0x00000003, 0x00000000, 0x20434f50, 0x59524947,
+	0x48542032, 0x30303520, 0x514c4f47, 0x49432043,
+	0x4f52504f, 0x52415449, 0x4f4e2020, 0x20495350,
+	0x32347878, 0x20466972, 0x6d776172, 0x65202020,
+	0x56657273, 0x696f6e20, 0x342e302e, 0x31362020,
+	0x20202024, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x42001800, 0x0010014f, 0x42002000, 0x0010b8fe,
+	0x500c0800, 0x800c1800, 0x500c1000, 0x800c1800,
+	0x54042000, 0x80102000, 0x80040800, 0x80081040,
+	0x040207fc, 0x500c0800, 0x800409c0, 0x040207f6,
+	0x44002000, 0x80102000, 0x40100000, 0x44040000,
+	0x80000000, 0x44080000, 0x80000000, 0x440c0000,
+	0x80000000, 0x44100000, 0x80000000, 0x44140000,
+	0x80000000, 0x44180000, 0x80000000, 0x441c0000,
+	0x80000000, 0x44200000, 0x80000000, 0x44240000,
+	0x80000000, 0x44280000, 0x80000000, 0x442c0000,
+	0x80000000, 0x44300000, 0x80000000, 0x44340000,
+	0x80000000, 0x44380000, 0x80000000, 0x443c0000,
+	0x80000000, 0x44400000, 0x80000000, 0x44440000,
+	0x80000000, 0x44480000, 0x80000000, 0x444c0000,
+	0x80000000, 0x44500000, 0x80000000, 0x44540000,
+	0x80000000, 0x44580000, 0x80000000, 0x445c0000,
+	0x80000000, 0x44600000, 0x80000000, 0x44640000,
+	0x80000000, 0x44680000, 0x80000000, 0x446c0000,
+	0x80000000, 0x44700000, 0x80000000, 0x44740000,
+	0x80000000, 0x44780000, 0x80000000, 0x447c0000,
+	0x80000000, 0x44800000, 0x80000000, 0x44840000,
+	0x80000000, 0x44880000, 0x80000000, 0x448c0000,
+	0x80000000, 0x44900000, 0x80000000, 0x44940000,
+	0x80000000, 0x44980000, 0x80000000, 0x449c0000,
+	0x80000000, 0x44a00000, 0x80000000, 0x44a40000,
+	0x80000000, 0x44a80000, 0x80000000, 0x44ac0000,
+	0x80000000, 0x44b00000, 0x80000000, 0x44b40000,
+	0x80000000, 0x44b80000, 0x80000000, 0x44bc0000,
+	0x80000000, 0x44c00000, 0x80000000, 0x44c40000,
+	0x80000000, 0x44c80000, 0x80000000, 0x44cc0000,
+	0x80000000, 0x44d00000, 0x80000000, 0x44d80000,
+	0x80000000, 0x44d40000, 0x80000000, 0x44dc0000,
+	0x80000000, 0x44e00000, 0x80000000, 0x44e40000,
+	0x80000000, 0x44e80000, 0x80000000, 0x44ec0000,
+	0x80000000, 0x44f00000, 0x80000000, 0x44f40000,
+	0x80000000, 0x44f80000, 0x80000000, 0x44fc0000,
+	0x80000000, 0x45000000, 0x80000000, 0x45040000,
+	0x80000000, 0x45080000, 0x80000000, 0x450c0000,
+	0x80000000, 0x45100000, 0x80000000, 0x45140000,
+	0x80000000, 0x45180000, 0x80000000, 0x451c0000,
+	0x80000000, 0x45200000, 0x80000000, 0x45240000,
+	0x80000000, 0x45280000, 0x80000000, 0x452c0000,
+	0x80000000, 0x45300000, 0x80000000, 0x45340000,
+	0x80000000, 0x45380000, 0x80000000, 0x453c0000,
+	0x80000000, 0x45400000, 0x80000000, 0x45440000,
+	0x80000000, 0x45480000, 0x80000000, 0x454c0000,
+	0x80000000, 0x45500000, 0x80000000, 0x45540000,
+	0x80000000, 0x45580000, 0x80000000, 0x455c0000,
+	0x80000000, 0x45600000, 0x80000000, 0x45640000,
+	0x80000000, 0x45680000, 0x80000000, 0x456c0000,
+	0x80000000, 0x45700000, 0x80000000, 0x45740000,
+	0x80000000, 0x45780000, 0x80000000, 0x457c0000,
+	0x80000000, 0x45800000, 0x80000000, 0x45840000,
+	0x80000000, 0x45880000, 0x80000000, 0x458c0000,
+	0x80000000, 0x45900000, 0x80000000, 0x45940000,
+	0x80000000, 0x45980000, 0x80000000, 0x459c0000,
+	0x80000000, 0x45a00000, 0x80000000, 0x45a40000,
+	0x80000000, 0x45a80000, 0x80000000, 0x45ac0000,
+	0x80000000, 0x45b00000, 0x80000000, 0x45b40000,
+	0x80000000, 0x45b80000, 0x80000000, 0x45bc0000,
+	0x80000000, 0x45c00000, 0x80000000, 0x45c40000,
+	0x80000000, 0x45c80000, 0x80000000, 0x45cc0000,
+	0x80000000, 0x45d00000, 0x80000000, 0x45d40000,
+	0x80000000, 0x45d80000, 0x80000000, 0x45dc0000,
+	0x80000000, 0x45e00000, 0x80000000, 0x45e40000,
+	0x80000000, 0x45e80000, 0x80000000, 0x45ec0000,
+	0x80000000, 0x45f00000, 0x80000000, 0x45f40000,
+	0x80000000, 0x45f80000, 0x80000000, 0x45fc0000,
+	0x4a03c020, 0x00004000, 0x4a03c011, 0x40000010,
+	0x04006000, 0x4203e000, 0x40000000, 0x59e00017,
+	0x8c000508, 0x04000003, 0x4a03c017, 0x00000000,
+	0x4203e000, 0x30000001, 0x0401f000, 0x0000bf00,
+	0x00000080, 0x0000bfe0, 0x00000020, 0x0000ff00,
+	0x00000080, 0x0000ffd0, 0x00000030, 0x00007100,
+	0x00000010, 0x00007200, 0x00000008, 0x00007209,
+	0x00000007, 0x00007300, 0x00000008, 0x00007309,
+	0x00000007, 0x00007400, 0x00000008, 0x00007409,
+	0x00000007, 0x00007600, 0x000000b0, 0x00007700,
+	0x00000040, 0x00003000, 0x00000070, 0x00004000,
+	0x000000c0, 0x00006000, 0x00000050, 0x00006100,
+	0x00000010, 0x00006130, 0x00000010, 0x00006150,
+	0x00000010, 0x00006170, 0x00000010, 0x00006190,
+	0x00000010, 0x000061b0, 0x00000010, 0x00000000,
+	0x42000000, 0x00000100, 0x4202f000, 0x00000000,
+	0x42000800, 0x00021f00, 0x45780800, 0x80040800,
+	0x80000040, 0x040207fd, 0x4203f000, 0x00021fff,
+	0x40000000, 0x4203e000, 0x90000100, 0x40000000,
+	0x0201f800, 0x001006fd, 0x42000000, 0x00001000,
+	0x50000000, 0x82000480, 0x24320002, 0x04020015,
+	0x42000800, 0x00000064, 0x80040840, 0x04000007,
+	0x4a030000, 0x00000001, 0x40000000, 0x59800000,
+	0x8c000500, 0x040007f9, 0x04000008, 0x42000800,
+	0x00007a17, 0x50040000, 0x8c00050e, 0x04020003,
+	0x8400054e, 0x44000800, 0x4a030000, 0x00000000,
+	0x4a03c020, 0x00000004, 0x4203e000, 0x6000000f,
+	0x59e00023, 0x8c000500, 0x04020039, 0x42000000,
+	0x00100001, 0x50000800, 0x82040c00, 0x00000004,
+	0x58042003, 0x42001000, 0xffffffff, 0x0201f800,
+	0x001006f4, 0x0402004e, 0x58042003, 0x42001000,
+	0xffffffff, 0x0201f800, 0x001006f4, 0x04020048,
+	0x58042003, 0x42001000, 0x00ffffff, 0x0201f800,
+	0x001006f4, 0x04020042, 0x58042003, 0x42001000,
+	0x00ffffff, 0x0201f800, 0x001006f4, 0x0402003c,
+	0x42000000, 0x00100001, 0x5000a000, 0x8250a400,
+	0x00000004, 0x4200a800, 0x00020000, 0x5850b003,
+	0x0201f800, 0x0010ab17, 0x8250a400, 0x00000005,
+	0x4a0370e8, 0x00000003, 0x4200a800, 0x0000c000,
+	0x5850b003, 0x0201f800, 0x0010ab17, 0x4a0378e8,
+	0x00000003, 0x4200a800, 0x00008000, 0x5850b003,
+	0x0201f800, 0x0010ab17, 0x0401f02b, 0x42000800,
+	0x00020000, 0x58042003, 0x42001000, 0xffffffff,
+	0x0201f800, 0x001006f4, 0x04020019, 0x4a0370e8,
+	0x00000003, 0x42000800, 0x0000c000, 0x58042003,
+	0x82102500, 0x00ffffff, 0x42001000, 0x00ffffff,
+	0x0201f800, 0x001006f4, 0x0402000d, 0x4a0378e8,
+	0x00000003, 0x42000800, 0x00008000, 0x58042003,
+	0x82102500, 0x00ffffff, 0x42001000, 0x00ffffff,
+	0x0201f800, 0x001006f4, 0x0400000b, 0x4a03c020,
+	0x00004010, 0x4a03c011, 0x40100011, 0x04006000,
+	0x4203e000, 0x40000000, 0x4203e000, 0x30000001,
+	0x0401f000, 0x0201f800, 0x00100791, 0x42001000,
+	0x0010ab4a, 0x40080000, 0x80140480, 0x82001d00,
+	0xffffff00, 0x04020003, 0x40001800, 0x0401f003,
+	0x42001800, 0x000000ff, 0x480bc840, 0x480fc842,
+	0x04011000, 0x400c0000, 0x80081400, 0x40140000,
+	0x80080580, 0x040207f0, 0x4817500d, 0x45782800,
+	0x59c40000, 0x82000500, 0xffff0000, 0x80000120,
+	0x82000580, 0x00002422, 0x04020005, 0x59a80005,
+	0x8400054e, 0x48035005, 0x0401f008, 0x59e00003,
+	0x82000500, 0x00030000, 0x04000004, 0x59a80005,
+	0x84000554, 0x48035005, 0x42000800, 0x00000040,
+	0x59a80005, 0x8c000514, 0x0402000e, 0x42000800,
+	0x00001000, 0x82141480, 0x0017ffff, 0x04021009,
+	0x80040902, 0x82141480, 0x0013ffff, 0x04021005,
+	0x80040902, 0x82141480, 0x0011ffff, 0x04001b8d,
+	0x4807500e, 0x42001000, 0x00000024, 0x0201f800,
+	0x00106681, 0x82040c00, 0x0010d1c0, 0x4807500b,
+	0x4a03c810, 0x00100000, 0x4a03c811, 0x0010ab4a,
+	0x4a03c829, 0x00000004, 0x59e40001, 0x82000540,
+	0x0003001d, 0x4803c801, 0x4a03c014, 0x001c001c,
+	0x42001000, 0x0000001c, 0x0201f800, 0x001006e2,
+	0x4202c000, 0x0010d1c0, 0x59aab00b, 0x59aaa00b,
+	0x59aaa80b, 0x59aac80e, 0x49675069, 0x59a8000b,
+	0x4803500c, 0x0401fbf5, 0x0201f800, 0x00107903,
+	0x0201f800, 0x001007be, 0x0201f800, 0x00100807,
+	0x0201f800, 0x00101a05, 0x0201f800, 0x00101354,
+	0x0201f800, 0x00100969, 0x0201f800, 0x00101354,
+	0x0201f800, 0x00100f4c, 0x0201f800, 0x001066c1,
+	0x0401fb1a, 0x0201f800, 0x0010220e, 0x0201f800,
+	0x001053bb, 0x0201f800, 0x00104c90, 0x0201f800,
+	0x00106194, 0x0201f800, 0x00105f28, 0x0201f800,
+	0x001013ed, 0x0201f800, 0x0010126f, 0x4203e000,
+	0xf0000001, 0x42000000, 0x00001000, 0x50000000,
+	0x82000480, 0x24220001, 0x04000016, 0x59e00002,
+	0x8c00051e, 0x42000000, 0x7ffe00fe, 0x04020003,
+	0x42000000, 0x7ffe01fe, 0x50000800, 0x48075058,
+	0x80040920, 0x82040580, 0x0000013a, 0x04000004,
+	0x82040580, 0x0000013b, 0x04020006, 0x59a80005,
+	0x84000552, 0x48035005, 0x4a0378e4, 0x000c0000,
+	0x4a03c018, 0x0000000f, 0x4203e000, 0x20000511,
+	0x4203e000, 0x50010000, 0x4a03c020, 0x00000000,
+	0x04027013, 0x59e00020, 0x82000580, 0x00000002,
+	0x0402000f, 0x4a03c020, 0x00004000, 0x4a03c011,
+	0x40000010, 0x04006000, 0x4203e000, 0x40000000,
+	0x59e00017, 0x8c000508, 0x04000003, 0x4a03c017,
+	0x00000000, 0x4203e000, 0x30000001, 0x4202d800,
+	0x00000000, 0x4203e000, 0xb0600000, 0x59a80005,
+	0x42000800, 0x00000002, 0x8c000512, 0x04020007,
+	0x42000800, 0x0000000f, 0x8c000514, 0x04020003,
+	0x42000800, 0x00000001, 0x4007f800, 0x59a80005,
+	0x8c000514, 0x02020000, 0x00020004, 0x59e00003,
+	0x82000500, 0x00030000, 0x82000580, 0x00000000,
+	0x04020af8, 0x0201f000, 0x00020004, 0x4df00000,
+	0x4203e000, 0x50000000, 0x416c0000, 0x82000c80,
+	0x00000008, 0x04021aef, 0x0c01f804, 0x5c03e000,
+	0x0201f000, 0x00020008, 0x001002f7, 0x0010030a,
+	0x001003d7, 0x001002f6, 0x00100452, 0x001002f6,
+	0x001002f6, 0x00100593, 0x0401fae2, 0x42000800,
+	0x0010b4a4, 0x5804001d, 0x4803c857, 0x8c000500,
+	0x0400000d, 0x84000500, 0x4800081d, 0x4202d800,
+	0x00000004, 0x0401fbd3, 0x49f3c857, 0x5c000800,
+	0x5c000000, 0x82000540, 0x00003e00, 0x4c000000,
+	0x4c040000, 0x1c01f000, 0x0401fbbd, 0x0201f800,
+	0x0010513b, 0x04000009, 0x0201f800, 0x00105151,
+	0x0402002e, 0x59c40006, 0x82000540, 0x000000c0,
+	0x48038806, 0x0401f029, 0x0201f800, 0x001050a2,
+	0x836c0580, 0x00000001, 0x040200bc, 0x59a80017,
+	0x82000580, 0x00000009, 0x040200b8, 0x497b5010,
+	0x4a038893, 0x00000001, 0x42001000, 0x000000f0,
+	0x0201f800, 0x0010193d, 0x0201f800, 0x00105149,
+	0x59c41006, 0x04020006, 0x82081540, 0x000000f1,
+	0x82081500, 0xbbffffff, 0x0401f003, 0x82081540,
+	0x440000f1, 0x480b8806, 0x0201f800, 0x0010609e,
+	0x4a0378e4, 0x00002000, 0x42000000, 0x0010b83a,
+	0x0201f800, 0x0010aa47, 0x42001000, 0x00008030,
+	0x497b5013, 0x0401f035, 0x0201f800, 0x00103b38,
+	0x59c400a4, 0x82000500, 0x0000000f, 0x82000480,
+	0x00000007, 0x04021091, 0x0201f800, 0x0010609e,
+	0x59c400a3, 0x82000500, 0xffefffff, 0x480388a3,
+	0x59a8004b, 0x800001c0, 0x04020004, 0x0201f800,
+	0x00104139, 0x0401f085, 0x59a80015, 0x84000546,
+	0x48035015, 0x0201f800, 0x00105141, 0x59c41006,
+	0x04020006, 0x82081540, 0x44000001, 0x82081500,
+	0xffffff0f, 0x0401f003, 0x82081540, 0x440000f1,
+	0x480b8806, 0x497b9005, 0x4a038802, 0x0000ffff,
+	0x4a0378e4, 0x00003000, 0x42000000, 0x0010b80c,
+	0x0201f800, 0x0010aa47, 0x59a81010, 0x42000800,
+	0x00000003, 0x0201f800, 0x00106c78, 0x42001000,
+	0x00008010, 0x59a8180a, 0x0201f800, 0x00103a3e,
+	0x0201f800, 0x00101815, 0x59a80805, 0x82040d00,
+	0xffffffdf, 0x48075005, 0x0201f800, 0x0010483d,
+	0x0201f800, 0x0010513b, 0x0400000a, 0x0201f800,
+	0x0010413e, 0x04000007, 0x4a035013, 0x00000001,
+	0x497b5021, 0x0201f800, 0x00103c80, 0x0401f04f,
+	0x0201f800, 0x001048ec, 0x04000005, 0x59c41002,
+	0x8408150c, 0x480b8802, 0x0401f012, 0x0201f800,
+	0x0010513b, 0x04020006, 0x59a8001d, 0x80000540,
+	0x02000800, 0x0010930f, 0x0401f00a, 0x0201f800,
+	0x0010930f, 0x59a80026, 0x8c000506, 0x04020005,
+	0x59a8001d, 0x80000540, 0x02020800, 0x00104245,
+	0x497b5028, 0x497b5027, 0x497b5018, 0x0201f800,
+	0x0010513b, 0x59a81026, 0x0402000a, 0x0201f800,
+	0x0010162a, 0x80001580, 0x59a8002a, 0x82000500,
+	0xffff0000, 0x80040d40, 0x4807502a, 0x0401f005,
+	0x59a8002a, 0x82000500, 0xffff0000, 0x4803502a,
+	0x599c0017, 0x8c00050a, 0x04000002, 0x84081544,
+	0x480b5026, 0x0201f800, 0x0010513b, 0x04000004,
+	0x0201f800, 0x0010162a, 0x48078880, 0x42001000,
+	0x00000005, 0x0201f800, 0x001070b0, 0x497b5028,
+	0x497b501b, 0x4a03501c, 0x0000ffff, 0x4a0378e4,
+	0x000000c0, 0x4202d800, 0x00000002, 0x0201f800,
+	0x0010513b, 0x04000007, 0x59a80026, 0x82000500,
+	0x0000000c, 0x82000580, 0x00000004, 0x04000003,
+	0x0201f800, 0x00101e45, 0x1c01f000, 0x59a8001c,
+	0x82000580, 0x0000ffff, 0x04000004, 0x0201f800,
+	0x00101e45, 0x0401f074, 0x59a80026, 0x8c00050a,
+	0x04020003, 0x8c000506, 0x0400001c, 0x8c000500,
+	0x0400001a, 0x4a038802, 0x0000ffbf, 0x8c000502,
+	0x04000016, 0x599c0018, 0x8c000516, 0x04020010,
+	0x59a80027, 0x82000580, 0x0000ffff, 0x0400000c,
+	0x0201f800, 0x00101f9a, 0x59a80026, 0x8c000504,
+	0x0402005d, 0x42001000, 0x00000003, 0x417a5800,
+	0x0201f800, 0x00101fbf, 0x0401f057, 0x59a80028,
+	0x80000540, 0x04020054, 0x59a80026, 0x8c000508,
+	0x04020005, 0x59a8001b, 0x80000540, 0x0402004e,
+	0x0401f003, 0x8c000516, 0x0400004b, 0x0201f800,
+	0x001048ec, 0x04020048, 0x599c0018, 0x8c000516,
+	0x04020004, 0x0201f800, 0x00104c51, 0x04020042,
+	0x599c0017, 0x8c00050a, 0x0400000d, 0x4200b000,
+	0x000007f0, 0x417a8800, 0x0201f800, 0x00020245,
+	0x04020004, 0x59340200, 0x8c00051a, 0x04020036,
+	0x81468800, 0x8058b040, 0x040207f8, 0x4a038802,
+	0x0000ffff, 0x42001800, 0x0010b4eb, 0x0401fb8c,
+	0x42001800, 0x0010b4f8, 0x0401fb89, 0x59a80005,
+	0x84000502, 0x48035005, 0x4a0378e4, 0x00000080,
+	0x4202d800, 0x00000003, 0x4a03501c, 0x0000ffff,
+	0x0401fa7f, 0x80000580, 0x0201f800, 0x00101590,
+	0x599c0018, 0x8c000516, 0x04000004, 0x0201f800,
+	0x00103b10, 0x0401f009, 0x42001800, 0x0000ffff,
+	0x42002000, 0x00000006, 0x42003000, 0x00000000,
+	0x0201f800, 0x00103aae, 0x0201f800, 0x00105151,
+	0x0400000b, 0x59c40006, 0x0201f800, 0x0010513b,
+	0x04000004, 0x82000500, 0xffffff0f, 0x0401f003,
+	0x82000500, 0xfbffffff, 0x48038806, 0x0201f800,
+	0x00106f36, 0x1c01f000, 0x4c040000, 0x4c080000,
+	0x4c100000, 0x59a8003e, 0x82000c80, 0x00000004,
+	0x04021980, 0x0c01f805, 0x5c002000, 0x5c001000,
+	0x5c000800, 0x1c01f000, 0x00100462, 0x001004ea,
+	0x00100516, 0x00100577, 0x42000000, 0x00000001,
+	0x0201f800, 0x00101590, 0x0201f800, 0x0010609e,
+	0x59c408a3, 0x82040d00, 0xfffffff7, 0x480788a3,
+	0x0201f800, 0x00105141, 0x0400000e, 0x0201f800,
+	0x00105151, 0x0400000b, 0x0201f800, 0x00105149,
+	0x04020964, 0x59c400a3, 0x84000532, 0x84000570,
+	0x480388a3, 0x4a038808, 0x00000008, 0x0401f010,
+	0x59c400a3, 0x84000530, 0x82000500, 0xbf7fffff,
+	0x480388a3, 0x42000800, 0x000000f8, 0x0201f800,
+	0x00104200, 0x59c400a3, 0x82000540, 0x00018000,
+	0x8400051c, 0x480388a3, 0x497b8808, 0x59c40006,
+	0x82000500, 0xfbffff0e, 0x48038806, 0x497b2822,
+	0x497b2823, 0x42000800, 0x000001f4, 0x42001000,
+	0x00100591, 0x0201f800, 0x00105f83, 0x59c40805,
+	0x42001000, 0x00000001, 0x0201f800, 0x0010193d,
+	0x0201f800, 0x0010163b, 0x0402000a, 0x42000000,
+	0x00000001, 0x0201f800, 0x0010188c, 0x42000000,
+	0x00000001, 0x0201f800, 0x00101821, 0x0401f022,
+	0x0201f800, 0x00101642, 0x04020008, 0x41780000,
+	0x0201f800, 0x0010188c, 0x41780000, 0x0201f800,
+	0x00101821, 0x0401f018, 0x0201f800, 0x00101649,
+	0x0402000a, 0x42000000, 0x00000002, 0x0201f800,
+	0x0010188c, 0x42000000, 0x00000002, 0x0201f800,
+	0x00101821, 0x0401f00c, 0x0201f800, 0x00101650,
+	0x04020918, 0x59a80049, 0x800001c0, 0x04000006,
+	0x0201f800, 0x00101656, 0x4a03503e, 0x00000001,
+	0x0401f021, 0x0201f800, 0x00101927, 0x4a03503e,
+	0x00000001, 0x0201f800, 0x00105141, 0x0400000c,
+	0x0201f800, 0x00105151, 0x04000009, 0x0201f800,
+	0x00105149, 0x04020903, 0x4a035033, 0x00000001,
+	0x0201f800, 0x001050a2, 0x0401f00f, 0x59c400a4,
+	0x82000500, 0x0000000f, 0x82000580, 0x00000008,
+	0x04000003, 0x4a038805, 0x04000000, 0x59c400a3,
+	0x82000540, 0x0001c000, 0x480388a3, 0x84000520,
+	0x480388a3, 0x1c01f000, 0x0401f8a3, 0x04020004,
+	0x4a03503e, 0x00000003, 0x0401f027, 0x0201f800,
+	0x00101650, 0x04020011, 0x59a80049, 0x800001c0,
+	0x0400000e, 0x0201f800, 0x00101656, 0x59a80048,
+	0x8c00051e, 0x0400001c, 0x0201f800, 0x00105149,
+	0x04020009, 0x4a035033, 0x00000001, 0x0201f800,
+	0x001050a2, 0x0401f004, 0x0201f800, 0x001018d3,
+	0x04020011, 0x0201f800, 0x00101815, 0x4a03503e,
+	0x00000002, 0x497b5049, 0x59c400a3, 0x84000520,
+	0x480388a3, 0x497b2822, 0x497b2823, 0x42000800,
+	0x0000002d, 0x42001000, 0x00100591, 0x0201f800,
+	0x00105f83, 0x1c01f000, 0x0401f877, 0x04020004,
+	0x4a03503e, 0x00000003, 0x0401f05b, 0x4a038805,
+	0x000000f0, 0x0201f800, 0x001018d3, 0x04020050,
+	0x0201f800, 0x00105149, 0x04000044, 0x59c400a4,
+	0x82000500, 0x0000000f, 0x82000580, 0x00000008,
+	0x04000020, 0x59c40005, 0x8c000534, 0x0402001d,
+	0x59940022, 0x82000580, 0x00000001, 0x04020046,
+	0x0201f800, 0x00105151, 0x04020043, 0x4a038805,
+	0x000000f0, 0x0201f800, 0x00105196, 0x4a035032,
+	0x0000aaaa, 0x4a035033, 0x00000000, 0x59c408a3,
+	0x82040d40, 0x00000008, 0x480788a3, 0x4202d800,
+	0x00000001, 0x4a03503e, 0x00000000, 0x4a038805,
+	0x00000001, 0x497b2822, 0x497b2823, 0x0401f01f,
+	0x0201f800, 0x00105151, 0x04020007, 0x59a80032,
+	0x82000580, 0x0000aaaa, 0x04020003, 0x4a035010,
+	0x00ffffff, 0x497b5032, 0x59c40006, 0x82000540,
+	0x04000001, 0x48038806, 0x59a80805, 0x8c040d06,
+	0x04020005, 0x59c408a3, 0x82040d40, 0x00000008,
+	0x480788a3, 0x4202d800, 0x00000001, 0x4a03503e,
+	0x00000000, 0x4a038805, 0x00000001, 0x497b2822,
+	0x497b2823, 0x0401f010, 0x59c40005, 0x82000500,
+	0x000000c0, 0x0400000c, 0x59c40006, 0x82000540,
+	0x000000f1, 0x48038806, 0x0401f7ef, 0x0201f800,
+	0x00101650, 0x04020004, 0x59a80049, 0x800001c0,
+	0x040207a4, 0x497b8885, 0x1c01f000, 0x4803c856,
+	0x42000000, 0x00000001, 0x0201f800, 0x00101590,
+	0x4a03503e, 0x00000000, 0x0201f800, 0x00101650,
+	0x0402000b, 0x59a80052, 0x800001c0, 0x04000004,
+	0x80000040, 0x48035052, 0x04020005, 0x4a035052,
+	0x0000000a, 0x4a035049, 0x00000001, 0x497b8885,
+	0x0401f0ed, 0x59940022, 0x59940823, 0x80040540,
+	0x1c01f000, 0x497b2823, 0x1c01f000, 0x4c080000,
+	0x42001000, 0x000000f0, 0x0201f800, 0x0010193d,
+	0x5c001000, 0x1c01f000, 0x4a03505c, 0x00000004,
+	0x4a03505d, 0x00000000, 0x4a03505e, 0x00000010,
+	0x4a03505f, 0x00000002, 0x4a035010, 0x00ffffff,
+	0x0201f800, 0x0010930f, 0x4a03502a, 0x20200000,
+	0x4a03502b, 0x88000200, 0x4a03502c, 0x00ff001f,
+	0x4a03502d, 0x000007d0, 0x4a03502e, 0x80000000,
+	0x4a03502f, 0x00000200, 0x4a035030, 0x00ff0000,
+	0x4a035031, 0x00010000, 0x4a03503a, 0x514c4f47,
+	0x4a03503b, 0x49432020, 0x1c01f000, 0x4d440000,
+	0x417a8800, 0x41780800, 0x0201f800, 0x00020245,
+	0x04020005, 0x0201f800, 0x001049e7, 0x04020002,
+	0x80040800, 0x81468800, 0x83440580, 0x000007f0,
+	0x040207f6, 0x5c028800, 0x1c01f000, 0x4803c857,
+	0x5c000000, 0x4c000000, 0x4803c857, 0x0401f809,
+	0x485fc857, 0x4203e000, 0x50000000, 0x5c000000,
+	0x4d780000, 0x4200b800, 0x00008002, 0x0401f006,
+	0x485fc857, 0x4203e000, 0x50000000, 0x4200b800,
+	0x00008002, 0x04006000, 0x4c000000, 0x4c040000,
+	0x59bc00ea, 0x82000500, 0x00000007, 0x82000580,
+	0x00000001, 0x04020005, 0x42000800, 0x00000000,
+	0x0201f800, 0x00106c6c, 0x5c000800, 0x4807c025,
+	0x80040920, 0x4807c026, 0x5c000000, 0x4803c023,
+	0x80000120, 0x4803c024, 0x5c000000, 0x4803c857,
+	0x4803c021, 0x80000120, 0x4803c022, 0x41f80000,
+	0x4803c027, 0x80000120, 0x4803c028, 0x42000000,
+	0x00001000, 0x50000000, 0x82000480, 0x24320001,
+	0x4803c857, 0x0400104f, 0x42000800, 0x00000064,
+	0x80040840, 0x04000007, 0x4a030000, 0x00000001,
+	0x40000000, 0x59800000, 0x8c000500, 0x040007f9,
+	0x04000042, 0x42000800, 0x0010c1a3, 0x46000800,
+	0xfaceface, 0x80040800, 0x42001000, 0x00007a00,
+	0x58080013, 0x44000800, 0x80040800, 0x58080019,
+	0x44000800, 0x80040800, 0x5808001a, 0x44000800,
+	0x80040800, 0x5808001b, 0x44000800, 0x80040800,
+	0x5808001c, 0x44000800, 0x80040800, 0x5808001f,
+	0x44000800, 0x80040800, 0x42001000, 0x00007a40,
+	0x42001800, 0x0000000b, 0x50080000, 0x44000800,
+	0x80081000, 0x80040800, 0x800c1840, 0x040207fb,
+	0x42001800, 0x00000003, 0x42001000, 0x00007b00,
+	0x480c1003, 0x58080005, 0x44000800, 0x80040800,
+	0x800c1840, 0x040217fb, 0x42001000, 0x00007c00,
+	0x58080002, 0x44000800, 0x80040800, 0x58080003,
+	0x44000800, 0x80040800, 0x58080020, 0x44000800,
+	0x80040800, 0x58080021, 0x44000800, 0x80040800,
+	0x58080022, 0x44000800, 0x80040800, 0x58080023,
+	0x44000800, 0x80040800, 0x4a030000, 0x00000000,
+	0x485fc020, 0x905cb9c0, 0x825cbd40, 0x00000012,
+	0x485fc011, 0x4203e000, 0x40000000, 0x4202d800,
+	0x00000005, 0x59e00017, 0x8c000508, 0x04000003,
+	0x4a03c017, 0x00000002, 0x4203e000, 0x30000001,
+	0x0401f81a, 0x0401f7ff, 0x4a03c850, 0x0010c1bf,
+	0x4a03c851, 0x0010d1be, 0x4a03c853, 0x00000800,
+	0x4a03c855, 0x0001eb5a, 0x59e40001, 0x82000540,
+	0x00003f00, 0x4803c801, 0x4a03b104, 0x70000002,
+	0x4a03a804, 0x70000002, 0x4a03b004, 0x70000002,
+	0x42000000, 0x0010b8ec, 0x49780001, 0x49780002,
+	0x1c01f000, 0x1c01f000, 0x59a8006b, 0x8c000530,
+	0x040207fe, 0x4c080000, 0x42001000, 0x00000004,
+	0x0401f862, 0x5c001000, 0x4201d000, 0x00028b0a,
+	0x0201f800, 0x0010608e, 0x4c080000, 0x42001000,
+	0x00000008, 0x0401f859, 0x5c001000, 0x4201d000,
+	0x00028b0a, 0x0201f800, 0x0010608e, 0x4c080000,
+	0x42001000, 0x00000010, 0x0401f850, 0x5c001000,
+	0x4201d000, 0x00028b0a, 0x0201f800, 0x0010608e,
+	0x0401f7e2, 0x8c00050c, 0x59a8086b, 0x04020003,
+	0x84040d30, 0x0401f006, 0x84040d70, 0x4807506b,
+	0x42001000, 0x00000000, 0x0401f040, 0x4807506b,
+	0x836c0500, 0x00000007, 0x0c01f001, 0x001006e1,
+	0x001006c7, 0x001006c7, 0x001006af, 0x001006d4,
+	0x001006c7, 0x001006c7, 0x001006d4, 0x59a80005,
+	0x8c000514, 0x04020013, 0x59c40801, 0x82040d00,
+	0x00018000, 0x82040580, 0x00010000, 0x0400000a,
+	0x82040580, 0x00008000, 0x04000004, 0x42001000,
+	0x42004000, 0x0401f006, 0x42001000, 0x22002000,
+	0x0401f003, 0x42001000, 0x12001000, 0x0401f025,
+	0x42001000, 0x00001004, 0x0401f022, 0x59a80005,
+	0x8c000514, 0x04020008, 0x59a8006b, 0x8c000534,
+	0x04020004, 0x42001000, 0x74057005, 0x0401f819,
+	0x1c01f000, 0x42001000, 0x00002008, 0x0401f7fc,
+	0x59a8006b, 0x8c000534, 0x0402000a, 0x59a80005,
+	0x8c000514, 0x04000004, 0x42001000, 0x24052005,
+	0x0401f00c, 0x42001000, 0x74057005, 0x0401f009,
+	0x1c01f000, 0x1c01f000, 0x82081500, 0x0000001c,
+	0x82081540, 0x001c0000, 0x480bc013, 0x1c01f000,
+	0x59a8006b, 0x8c000530, 0x04000002, 0x84081570,
+	0x480b506b, 0x8c000530, 0x04020005, 0x82081500,
+	0x00007000, 0x80081114, 0x0401fff0, 0x1c01f000,
+	0x41780000, 0x50041800, 0x800c0400, 0x80040800,
+	0x80102040, 0x040207fc, 0x80080500, 0x80000540,
+	0x1c01f000, 0x4202f000, 0x00000000, 0x41780000,
+	0x41780800, 0x41781000, 0x41781800, 0x41782000,
+	0x41782800, 0x41783000, 0x41783800, 0x41784000,
+	0x41784800, 0x41785000, 0x41785800, 0x41786000,
+	0x41786800, 0x41787000, 0x41787800, 0x41788000,
+	0x41788800, 0x41789000, 0x41789800, 0x4178a000,
+	0x4178a800, 0x4178b000, 0x4178b800, 0x4178c000,
+	0x4178c800, 0x4178d000, 0x4178d800, 0x4178e000,
+	0x4178e800, 0x4178f000, 0x4178f800, 0x41790000,
+	0x41790800, 0x41791000, 0x41791800, 0x41792000,
+	0x41792800, 0x41793000, 0x41793800, 0x41794000,
+	0x41794800, 0x41795000, 0x41795800, 0x41796000,
+	0x41796800, 0x41797000, 0x41797800, 0x41798000,
+	0x41798800, 0x42019000, 0x0010b537, 0x42019800,
+	0x0010b50e, 0x4179a000, 0x4179b000, 0x4179a800,
+	0x4179b800, 0x4179c800, 0x4179c000, 0x4179d000,
+	0x4179d800, 0x4179e000, 0x4179e800, 0x4179f000,
+	0x4179f800, 0x417a0000, 0x417a0800, 0x417a1000,
+	0x417a1800, 0x417a2000, 0x42022800, 0x00006100,
+	0x417a3000, 0x417a3800, 0x417a4000, 0x417a4800,
+	0x417a5000, 0x417a5800, 0x417a6000, 0x417a6800,
+	0x417a7000, 0x417a7800, 0x417a8000, 0x417a8800,
+	0x417a9000, 0x417a9800, 0x417ae800, 0x417af800,
+	0x42030000, 0x00007c00, 0x42031000, 0x0010b806,
+	0x42031800, 0x0000bf1d, 0x42032000, 0x0000bf32,
+	0x42032800, 0x0010b7ce, 0x42033000, 0x0010b46e,
+	0x42034000, 0x0010b4a4, 0x42033800, 0x0010b4c3,
+	0x42034800, 0x0010b544, 0x42035000, 0x0010b400,
+	0x42035800, 0x0010ac00, 0x42030800, 0x0010b505,
+	0x417b6000, 0x42036800, 0x00006f00, 0x4203c800,
+	0x00003000, 0x42037000, 0x0000ff00, 0x42037800,
+	0x0000bf00, 0x42038000, 0x00007700, 0x42038800,
+	0x00004000, 0x42039000, 0x00006000, 0x42039800,
+	0x0010bedb, 0x4203a000, 0x00007600, 0x4203a800,
+	0x00007400, 0x4203b000, 0x00007200, 0x4203b800,
+	0x00007100, 0x4203c000, 0x00007000, 0x4203d000,
+	0x00000000, 0x4203e800, 0x00101b95, 0x417bd800,
+	0x1c01f000, 0x42000800, 0x00100000, 0x50040000,
+	0x4c000000, 0x42000000, 0x0000aaaa, 0x44000800,
+	0x42001800, 0x00005555, 0x41782000, 0x82102400,
+	0x00010000, 0x40100000, 0x80042c00, 0x440c2800,
+	0x42003000, 0x0000000a, 0x80183040, 0x040207ff,
+	0x50140000, 0x800c0580, 0x04020004, 0x50040000,
+	0x800c0580, 0x040207f2, 0x5c000000, 0x44000800,
+	0x80142840, 0x4817c861, 0x1c01f000, 0x59a8081f,
+	0x800409c0, 0x04020009, 0x49781c0c, 0x4a001a0c,
+	0x00000200, 0x4a001804, 0x07000000, 0x59a80010,
+	0x9c0001c0, 0x48001805, 0x0401fe01, 0x9c0409c0,
+	0x48041806, 0x1c01f000, 0x59a8080c, 0x4006d000,
+	0x4202b800, 0x00000001, 0x59a8180d, 0x480fc857,
+	0x82041400, 0x00000014, 0x82082400, 0x00000014,
+	0x40100000, 0x800c0480, 0x04001006, 0x44080800,
+	0x40080800, 0x40101000, 0x815eb800, 0x0401f7f7,
+	0x45780800, 0x495f5020, 0x1c01f000, 0x835c0480,
+	0x00000020, 0x04001009, 0x496bc857, 0x815eb840,
+	0x416a5800, 0x592ed000, 0x497a5800, 0x497a5801,
+	0x812e59c0, 0x1c01f000, 0x42000000, 0x0010b853,
+	0x0201f800, 0x0010aa47, 0x417a5800, 0x0401f7f9,
+	0x815eb840, 0x04001008, 0x416a5800, 0x492fc857,
+	0x592ed000, 0x497a5800, 0x497a5801, 0x812e59c0,
+	0x1c01f000, 0x42000000, 0x0010b853, 0x0201f800,
+	0x0010aa47, 0x417ab800, 0x417a5800, 0x0401f7f8,
+	0x492fc857, 0x496a5800, 0x412ed000, 0x815eb800,
+	0x59c80000, 0x82000540, 0x00001200, 0x48039000,
+	0x1c01f000, 0x492fc857, 0x812e59c0, 0x04000007,
+	0x592c0001, 0x497a5801, 0x4c000000, 0x0401fff1,
+	0x5c025800, 0x0401f7f9, 0x1c01f000, 0x4807c856,
+	0x42007000, 0x0010b7f8, 0x4a007001, 0x00000000,
+	0x59e00003, 0x82000540, 0x00008080, 0x4803c003,
+	0x4a03b805, 0x90000001, 0x59dc0006, 0x4a03b805,
+	0x70000000, 0x59dc0006, 0x4a03b805, 0x30000000,
+	0x4200b000, 0x00000020, 0x497bb807, 0x8058b040,
+	0x040207fe, 0x4a03b805, 0x30000000, 0x59dc0006,
+	0x4a03b805, 0x60000001, 0x59dc0006, 0x4a03b805,
+	0x70000001, 0x59dc0006, 0x4a03b805, 0x30000002,
+	0x4200b000, 0x00000020, 0x497bb807, 0x8058b040,
+	0x040207fe, 0x4a03b805, 0x30000000, 0x59dc0006,
+	0x4a03b805, 0x60000001, 0x0401ffa1, 0x04000da5,
+	0x42001000, 0x0010b7f6, 0x452c1000, 0x4a025801,
+	0x00000001, 0x4a025802, 0x00000100, 0x4a025809,
+	0x00107149, 0x497a580a, 0x497a580b, 0x497a580c,
+	0x0401ff93, 0x04000d97, 0x42001000, 0x0010b7f7,
+	0x452c1000, 0x4a025801, 0x00000000, 0x4a025802,
+	0x00000100, 0x4a025809, 0x001011bc, 0x497a5803,
+	0x497a5807, 0x497a5808, 0x497a580a, 0x59a80005,
+	0x8c00050e, 0x04000006, 0x4a03b805, 0xe0000001,
+	0x59dc0006, 0x8c000522, 0x040007fc, 0x1c01f000,
+	0x4df00000, 0x4203e000, 0x50000000, 0x4c380000,
+	0x40087000, 0x480bc857, 0x4a007002, 0x00000000,
+	0x42007000, 0x0010b7f8, 0x82080400, 0x00000000,
+	0x45780000, 0x58380005, 0x48087005, 0x80000540,
+	0x04000005, 0x82000400, 0x00000000, 0x44080000,
+	0x0401f003, 0x480bc857, 0x48087006, 0x58380001,
+	0x80000540, 0x0400080c, 0x5c007000, 0x5c03e000,
+	0x1c01f000, 0x4c380000, 0x42007000, 0x0010b7f8,
+	0x58380001, 0x80000540, 0x04000803, 0x5c007000,
+	0x1c01f000, 0x42007000, 0x0010b7f8, 0x58380001,
+	0x82000580, 0x00000000, 0x04020012, 0x58380000,
+	0x0c01f001, 0x0010088e, 0x0010088d, 0x0010088d,
+	0x0010088d, 0x0010088d, 0x0010088d, 0x0010088d,
+	0x0010088d, 0x0401fd4b, 0x58380808, 0x800409c0,
+	0x04020024, 0x58380006, 0x80000540, 0x04020002,
+	0x1c01f000, 0x4803c857, 0x48007002, 0x40006800,
+	0x58340000, 0x80000540, 0x04020002, 0x48007005,
+	0x48007006, 0x4a03b805, 0x20000000, 0x59dc0006,
+	0x4a03b805, 0x30000000, 0x58340007, 0x4803b800,
+	0x58340008, 0x4803b801, 0x58340004, 0x48007003,
+	0x58340003, 0x48007004, 0x4803b803, 0x58340001,
+	0x8c000500, 0x04000004, 0x4a007001, 0x00000001,
+	0x0401f028, 0x4a007001, 0x00000002, 0x0401f03d,
+	0x0201f800, 0x001093ea, 0x0201f800, 0x0010a69d,
+	0x04000017, 0x4a03b805, 0x20000000, 0x59dc0006,
+	0x4a03b805, 0x30000000, 0x4807b800, 0x480bb801,
+	0x4a007003, 0x00000010, 0x480c7009, 0x42001000,
+	0x00100875, 0x0201f800, 0x00105f9a, 0x58380008,
+	0x82000400, 0x00000004, 0x48007004, 0x4803b803,
+	0x4a007001, 0x00000007, 0x0401f022, 0x0201f800,
+	0x00109402, 0x42000800, 0x00000001, 0x42001000,
+	0x00100875, 0x0201f800, 0x00105f76, 0x0401f7ba,
+	0x4c040000, 0x4c080000, 0x58380803, 0x42001000,
+	0x00003fff, 0x82040480, 0x00003fff, 0x04021003,
+	0x40041000, 0x80000580, 0x48007003, 0x800800c4,
+	0x4803b802, 0x4a03b805, 0x30000002, 0x59dc0006,
+	0x4a03b805, 0x70000001, 0x59dc0006, 0x4a03b805,
+	0x10000000, 0x5c001000, 0x5c000800, 0x1c01f000,
+	0x483bc857, 0x4c040000, 0x4c080000, 0x58380803,
+	0x42001000, 0x00003fff, 0x82040480, 0x00003fff,
+	0x04021003, 0x40041000, 0x80000580, 0x48007003,
+	0x800800c4, 0x4803b802, 0x4a03b805, 0x10000002,
+	0x5c001000, 0x5c000800, 0x1c01f000, 0x4c040000,
+	0x4c380000, 0x42007000, 0x0010b7f8, 0x59dc0806,
+	0x4807c857, 0x4a03b805, 0x20000000, 0x8c040d3e,
+	0x04000007, 0x8c040d08, 0x04020cca, 0x58380001,
+	0x82000500, 0x00000007, 0x0c01f804, 0x5c007000,
+	0x5c000800, 0x1c01f000, 0x0010087d, 0x0010091e,
+	0x0010092e, 0x001005d8, 0x001005d8, 0x001005d8,
+	0x001005d8, 0x001011ea, 0x4807c856, 0x82040d00,
+	0x43000f80, 0x04020009, 0x58380003, 0x80000540,
+	0x0400001c, 0x59dc0000, 0x4803b800, 0x59dc0001,
+	0x4803b801, 0x0401f7af, 0x58380802, 0x4a000802,
+	0x00000200, 0x0401f01e, 0x4807c856, 0x82040d00,
+	0x43000f80, 0x04020009, 0x58380003, 0x80000540,
+	0x0400000c, 0x59dc0000, 0x4803b800, 0x59dc0001,
+	0x4803b801, 0x0401f7b7, 0x58380002, 0x82000400,
+	0x00000002, 0x46000000, 0x00000200, 0x0401f00c,
+	0x4c340000, 0x58386802, 0x59dc0000, 0x4803c857,
+	0x48006807, 0x59dc0001, 0x4803c857, 0x48006808,
+	0x4a006802, 0x00000100, 0x5c006800, 0x4a007001,
+	0x00000000, 0x4c300000, 0x58386002, 0x0401f80c,
+	0x04000009, 0x58300009, 0x82000c80, 0x0010ab4a,
+	0x04021c84, 0x82000c80, 0x00020000, 0x04001c81,
+	0x0801f800, 0x5c006000, 0x0401f723, 0x4833c857,
+	0x803061c0, 0x04000009, 0x59a8000c, 0x80300480,
+	0x04001007, 0x59a8000d, 0x80300480, 0x04021004,
+	0x82000540, 0x00000001, 0x1c01f000, 0x80000580,
+	0x1c01f000, 0x4803c856, 0x4dc00000, 0x42007000,
+	0x0010b803, 0x4a007400, 0x00000000, 0x49787001,
+	0x42038000, 0x00007720, 0x4a038006, 0x60000001,
+	0x4a038009, 0xf4f60000, 0x42038000, 0x00007700,
+	0x4a038006, 0x60000001, 0x4a038009, 0xf4f60000,
+	0x4a03c822, 0x00000010, 0x4a0370e8, 0x00000000,
+	0x0401f809, 0x4a0370e9, 0x00003a0f, 0x4a0370e8,
+	0x00000000, 0x4a0370e8, 0x00000001, 0x5c038000,
+	0x1c01f000, 0x4c5c0000, 0x4178b800, 0x0401f80a,
+	0x5c00b800, 0x1c01f000, 0x4803c856, 0x4c5c0000,
+	0x825cbd40, 0x00000001, 0x0401f803, 0x5c00b800,
+	0x1c01f000, 0x4803c856, 0x4dc00000, 0x4c500000,
+	0x4c580000, 0x4c540000, 0x4a0370e8, 0x00000000,
+	0x805cb9c0, 0x04000009, 0x4a038807, 0x00000004,
+	0x59b800ea, 0x8c000510, 0x04000004, 0x59b800e0,
+	0x0401f87b, 0x0401f7fb, 0x42038000, 0x00007720,
+	0x0201f800, 0x00100ec1, 0x59c00007, 0x4a038006,
+	0x20000000, 0x59c00007, 0x4a038006, 0x8000000a,
+	0x59c00007, 0x4a038006, 0x8000000b, 0x59c00007,
+	0x4a038006, 0x40000001, 0x83c00580, 0x00007700,
+	0x04000004, 0x42038000, 0x00007700, 0x0401f7ed,
+	0x42038000, 0x00007720, 0x42000800, 0x00000800,
+	0x59c00007, 0x8c00051e, 0x04000006, 0x4a038006,
+	0x90000001, 0x80040840, 0x040207fa, 0x0401fc11,
+	0x83c00580, 0x00007700, 0x04000004, 0x42038000,
+	0x00007700, 0x0401f7f1, 0x805cb9c0, 0x0402001d,
+	0x4200b000, 0x00000020, 0x83b8ac00, 0x00000020,
+	0x0201f800, 0x0010ab20, 0x4a0370fb, 0x00000001,
+	0x4a037020, 0x001010bd, 0x59a80039, 0x82000500,
+	0x0000ffff, 0x48037021, 0x4a037035, 0x0010bddb,
+	0x4a037030, 0x0010b410, 0x4a037031, 0x0010ac00,
+	0x4a037032, 0x0010b519, 0x4a037036, 0x0010b524,
+	0x59840002, 0x48037034, 0x4a037038, 0x001010b4,
+	0x4a0370fb, 0x00000001, 0x4178a000, 0x4200b000,
+	0x00000020, 0x83b8ac00, 0x00000000, 0x0201f800,
+	0x0010ab20, 0x4200b000, 0x00000040, 0x83b8ac00,
+	0x00000040, 0x0201f800, 0x0010ab20, 0x805cb9c0,
+	0x04020004, 0x4a0370e4, 0xaaaaaaaa, 0x0401f003,
+	0x4a0370e4, 0xa2aaaa82, 0x4a0370e5, 0xaaaaaaaa,
+	0x4a0370e6, 0xaaaaaaaa, 0x4a0370fb, 0x00000000,
+	0x4a0370e6, 0xaaaaaaaa, 0x42038000, 0x00007720,
+	0x4a038006, 0x90000000, 0x59c00007, 0x8c00051e,
+	0x02020800, 0x001005d8, 0x42038000, 0x00007700,
+	0x4a038006, 0x90000000, 0x59c00007, 0x8c00051e,
+	0x02020800, 0x001005d8, 0x5c00a800, 0x5c00b000,
+	0x5c00a000, 0x5c038000, 0x1c01f000, 0x4d300000,
+	0x4d380000, 0x40026000, 0x82000500, 0x7f000000,
+	0x82000580, 0x00000003, 0x0402000f, 0x83326500,
+	0x00ffffff, 0x59300203, 0x82000580, 0x00000004,
+	0x04020009, 0x59300c06, 0x82040580, 0x00000009,
+	0x04020005, 0x42027000, 0x00000047, 0x0201f800,
+	0x000207a1, 0x5c027000, 0x5c026000, 0x1c01f000,
+	0x4d300000, 0x4d2c0000, 0x4d340000, 0x4d400000,
+	0x4cfc0000, 0x4d380000, 0x4d3c0000, 0x4d440000,
+	0x4d4c0000, 0x4d480000, 0x4c5c0000, 0x4c600000,
+	0x4c640000, 0x4cc80000, 0x4ccc0000, 0x4cf00000,
+	0x4cf40000, 0x4cf80000, 0x4cfc0000, 0x4d000000,
+	0x4d040000, 0x0201f800, 0x00020015, 0x5c020800,
+	0x5c020000, 0x5c01f800, 0x5c01f000, 0x5c01e800,
+	0x5c01e000, 0x5c019800, 0x5c019000, 0x5c00c800,
+	0x5c00c000, 0x5c00b800, 0x5c029000, 0x5c029800,
+	0x5c028800, 0x5c027800, 0x5c027000, 0x5c01f800,
+	0x5c028000, 0x5c026800, 0x5c025800, 0x5c026000,
+	0x1c01f000, 0x493bc857, 0x0201f000, 0x00020044,
+	0x83300500, 0x1f000000, 0x04000008, 0x81326580,
+	0x80000130, 0x82000c80, 0x00000014, 0x02021800,
+	0x001005d8, 0x0c01f013, 0x83300500, 0x000000ff,
+	0x82000c80, 0x00000007, 0x02021800, 0x001005d8,
+	0x0c01f025, 0x1c01f000, 0x82000d00, 0xc0000038,
+	0x02020800, 0x001005d0, 0x0201f800, 0x001005d8,
+	0x00000000, 0x00000048, 0x00000054, 0x00000053,
+	0x00100a9b, 0x00100abf, 0x00100aba, 0x00100adf,
+	0x00100aa6, 0x00100ab2, 0x00100a9b, 0x00100ada,
+	0x00100b1a, 0x00100a9b, 0x00100a9b, 0x00100a9b,
+	0x00100a9b, 0x00100b1d, 0x00100b23, 0x00100b34,
+	0x00100b45, 0x00100a9b, 0x00100b4e, 0x00100b5a,
+	0x00100a9b, 0x00100a9b, 0x00100a9b, 0x0201f800,
+	0x001005d8, 0x00100aa4, 0x00100bff, 0x00100aec,
+	0x00100b0f, 0x00100aa4, 0x00100aa4, 0x00100aa4,
+	0x0201f800, 0x001005d8, 0x4803c856, 0x59300004,
+	0x8c00053e, 0x04020005, 0x42027000, 0x00000055,
+	0x0201f000, 0x000207a1, 0x0201f800, 0x00106f60,
+	0x040007fa, 0x1c01f000, 0x4803c856, 0x0401f8a9,
+	0x40002800, 0x41782000, 0x42027000, 0x00000056,
+	0x0201f000, 0x000207a1, 0x4803c856, 0x42027000,
+	0x00000057, 0x0201f000, 0x000207a1, 0x4803c856,
+	0x59300007, 0x8c00051a, 0x04020010, 0x59325808,
+	0x812e59c0, 0x04000014, 0x592c0408, 0x8c00051c,
+	0x04020003, 0x4a026011, 0xffffffff, 0x59300004,
+	0x8c00053e, 0x04020009, 0x42027000, 0x00000048,
+	0x0201f000, 0x000207a1, 0x59325808, 0x4a025a06,
+	0x00000007, 0x0401f7f4, 0x0201f800, 0x00106f60,
+	0x040007f6, 0x1c01f000, 0x4803c856, 0x83300500,
+	0x00ffffff, 0x0201f000, 0x001064d7, 0x1c01f000,
+	0x4c040000, 0x59b808ea, 0x82040d00, 0x00000007,
+	0x82040580, 0x00000003, 0x04000004, 0x42000000,
+	0x60000000, 0x0401f8ab, 0x5c000800, 0x1c01f000,
+	0x0401f8f9, 0x59325808, 0x812e59c0, 0x04000018,
+	0x592c0204, 0x82000500, 0x000000ff, 0x82000d80,
+	0x00000029, 0x04020012, 0x59300203, 0x82000580,
+	0x00000003, 0x0400000b, 0x59300807, 0x84040d26,
+	0x48066007, 0x0201f800, 0x00020086, 0x4a03900d,
+	0x00000040, 0x4a0370e5, 0x00000008, 0x1c01f000,
+	0x0201f800, 0x00106f60, 0x040007f4, 0x59880052,
+	0x80000000, 0x48031052, 0x4a03900d, 0x00000040,
+	0x42000000, 0xc0000000, 0x0401f05a, 0x42007800,
+	0x0010bde2, 0x42002000, 0x00003000, 0x42003000,
+	0x00000105, 0x0201f800, 0x00105e04, 0x4a0370e4,
+	0x02000000, 0x1c01f000, 0x4933c857, 0x0201f000,
+	0x0002077d, 0x41300800, 0x800409c0, 0x02020800,
+	0x001005d8, 0x0201f800, 0x001005d0, 0x4933c857,
+	0x813261c0, 0x02000800, 0x001005d8, 0x0401f835,
+	0x40002800, 0x0201f800, 0x0010a99c, 0x0401f8ae,
+	0x04000007, 0x59326809, 0x59340200, 0x8c00050e,
+	0x59300414, 0x02020800, 0x001092ce, 0x1c01f000,
+	0x4933c857, 0x813261c0, 0x02000800, 0x001005d8,
+	0x0401f8a1, 0x0400000b, 0x59325808, 0x0201f800,
+	0x00109037, 0x04000007, 0x592c0208, 0x8400054e,
+	0x48025a08, 0x417a7800, 0x0201f800, 0x00108be3,
+	0x1c01f000, 0x485fc857, 0x5c000000, 0x4d780000,
+	0x4203e000, 0x50000000, 0x4200b800, 0x00008005,
+	0x0201f000, 0x001005dd, 0x4933c857, 0x83300480,
+	0x00000020, 0x02021800, 0x001005d8, 0x83300c00,
+	0x0010b8cc, 0x50040000, 0x80000000, 0x04001002,
+	0x44000800, 0x1c01f000, 0x4933c857, 0x0401f7f4,
+	0x4807c856, 0x59b800ea, 0x8c000510, 0x040007fd,
+	0x59b800e0, 0x4803c857, 0x1c01f000, 0x4803c856,
+	0x42000000, 0x10000000, 0x41300800, 0x0401f02d,
+	0x82000500, 0xf0000000, 0x82040d00, 0x0fffffff,
+	0x80040d40, 0x4807c857, 0x59b800ea, 0x8c000516,
+	0x04020003, 0x480770e1, 0x1c01f000, 0x8c000510,
+	0x040007fa, 0x4c040000, 0x0401f809, 0x5c000800,
+	0x82100480, 0x00000008, 0x040017f4, 0x4c040000,
+	0x0401febc, 0x5c000800, 0x0401f7f0, 0x59b800e2,
+	0x59b820e2, 0x80100580, 0x040207fd, 0x80102114,
+	0x0401f006, 0x59b800e2, 0x59b820e2, 0x80100580,
+	0x040207fd, 0x0401f001, 0x40101800, 0x800c190a,
+	0x82100500, 0x0000001f, 0x820c1d00, 0x0000001f,
+	0x800c2480, 0x82102500, 0x0000001f, 0x1c01f000,
+	0x82000500, 0xf0000000, 0x82040d00, 0x0fffffff,
+	0x80040d40, 0x4807c857, 0x42001000, 0x0010b804,
+	0x50080000, 0x80000540, 0x04020005, 0x4a0370e5,
+	0x00000003, 0x4a0370e4, 0x00000300, 0x80000000,
+	0x44001000, 0x42001000, 0x00000400, 0x59b800ea,
+	0x8c000510, 0x0400000c, 0x0401ffd5, 0x82100480,
+	0x00000008, 0x04001007, 0x4c040000, 0x4c080000,
+	0x0401fe88, 0x5c001000, 0x5c000800, 0x0401f020,
+	0x59b800ea, 0x8c000516, 0x0402001d, 0x4a0370e4,
+	0x00300000, 0x480770e1, 0x42001000, 0x0000ff00,
+	0x80081040, 0x04000012, 0x59b808e4, 0x8c040d28,
+	0x040207fc, 0x42001000, 0x0010b804, 0x50080000,
+	0x80000040, 0x04020005, 0x4a0370e5, 0x00000002,
+	0x4a0370e4, 0x00000200, 0x02001800, 0x001005d8,
+	0x44001000, 0x8c040d2c, 0x1c01f000, 0x41f80000,
+	0x50000000, 0x0201f800, 0x001005d8, 0x80081040,
+	0x040207d3, 0x41f80000, 0x50000000, 0x0201f800,
+	0x001005d8, 0x4d380000, 0x59300c06, 0x82040580,
+	0x00000009, 0x04020006, 0x42027000, 0x00000047,
+	0x0201f800, 0x000207a1, 0x80000580, 0x5c027000,
+	0x1c01f000, 0x4c500000, 0x4a03900d, 0x00000001,
+	0x59c8a020, 0x4a03900d, 0x00000002, 0x59c80820,
+	0x8c50a52e, 0x04000002, 0x900409c0, 0x82040d00,
+	0x0000ffff, 0x0201f800, 0x00105dd7, 0x02000800,
+	0x001005d8, 0x4933c857, 0x8250a500, 0xff000000,
+	0x82500580, 0x05000000, 0x04000003, 0x82000540,
+	0x00000001, 0x5c00a000, 0x1c01f000, 0x0401ffe6,
+	0x4933c857, 0x59300406, 0x82000580, 0x00000000,
+	0x04000040, 0x59c82021, 0x4a03900d, 0x00000001,
+	0x59c82821, 0x82142d00, 0x0000ffff, 0x59325808,
+	0x812e59c0, 0x04000037, 0x59326809, 0x0201f800,
+	0x001048d9, 0x02020800, 0x001092b6, 0x599c0019,
+	0x8c00050c, 0x04020018, 0x0201f800, 0x001048d9,
+	0x04020015, 0x59300811, 0x4807c857, 0x592c0408,
+	0x8c00051c, 0x0402000e, 0x8400055c, 0x48025c08,
+	0x592c0a04, 0x82040d00, 0x000000ff, 0x82040580,
+	0x00000048, 0x04000004, 0x82040580, 0x00000018,
+	0x04020003, 0x59300811, 0x48065803, 0x4a026011,
+	0x7fffffff, 0x48166013, 0x0201f800, 0x001010dd,
+	0x04020014, 0x0401f9fd, 0x40280000, 0x4802600d,
+	0x04000005, 0x4832600b, 0x50200000, 0x4802600a,
+	0x4822600c, 0x59300414, 0x8c00051c, 0x04020004,
+	0x599c0019, 0x8c00050c, 0x0402086e, 0x4a03900d,
+	0x00000040, 0x4a0370e5, 0x00000008, 0x1c01f000,
+	0x59880052, 0x80000000, 0x48031052, 0x4a03900d,
+	0x00000040, 0x42000000, 0xc0000000, 0x0401f71d,
+	0x4cf80000, 0x58f40000, 0x8001f540, 0x0401f820,
+	0x41781800, 0x0401f8e4, 0x04020014, 0x44140800,
+	0x0401f82a, 0x04000011, 0x40043800, 0x42001800,
+	0x00000001, 0x40142000, 0x0401f8db, 0x0402000b,
+	0x801c3800, 0x501c0000, 0x44000800, 0x0401f810,
+	0x801c0580, 0x04000004, 0x44103800, 0x801c3840,
+	0x44143800, 0x0401f819, 0x5c01f000, 0x1c01f000,
+	0x80f9f1c0, 0x04020003, 0x58f41202, 0x0401f003,
+	0x42001000, 0x00000007, 0x1c01f000, 0x80f9f1c0,
+	0x04020006, 0x58f40401, 0x82000480, 0x00000002,
+	0x80f40400, 0x0401f005, 0x58f80401, 0x82000480,
+	0x00000002, 0x80f80400, 0x50002800, 0x80000000,
+	0x50002000, 0x1c01f000, 0x80f9f1c0, 0x04020008,
+	0x58f40401, 0x82000480, 0x00000002, 0x02001800,
+	0x001005d8, 0x4801ec01, 0x0401f00b, 0x58f80401,
+	0x82000480, 0x00000002, 0x02001800, 0x001005d8,
+	0x4801f401, 0x82000580, 0x00000002, 0x04020002,
+	0x0401f809, 0x58f40202, 0x80000040, 0x4801ea02,
+	0x02000800, 0x001005d8, 0x82000580, 0x00000001,
+	0x1c01f000, 0x4d2c0000, 0x40fa5800, 0x0201f800,
+	0x001007f4, 0x4979e800, 0x4179f000, 0x5c025800,
+	0x1c01f000, 0x80f5e9c0, 0x04000009, 0x80f9f1c0,
+	0x04020ff5, 0x4d2c0000, 0x40f65800, 0x0201f800,
+	0x001007f4, 0x4179e800, 0x5c025800, 0x1c01f000,
+	0x4cf40000, 0x59300807, 0x82040500, 0x00003100,
+	0x04020032, 0x8c040d22, 0x04000032, 0x5930001f,
+	0x8001ed40, 0x02000800, 0x001005d8, 0x82000580,
+	0xffffffff, 0x04000029, 0x58f40201, 0x82000580,
+	0x0000dcb3, 0x02020800, 0x001005d8, 0x58f40a02,
+	0x82040500, 0x0000fffe, 0x04000003, 0x0401ff89,
+	0x58f40a02, 0x82040480, 0x0000000f, 0x04021059,
+	0x80040800, 0x4805ea02, 0x82040580, 0x00000008,
+	0x0400005d, 0x82040480, 0x00000008, 0x0400100a,
+	0x58f40000, 0x8001ed40, 0x02000800, 0x001005d8,
+	0x58f40201, 0x82000580, 0x0000ddb9, 0x02020800,
+	0x001005d8, 0x58f40401, 0x82000c00, 0x00000002,
+	0x4805ec01, 0x80f40400, 0x59300812, 0x44040000,
+	0x80000000, 0x45780000, 0x5c01e800, 0x1c01f000,
+	0x42001000, 0x00000400, 0x59b800e4, 0x8c000524,
+	0x04020023, 0x4a0370e4, 0x00030000, 0x40000000,
+	0x59b800e4, 0x8c000524, 0x0402001b, 0x59300807,
+	0x84040d62, 0x48066007, 0x4a0370e4, 0x00020000,
+	0x4d2c0000, 0x0201f800, 0x001007d3, 0x04000025,
+	0x492e601f, 0x4a025a01, 0x0000dcb3, 0x59300008,
+	0x80001d40, 0x02000800, 0x001005d8, 0x580c080f,
+	0x48065803, 0x59301811, 0x40040000, 0x800c0580,
+	0x0402000d, 0x497a5a02, 0x4a025c01, 0x00000004,
+	0x0401f011, 0x4a0370e4, 0x00020000, 0x40000000,
+	0x40000000, 0x80081040, 0x02000800, 0x001005d8,
+	0x0401f7d6, 0x4a025a02, 0x00000001, 0x4a025c01,
+	0x00000006, 0x497a5804, 0x400c0000, 0x80040480,
+	0x48025805, 0x412de800, 0x5c025800, 0x0401f7a9,
+	0x5c025800, 0x4a02601f, 0xffffffff, 0x0401f7c3,
+	0x4d2c0000, 0x58f65800, 0x0201f800, 0x001007f4,
+	0x40f65800, 0x0201f800, 0x001007f4, 0x5c025800,
+	0x0401f7f5, 0x4d2c0000, 0x0201f800, 0x001007d3,
+	0x040007f8, 0x4a025a01, 0x0000ddb9, 0x4a025c01,
+	0x00000002, 0x492de800, 0x412de800, 0x5c025800,
+	0x0401f7a5, 0x0401ff33, 0x82f40400, 0x00000004,
+	0x800c0400, 0x40000800, 0x50040000, 0x80100580,
+	0x04000016, 0x82040c00, 0x00000002, 0x80081040,
+	0x040207fa, 0x80f9f1c0, 0x04000011, 0x58f41202,
+	0x82081480, 0x00000007, 0x82f80400, 0x00000002,
+	0x800c0400, 0x40000800, 0x50040000, 0x80100580,
+	0x04000006, 0x82040c00, 0x00000002, 0x80081040,
+	0x040207fa, 0x0401f002, 0x1c01f000, 0x82000540,
+	0x00000001, 0x0401f7fd, 0x4cf40000, 0x4cf80000,
+	0x4001e800, 0x592c0a06, 0x800409c0, 0x0402001d,
+	0x82f40580, 0xffffffff, 0x04000017, 0x58f40201,
+	0x82000580, 0x0000dcb3, 0x02020800, 0x001005d8,
+	0x58f40000, 0x8001f540, 0x04000006, 0x58f80201,
+	0x82000580, 0x0000ddb9, 0x02020800, 0x001005d8,
+	0x41783800, 0x0401f839, 0x04020006, 0x0401ff32,
+	0x497a601f, 0x5c01f000, 0x5c01e800, 0x1c01f000,
+	0x0401ff2d, 0x4a025a06, 0x00000011, 0x0401f7f9,
+	0x82f40580, 0xffffffff, 0x04020f27, 0x0401f7f5,
+	0x4cf40000, 0x4cf80000, 0x4001e800, 0x82040580,
+	0x00000001, 0x0402001f, 0x82f40580, 0xffffffff,
+	0x04000019, 0x58f40201, 0x82000580, 0x0000dcb3,
+	0x02020800, 0x001005d8, 0x58f40000, 0x8001f540,
+	0x04000006, 0x58f80201, 0x82000580, 0x0000ddb9,
+	0x02020800, 0x001005d8, 0x41783800, 0x0401f813,
+	0x04020008, 0x0401ff0c, 0x42000800, 0x00000001,
+	0x497a601f, 0x5c01f000, 0x5c01e800, 0x1c01f000,
+	0x0401ff05, 0x42000800, 0x00000011, 0x0401f7f9,
+	0x4c040000, 0x82f40580, 0xffffffff, 0x04020efe,
+	0x5c000800, 0x0401f7f3, 0x4803c856, 0x401c2000,
+	0x41781800, 0x0401ff8c, 0x0402002c, 0x58f42003,
+	0x42001800, 0x00000001, 0x0401ff87, 0x04020027,
+	0x0401feb8, 0x40082800, 0x82f40400, 0x00000004,
+	0x40003000, 0x50182000, 0x40100000, 0x801c0580,
+	0x04000005, 0x42001800, 0x00000001, 0x0401ff7a,
+	0x0402001a, 0x82183400, 0x00000002, 0x80142840,
+	0x040207f5, 0x80f9f1c0, 0x04000013, 0x58f42a02,
+	0x82142c80, 0x00000007, 0x82f80400, 0x00000003,
+	0x40003000, 0x50182000, 0x40100000, 0x801c0580,
+	0x04000005, 0x42001800, 0x00000001, 0x0401ff66,
+	0x04020006, 0x82183400, 0x00000002, 0x80142840,
+	0x040207f5, 0x1c01f000, 0x82000540, 0x00000001,
+	0x0401f7fd, 0x0201f800, 0x001005d8, 0x58380207,
+	0x8c000502, 0x040007fc, 0x50200000, 0x80387c00,
+	0x583c2800, 0x583c2001, 0x58380404, 0x80001540,
+	0x04020002, 0x58381407, 0x58c83401, 0x58380c08,
+	0x59303807, 0x497a6012, 0x497a6013, 0x0201f000,
+	0x000200be, 0x592c0408, 0x8c000502, 0x040007ea,
+	0x592c0409, 0x80000540, 0x040007e7, 0x82000c80,
+	0x00000002, 0x04001011, 0x58380001, 0x80007540,
+	0x02000800, 0x001005d8, 0x58380204, 0x82000500,
+	0x0000000f, 0x82000400, 0x001010bd, 0x50004000,
+	0x40040000, 0x800409c0, 0x04000005, 0x82040c80,
+	0x00000005, 0x040217f1, 0x80204400, 0x50200000,
+	0x80387c00, 0x583c2800, 0x583c2001, 0x583c1002,
+	0x592c0a07, 0x592c4c08, 0x592c300d, 0x59303807,
+	0x497a6012, 0x497a6013, 0x4816600e, 0x4812600f,
+	0x480a6010, 0x481a6011, 0x80040840, 0x4806600d,
+	0x02000000, 0x000200c6, 0x80204000, 0x50201800,
+	0x800c19c0, 0x0402000c, 0x58380001, 0x80007540,
+	0x02000800, 0x001005d8, 0x58380204, 0x82000500,
+	0x0000000f, 0x82000400, 0x001010bd, 0x50004000,
+	0x50201800, 0x483a600b, 0x480e600a, 0x4822600c,
+	0x0201f000, 0x000200c6, 0x4803c856, 0x592c0208,
+	0x8c00051e, 0x04020017, 0x50200000, 0x80306c00,
+	0x40240000, 0x0c01f001, 0x00100e46, 0x00100e46,
+	0x00100e4f, 0x00100e46, 0x00100e46, 0x00100e46,
+	0x00100e46, 0x00100e46, 0x00100e4f, 0x00100e46,
+	0x00100e4f, 0x00100e46, 0x00100e46, 0x00100e4f,
+	0x00100e46, 0x00100e46, 0x0201f800, 0x001005d8,
+	0x8400051e, 0x48025a08, 0x50200000, 0x80306c00,
+	0x58343801, 0x481e600f, 0x0401f007, 0x58341802,
+	0x58342800, 0x58343801, 0x480e6010, 0x4816600e,
+	0x481e600f, 0x0401f246, 0x4933c857, 0x5931f808,
+	0x59300a06, 0x800409c0, 0x04000005, 0x80040906,
+	0x04020002, 0x80040800, 0x4805fc06, 0x4a026206,
+	0x00000002, 0x592c0409, 0x82000500, 0x00000008,
+	0x0400000b, 0x0401f834, 0x59300203, 0x82000580,
+	0x00000004, 0x04020005, 0x42027000, 0x00000048,
+	0x0201f800, 0x000207a1, 0x1c01f000, 0x4cfc0000,
+	0x58fc0204, 0x82000500, 0x000000ff, 0x82000580,
+	0x00000048, 0x0402000c, 0x58fc000b, 0x800001c0,
+	0x04000009, 0x58fc0407, 0x800001c0, 0x04000006,
+	0x58fc080b, 0x8c040d16, 0x04000017, 0x58fc0007,
+	0x0401f00a, 0x58fc0408, 0x8c000512, 0x04020014,
+	0x58fc0c09, 0x8c040d16, 0x04020003, 0x5c01f800,
+	0x1c01f000, 0x58fc000a, 0x59300811, 0x80040580,
+	0x04020009, 0x59300007, 0x84000500, 0x48026007,
+	0x42027000, 0x00000048, 0x5c01f800, 0x0201f000,
+	0x000207a1, 0x5c01f800, 0x1c01f000, 0x58fdf809,
+	0x0401f7ec, 0x4933c857, 0x59b808ea, 0x82040d00,
+	0x00000007, 0x82040580, 0x00000000, 0x0400001e,
+	0x82040580, 0x00000003, 0x0400001b, 0x59300406,
+	0x4c000000, 0x4a026406, 0x00000000, 0x42003000,
+	0x00000041, 0x42000000, 0x50000000, 0x41300800,
+	0x4c180000, 0x0401fce7, 0x5c003000, 0x0400000b,
+	0x42000000, 0x0000001e, 0x80000040, 0x040207ff,
+	0x80183040, 0x040207f4, 0x42000000, 0x40000000,
+	0x41300800, 0x0401fcdb, 0x5c000000, 0x48026406,
+	0x1c01f000, 0x59300007, 0x84000500, 0x48026007,
+	0x0401f7fc, 0x59c00007, 0x4a038006, 0x30000000,
+	0x40000000, 0x59c00007, 0x8c00050a, 0x040207fe,
+	0x1c01f000, 0x5c000000, 0x4c000000, 0x4803c857,
+	0x4dc00000, 0x4a0370e8, 0x00000000, 0x42038000,
+	0x00007720, 0x0401fff0, 0x42038000, 0x00007700,
+	0x0401ffed, 0x0201f800, 0x0010513b, 0x04020013,
+	0x4a038891, 0x0000ffff, 0x497b8880, 0x497b8892,
+	0x42001000, 0x00000190, 0x40000000, 0x40000000,
+	0x80081040, 0x040207fd, 0x42000000, 0x0010b8a6,
+	0x0201f800, 0x0010aa47, 0x0401f80e, 0x5c038000,
+	0x0201f000, 0x00105258, 0x0401f82d, 0x42000000,
+	0x0010b8a7, 0x0201f800, 0x0010aa47, 0x0401f805,
+	0x48178892, 0x480b8880, 0x5c038000, 0x1c01f000,
+	0x496fc857, 0x836c0580, 0x00000003, 0x0402000b,
+	0x4c080000, 0x4c0c0000, 0x42001000, 0x00008048,
+	0x42001800, 0x0000ffff, 0x0201f800, 0x00103a3e,
+	0x5c001800, 0x5c001000, 0x42000800, 0x0000003c,
+	0x0201f800, 0x00101345, 0x59a8006c, 0x80000540,
+	0x04000006, 0x59a8106d, 0x800811c0, 0x04000003,
+	0x0201f800, 0x00101aaf, 0x4a038891, 0x0000ffff,
+	0x4a03900d, 0x00000040, 0x0201f800, 0x0010098e,
+	0x4a0370e8, 0x00000001, 0x1c01f000, 0x5c000000,
+	0x4c000000, 0x4803c857, 0x59c41080, 0x497b8880,
+	0x59c42892, 0x497b8892, 0x0201f800, 0x0010513b,
+	0x04020002, 0x1c01f000, 0x42002000, 0x00000260,
+	0x59c418a4, 0x820c1d00, 0x0000000f, 0x820c0580,
+	0x00000000, 0x04000010, 0x59c41805, 0x820c1d00,
+	0x00000001, 0x0402000e, 0x59c418a4, 0x820c1d00,
+	0x0000000f, 0x820c0480, 0x00000007, 0x04001004,
+	0x820c0480, 0x0000000c, 0x04001003, 0x80102040,
+	0x040207ec, 0x497b8891, 0x1c01f000, 0x4c100000,
+	0x42002000, 0x00000019, 0x46000000, 0x00000001,
+	0x0201f800, 0x00101937, 0x50001800, 0x820c1d00,
+	0x00000001, 0x04000005, 0x80102040, 0x040207f7,
+	0x5c002000, 0x0401f7f0, 0x5c002000, 0x0401f7ec,
+	0x4803c856, 0x1c01f000, 0x4d2c0000, 0x59325808,
+	0x592c0a04, 0x4807c857, 0x82040d00, 0x000000ff,
+	0x82040500, 0x0000000f, 0x0c01f001, 0x00100f67,
+	0x00100f67, 0x00100f67, 0x00100f7f, 0x00100f67,
+	0x00100f67, 0x00100f67, 0x00100f67, 0x00100f67,
+	0x00100f7f, 0x00100f67, 0x00100f69, 0x00100f67,
+	0x00100f67, 0x00100f67, 0x00100f67, 0x0201f800,
+	0x001005d8, 0x82040580, 0x0000003b, 0x02020800,
+	0x001005d8, 0x592c020a, 0x8c000500, 0x0400005f,
+	0x592c1a07, 0x82040500, 0x0000000f, 0x82000400,
+	0x001010bd, 0x50001000, 0x50080000, 0x59302013,
+	0x4802600a, 0x492e600b, 0x480a600c, 0x480e600d,
+	0x48126012, 0x5c025800, 0x1c01f000, 0x82040500,
+	0x0000000f, 0x82000400, 0x001010bd, 0x50001000,
+	0x50080000, 0x592c1a07, 0x4802600a, 0x492e600b,
+	0x480a600c, 0x480e600d, 0x497a6012, 0x0401f7f2,
+	0x8c040d00, 0x04020041, 0x82040d00, 0x00000080,
+	0x0400003e, 0x0201f000, 0x000200cf, 0x59300013,
+	0x59301012, 0x80080580, 0x0402000c, 0x42007800,
+	0x80000005, 0x592c1208, 0x82080500, 0xffff7fff,
+	0x48025a08, 0x8c08151e, 0x0402002d, 0x823c7d40,
+	0x00000020, 0x0401f02a, 0x480bc857, 0x42000000,
+	0x0010b851, 0x0201f800, 0x0010aa47, 0x59300414,
+	0x4803c857, 0x8c000514, 0x04020007, 0x599c1819,
+	0x8c0c1d12, 0x04020004, 0x820c1d40, 0x00000001,
+	0x0401f01d, 0x59302013, 0x0401f92b, 0x0402001a,
+	0x42007800, 0x80000005, 0x5930500d, 0x592c0208,
+	0x4803c857, 0x8c00051e, 0x04020005, 0x823c7d40,
+	0x00000020, 0x5930400c, 0x0401f004, 0x8400051e,
+	0x48025a08, 0x0401f8da, 0x50201800, 0x480e600a,
+	0x4832600b, 0x4822600c, 0x482a600d, 0x480fc857,
+	0x4833c857, 0x4823c857, 0x482bc857, 0x80000580,
+	0x483e6004, 0x1c01f000, 0x0201f800, 0x001005d8,
+	0x4933c857, 0x4d2c0000, 0x59900004, 0x81300580,
+	0x02020800, 0x001005d8, 0x0201f800, 0x00109037,
+	0x02000800, 0x001005d8, 0x59325808, 0x4d3c0000,
+	0x4d400000, 0x59300004, 0x4803c857, 0x4c000000,
+	0x0201f800, 0x00106dc3, 0x0201f800, 0x00106b8a,
+	0x5c000000, 0x8c000516, 0x04000010, 0x592c000f,
+	0x4803c857, 0x48025807, 0x41780800, 0x42028000,
+	0x00000002, 0x0201f800, 0x00104e70, 0x4a025c06,
+	0x0000ffff, 0x0201f800, 0x000202da, 0x0201f800,
+	0x00107911, 0x0401f015, 0x4a026203, 0x00000002,
+	0x592c0208, 0x8400054e, 0x48025a08, 0x59300406,
+	0x82000580, 0x00000006, 0x04020009, 0x811800ca,
+	0x81c80c00, 0x58040939, 0x592c000d, 0x80040480,
+	0x592c080f, 0x80040480, 0x4802580b, 0x417a7800,
+	0x0201f800, 0x00108be3, 0x5c028000, 0x5c027800,
+	0x5c025800, 0x1c01f000, 0x4933c857, 0x4d2c0000,
+	0x59900004, 0x81300580, 0x02020800, 0x001005d8,
+	0x0201f800, 0x00109037, 0x02000800, 0x001005d8,
+	0x59325808, 0x592c0208, 0x84000540, 0x48025a08,
+	0x0401f7bf, 0x491bc857, 0x49d3c857, 0x4dd00000,
+	0x41780800, 0x8007a0ca, 0x83d3a400, 0x00007600,
+	0x4a03a005, 0x80000002, 0x42000000, 0x00001000,
+	0x50000000, 0x82000480, 0x24220001, 0x04020029,
+	0x59d01006, 0x82080500, 0x00006000, 0x82000580,
+	0x00006000, 0x0400002f, 0x82080500, 0x40008000,
+	0x040007f8, 0x800409c0, 0x0402002a, 0x811a31c0,
+	0x04000028, 0x42000000, 0x00001002, 0x50001000,
+	0x46000000, 0x00000512, 0x42001800, 0x0000000a,
+	0x59e00000, 0x8c00051a, 0x040207fc, 0x800c1840,
+	0x040207fc, 0x42000000, 0x00001002, 0x46000000,
+	0x00000514, 0x42001800, 0x0000000a, 0x59e00000,
+	0x8c00053a, 0x040207fc, 0x800c1840, 0x040207fc,
+	0x42000000, 0x00001002, 0x44080000, 0x0401f00d,
+	0x59d01006, 0x82080500, 0x00006000, 0x82000580,
+	0x00006000, 0x04000007, 0x8c08151e, 0x040007f9,
+	0x59d01006, 0x82080500, 0x00006000, 0x040207f5,
+	0x83d3a400, 0x00000020, 0x80040800, 0x82040480,
+	0x00000005, 0x040017bf, 0x5c03a000, 0x1c01f000,
+	0x491bc857, 0x49d3c857, 0x4dd00000, 0x41780800,
+	0x8007a0ca, 0x83d3a400, 0x00007600, 0x4a03a005,
+	0x80000001, 0x59d00006, 0x83d3a400, 0x00000020,
+	0x80040800, 0x82040480, 0x00000005, 0x040017f8,
+	0x5c03a000, 0x1c01f000, 0x59d00006, 0x8c00053e,
+	0x0400001e, 0x59902804, 0x4817c857, 0x801429c0,
+	0x04000013, 0x5990000a, 0x5990080b, 0x5990100c,
+	0x5990180d, 0x4800280a, 0x4804280b, 0x4808280c,
+	0x480c280d, 0x59d00000, 0x59d00801, 0x59d01002,
+	0x59d01803, 0x59d02004, 0x4800280e, 0x4804280f,
+	0x48082810, 0x480c2811, 0x48102812, 0x59900006,
+	0x82000500, 0xffff0000, 0x48032006, 0x4a03a005,
+	0x30000000, 0x59d00006, 0x1c01f000, 0x4803c856,
+	0x80204000, 0x50200000, 0x80000540, 0x04000003,
+	0x80285040, 0x1c01f000, 0x58300001, 0x80000540,
+	0x0400000e, 0x4802600b, 0x40006000, 0x58300204,
+	0x82000500, 0x0000000f, 0x82000400, 0x001010bd,
+	0x50004000, 0x802041c0, 0x02000800, 0x001005d8,
+	0x80285040, 0x1c01f000, 0x40005000, 0x1c01f000,
+	0x00000005, 0x00000008, 0x0000000b, 0x0000000e,
+	0x00000011, 0x00000000, 0x00000000, 0x0000000b,
+	0x00000000, 0x00000000, 0x00000000, 0x001010b8,
+	0x001010b7, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x001010b8, 0x001010b7, 0x001010b4,
+	0x001010b8, 0x001010b7, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x001010b8,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x001010b8, 0x001010b8, 0x001010b8,
+	0x00000000, 0x001010b8, 0x00000000, 0x00000000,
+	0x00000000, 0x4813c857, 0x492fc857, 0x4933c857,
+	0x48126012, 0x592c5207, 0x802851c0, 0x0400004a,
+	0x412c6000, 0x0401f84b, 0x04000009, 0x82240580,
+	0x00000002, 0x04020003, 0x5830000d, 0x80102480,
+	0x50200000, 0x80004540, 0x0400003f, 0x50200000,
+	0x80000540, 0x0400000b, 0x80301400, 0x58080002,
+	0x80102480, 0x0400101e, 0x801021c0, 0x04000009,
+	0x80285040, 0x04000034, 0x80204000, 0x0401f7f4,
+	0x58300001, 0x80006540, 0x0400002f, 0x0401f7e6,
+	0x80285040, 0x0400002c, 0x80204000, 0x50200000,
+	0x80000540, 0x0402000a, 0x58300001, 0x80006540,
+	0x04000025, 0x58300204, 0x82004d00, 0x0000000f,
+	0x82244400, 0x001010bd, 0x50204000, 0x592c0208,
+	0x8400051e, 0x48025a08, 0x0401f013, 0x80102080,
+	0x80102000, 0x48126010, 0x4813c857, 0x58080802,
+	0x40100000, 0x80042480, 0x02001800, 0x001005d8,
+	0x58080000, 0x58081801, 0x80102400, 0x4812600e,
+	0x480e600f, 0x4813c857, 0x592c0208, 0x8400055e,
+	0x48025a08, 0x4833c857, 0x4823c857, 0x482bc857,
+	0x4832600b, 0x4822600c, 0x482a600d, 0x80000580,
+	0x0401f003, 0x82000540, 0x00000001, 0x1c01f000,
+	0x58300204, 0x82004d00, 0x0000000f, 0x82244400,
+	0x001010bd, 0x82000500, 0x000000ff, 0x82000580,
+	0x00000029, 0x0402001b, 0x50204000, 0x592c0409,
+	0x80000540, 0x02000800, 0x001005d8, 0x82000c80,
+	0x00000002, 0x04001011, 0x58300001, 0x80006540,
+	0x02000800, 0x001005d8, 0x58300204, 0x82000500,
+	0x0000000f, 0x82000400, 0x001010bd, 0x50004000,
+	0x40040000, 0x800409c0, 0x04000006, 0x82040c80,
+	0x00000005, 0x040217f1, 0x80204400, 0x80000580,
+	0x1c01f000, 0x59e00004, 0x8c00050e, 0x02020000,
+	0x00100903, 0x1c01f000, 0x4c5c0000, 0x59e4b800,
+	0x485fc857, 0x825c0500, 0x0000001f, 0x04000004,
+	0x59e40862, 0x0201f800, 0x001005d8, 0x825c0500,
+	0x000000e0, 0x02000800, 0x001005d8, 0x8c5cbd0e,
+	0x04020807, 0x8c5cbd0c, 0x04020809, 0x8c5cbd0a,
+	0x04020878, 0x5c00b800, 0x1c01f000, 0x4803c856,
+	0x4a03c800, 0x00000080, 0x1c01f000, 0x4d2c0000,
+	0x42007800, 0x0010b8ec, 0x583c0001, 0x583c0802,
+	0x80040540, 0x0400003f, 0x42000800, 0x0010b7f7,
+	0x50065800, 0x592c0002, 0x82000580, 0x00000000,
+	0x0400000e, 0x59e40850, 0x59e41853, 0x400c0000,
+	0x80040400, 0x59e40852, 0x4807c857, 0x80041480,
+	0x04021008, 0x40001000, 0x480bc857, 0x4a007800,
+	0x00000001, 0x0401f006, 0x4803c857, 0x0401f029,
+	0x59e41050, 0x480bc857, 0x49787800, 0x480bc857,
+	0x480fc857, 0x592c0003, 0x80000540, 0x04000006,
+	0x80080580, 0x04020004, 0x592c0003, 0x4803c857,
+	0x480bc857, 0x480a5803, 0x592c0007, 0x800001c0,
+	0x04000007, 0x592c1007, 0x480bc857, 0x583c0003,
+	0x4803c857, 0x80080480, 0x04001003, 0x583c1001,
+	0x480bc857, 0x583c0802, 0x480bc857, 0x4807c857,
+	0x4a025801, 0x00000000, 0x4a025809, 0x001011bc,
+	0x480a5807, 0x48065808, 0x59e40053, 0x48025804,
+	0x412c1000, 0x492fc857, 0x0201f800, 0x00100858,
+	0x5c025800, 0x4a03c800, 0x00000040, 0x1c01f000,
+	0x42007800, 0x0010b7f7, 0x503c7800, 0x4a007802,
+	0x00000100, 0x42007800, 0x0010b8ec, 0x583c0000,
+	0x4803c857, 0x82000d80, 0x00000001, 0x04000004,
+	0x80000000, 0x48007800, 0x0401f019, 0x49787800,
+	0x583c1806, 0x583c0005, 0x800c1800, 0x480c7806,
+	0x800c0580, 0x04020002, 0x49787806, 0x583c0807,
+	0x800409c0, 0x0400000e, 0x583c0008, 0x80000000,
+	0x48007808, 0x80040580, 0x04020009, 0x49787808,
+	0x583c2006, 0x42001800, 0x00000001, 0x42001000,
+	0x00008028, 0x0201f800, 0x00103a3e, 0x1c01f000,
+	0x4a03c800, 0x00000020, 0x0201f800, 0x0010aa40,
+	0x59e40000, 0x1c01f000, 0x4d2c0000, 0x4a007001,
+	0x00000000, 0x82040d00, 0x43000f80, 0x02020800,
+	0x001005d8, 0x58380009, 0x4803c00f, 0x0201f800,
+	0x00109402, 0x583a5808, 0x592c0000, 0x48007008,
+	0x800001c0, 0x04020002, 0x49787007, 0x0201f800,
+	0x001007f4, 0x5c025800, 0x0201f000, 0x0010087d,
+	0x4803c856, 0x4c3c0000, 0x4d2c0000, 0x4d300000,
+	0x5830000a, 0x80025d40, 0x02000800, 0x001005d8,
+	0x592e6008, 0x4c300000, 0x0201f800, 0x0010941a,
+	0x5c006000, 0x02000800, 0x001005d8, 0x58300002,
+	0x82000580, 0x00000100, 0x04020010, 0x5930780b,
+	0x583c0001, 0x80000540, 0x0400000e, 0x4802600b,
+	0x40007800, 0x82000400, 0x00000002, 0x48006003,
+	0x583c0000, 0x48006004, 0x40301000, 0x0201f800,
+	0x00100858, 0x0401f00c, 0x4a025a06, 0x00000002,
+	0x4c300000, 0x0201f800, 0x000202da, 0x5c006000,
+	0x40325800, 0x0201f800, 0x001007f4, 0x0201f800,
+	0x0002077d, 0x5c026000, 0x5c025800, 0x5c007800,
+	0x1c01f000, 0x4803c856, 0x4d2c0000, 0x4d300000,
+	0x42007000, 0x0010b7f8, 0x58380801, 0x82040580,
+	0x00000002, 0x04020011, 0x58386002, 0x5830000a,
+	0x812c0580, 0x0402000d, 0x59e00004, 0x8c00050e,
+	0x040007fe, 0x59dc0006, 0x4803c857, 0x4a03b805,
+	0x20000000, 0x8c00053e, 0x040007f8, 0x4a007001,
+	0x00000000, 0x0401f019, 0x58386006, 0x40305000,
+	0x803061c0, 0x02000800, 0x001005d8, 0x5830000a,
+	0x812c0580, 0x04000004, 0x40305000, 0x58306000,
+	0x0401f7f8, 0x40280000, 0x80300580, 0x58300000,
+	0x04000006, 0x48005000, 0x800001c0, 0x04020007,
+	0x48287005, 0x0401f005, 0x800001c0, 0x04020002,
+	0x48007005, 0x48007006, 0x40325800, 0x0201f800,
+	0x001007f4, 0x42007000, 0x0010b7f8, 0x58380001,
+	0x82000580, 0x00000000, 0x02000800, 0x0010087d,
+	0x5c026000, 0x5c025800, 0x1c01f000, 0x4803c856,
+	0x42000800, 0x0000003c, 0x48079000, 0x59c80000,
+	0x80040500, 0x040207fe, 0x497b9005, 0x4a039035,
+	0x00880200, 0x59a8000e, 0x800000e0, 0x4803900e,
+	0x4a039011, 0x00000024, 0x4a03900f, 0x0010d1c0,
+	0x4a039010, 0x0010d1c0, 0x4a039015, 0x0000007f,
+	0x4a03900d, 0x00000040, 0x4a039000, 0x00001600,
+	0x1c01f000, 0x59c80007, 0x8c000508, 0x040208b7,
+	0x59c80800, 0x8c040d16, 0x04020004, 0x82000500,
+	0x00000006, 0x0c01f005, 0x4807c857, 0x82000500,
+	0x0000000e, 0x0c01f001, 0x001012a8, 0x001012a6,
+	0x00105999, 0x001012a6, 0x001012aa, 0x001012a6,
+	0x001012aa, 0x001012aa, 0x001012a6, 0x001012a6,
+	0x001012a6, 0x001012a6, 0x001012aa, 0x001012a6,
+	0x001012aa, 0x001012a6, 0x0201f800, 0x001005d8,
+	0x4803c857, 0x1c01f000, 0x59c8080c, 0x4807c857,
+	0x82040500, 0x00006000, 0x04000004, 0x0201f800,
+	0x0010aa03, 0x0401f006, 0x82040500, 0x007f0000,
+	0x04000006, 0x0201f800, 0x0010a9d5, 0x0201f800,
+	0x00106eb3, 0x0401f02b, 0x82040500, 0x00000014,
+	0x04000014, 0x0201f800, 0x0010aa32, 0x836c0580,
+	0x00000003, 0x0400000d, 0x0201f800, 0x0010513b,
+	0x04000004, 0x0201f800, 0x0010411d, 0x0401f007,
+	0x4a035033, 0x00000001, 0x4202d800, 0x00000001,
+	0x0201f800, 0x001050a2, 0x0401f817, 0x0401f015,
+	0x82040500, 0x00001c00, 0x04000005, 0x0201f800,
+	0x0010aa11, 0x0401f810, 0x0401f00e, 0x82040500,
+	0x00000140, 0x04000005, 0x0201f800, 0x0010aa24,
+	0x0401f809, 0x0401f007, 0x82040500, 0x00008000,
+	0x04000004, 0x0201f800, 0x0010a9fc, 0x0401f802,
+	0x1c01f000, 0x4c0c0000, 0x4c100000, 0x4c140000,
+	0x0201f800, 0x00100ec9, 0x5c002800, 0x5c002000,
+	0x5c001800, 0x1c01f000, 0x4803c856, 0x59a80804,
+	0x59a8002b, 0x82000500, 0xfffff000, 0x80040540,
+	0x4803502b, 0x59a8002f, 0x82000500, 0xfffff000,
+	0x80040540, 0x4803502f, 0x48078882, 0x82041c00,
+	0x0000000f, 0x800c1908, 0x820c1c00, 0x00000004,
+	0x400c2000, 0x901029c0, 0x82040480, 0x000001e4,
+	0x04021005, 0x42001000, 0x00000008, 0x801020c6,
+	0x0401f031, 0x82040480, 0x00000230, 0x04021009,
+	0x42001000, 0x00000007, 0x801000c2, 0x800000c2,
+	0x80100400, 0x80100400, 0x80102400, 0x0401f026,
+	0x82040480, 0x00000298, 0x04021008, 0x42001000,
+	0x00000006, 0x801000c2, 0x800000c2, 0x80100400,
+	0x80102400, 0x0401f01c, 0x82040480, 0x00000328,
+	0x04021007, 0x42001000, 0x00000005, 0x801000c2,
+	0x800000c2, 0x80102400, 0x0401f013, 0x82040480,
+	0x00000404, 0x04021005, 0x42001000, 0x00000004,
+	0x801020c4, 0x0401f00c, 0x82040480, 0x0000056c,
+	0x04021006, 0x42001000, 0x00000003, 0x801000c2,
+	0x80102400, 0x0401f004, 0x42001000, 0x00000002,
+	0x801020c2, 0x82100480, 0x00000110, 0x80000080,
+	0x80002000, 0x800800d0, 0x80140540, 0x80100540,
+	0x48039035, 0x1c01f000, 0x59c80815, 0x0201f800,
+	0x001005d0, 0x82040d00, 0x0000007c, 0x48079000,
+	0x59c80000, 0x80040500, 0x040207fe, 0x8c040d04,
+	0x04000003, 0x59c80035, 0x48039035, 0x59c80000,
+	0x82000540, 0x00001200, 0x48039000, 0x1c01f000,
+	0x4803c856, 0x497b88a9, 0x4a038807, 0x00000001,
+	0x497b8807, 0x59c40005, 0x48038805, 0x0201f800,
+	0x00101815, 0x4201d000, 0x000001f4, 0x0201f800,
+	0x0010608e, 0x497b880e, 0x4200b000, 0x000001f4,
+	0x42000000, 0x00000001, 0x42000800, 0x00000014,
+	0x0201f800, 0x00101944, 0x42000800, 0x00000014,
+	0x0201f800, 0x0010193f, 0x8c040d00, 0x04000005,
+	0x8058b040, 0x040207f3, 0x0201f800, 0x001005d8,
+	0x4200b000, 0x00000032, 0x42000000, 0x00000001,
+	0x42000800, 0x000000b4, 0x0201f800, 0x00101944,
+	0x42000800, 0x000000b4, 0x0201f800, 0x0010193f,
+	0x8c040d00, 0x04000005, 0x8058b040, 0x040207f3,
+	0x0201f800, 0x001005d8, 0x59c40005, 0x48038805,
+	0x42000000, 0x00000089, 0x800008d0, 0x48075054,
+	0x48075055, 0x48075056, 0x42000800, 0x000000e0,
+	0x0201f800, 0x00101944, 0x42000800, 0x000000f4,
+	0x0201f800, 0x0010193f, 0x82040500, 0xffffffd1,
+	0x82000540, 0x00000002, 0x42000800, 0x000000f4,
+	0x0201f800, 0x00101944, 0x42000800, 0x000000a0,
+	0x0201f800, 0x0010193f, 0x82040540, 0x00000001,
+	0x42000800, 0x000000a0, 0x0201f800, 0x00101944,
+	0x42000800, 0x00000000, 0x0201f800, 0x0010193f,
+	0x82040540, 0x00000001, 0x42000800, 0x00000000,
+	0x0201f800, 0x00101944, 0x4201d000, 0x0001d4c0,
+	0x0201f800, 0x0010608e, 0x0401fa2b, 0x4a0388a7,
+	0x0000f7f7, 0x4a0388a3, 0x8000403c, 0x4a0388ae,
+	0x000061a8, 0x4a038801, 0x00032063, 0x4a038810,
+	0x00410108, 0x4a038811, 0x00520608, 0x4a038812,
+	0x00450320, 0x4a038813, 0x00440405, 0x4a03881c,
+	0x004132e1, 0x4a038850, 0x80000108, 0x4a038860,
+	0x00000008, 0x4a038870, 0x00000008, 0x4a038851,
+	0x80000508, 0x4a038861, 0x00800000, 0x4a038871,
+	0x00800000, 0x4a038852, 0x80000708, 0x4a038862,
+	0x00800000, 0x4a038872, 0x00800000, 0x4a038853,
+	0x80000608, 0x497b8863, 0x4a038873, 0x00800000,
+	0x4a038882, 0x00000840, 0x4a0388a5, 0x0000001e,
+	0x4a0388a6, 0x0000001e, 0x4a0388b0, 0x00007530,
+	0x4a038802, 0x0000ffff, 0x4a038806, 0xc0e00800,
+	0x1c01f000, 0x497b5022, 0x4a035021, 0x00000001,
+	0x42000800, 0x00000040, 0x0201f800, 0x0010193f,
+	0x82040500, 0xffffffaf, 0x82000540, 0x00000000,
+	0x42000800, 0x00000040, 0x0201f800, 0x00101944,
+	0x42000800, 0x000000f4, 0x0201f800, 0x0010193f,
+	0x4c040000, 0x40040000, 0x84000548, 0x42000800,
+	0x000000f4, 0x0201f800, 0x00101944, 0x42000800,
+	0x00000000, 0x0201f800, 0x0010193f, 0x82040500,
+	0xffffffc1, 0x82000540, 0x00000038, 0x42000800,
+	0x00000000, 0x0201f800, 0x00101944, 0x5c000000,
+	0x42000800, 0x000000f4, 0x0201f000, 0x00101944,
+	0x59c40805, 0x4807c857, 0x59c40006, 0x80040d00,
+	0x02000800, 0x001005d8, 0x82040500, 0x00e00800,
+	0x04020004, 0x8c040d3e, 0x040208c4, 0x0401f007,
+	0x82040500, 0x00800800, 0x02020800, 0x001005d0,
+	0x0201f800, 0x001005d8, 0x4c5c0000, 0x4c600000,
+	0x59c4b805, 0x485fc857, 0x59c40006, 0x8c000500,
+	0x04000003, 0x8c5cbd00, 0x04020079, 0x0201f800,
+	0x0010513b, 0x04000014, 0x59c40005, 0x82000500,
+	0x000000c0, 0x04000036, 0x0201f800, 0x00105151,
+	0x04020033, 0x4a038805, 0x04000000, 0x59c400a3,
+	0x82000500, 0xbf203fff, 0x480388a3, 0x497b5049,
+	0x4a038805, 0x000000c0, 0x0201f800, 0x00105065,
+	0x0401f063, 0x8c5cbd34, 0x04020025, 0x59c40005,
+	0x8c00050c, 0x04020012, 0x8c00050e, 0x04020013,
+	0x8c00050a, 0x04020014, 0x8c000508, 0x0400000b,
+	0x59a80017, 0x82000580, 0x00000009, 0x04020007,
+	0x42000000, 0x0010b844, 0x0201f800, 0x0010aa47,
+	0x0201f800, 0x00105318, 0x0401f04b, 0x4a035033,
+	0x00000000, 0x0401f00b, 0x4a035033, 0x00000002,
+	0x0401f008, 0x42000000, 0x0010b846, 0x0201f800,
+	0x0010aa47, 0x0201f800, 0x001052c2, 0x0401f03e,
+	0x0201f800, 0x00105378, 0x0401f03b, 0x8c5cbd34,
+	0x04000037, 0x59c40005, 0x8c00053a, 0x04020005,
+	0x42000000, 0x0010b818, 0x0201f800, 0x0010aa47,
+	0x4a038805, 0x02000000, 0x0201f800, 0x0010513b,
+	0x04020010, 0x4a038805, 0x04000000, 0x0201f800,
+	0x00105149, 0x04020008, 0x4a035033, 0x00000001,
+	0x4202d800, 0x00000001, 0x0201f800, 0x001050a2,
+	0x0401f05b, 0x41780000, 0x0201f800, 0x00105113,
+	0x0201f800, 0x001019fe, 0x4000c000, 0x0201f800,
+	0x00101963, 0x836c1580, 0x00000004, 0x0402000d,
+	0x8c5cbd00, 0x04020012, 0x59a81005, 0x8c081506,
+	0x04020005, 0x59c410a3, 0x82081540, 0x00000008,
+	0x480b88a3, 0x59c41006, 0x84081540, 0x480b8806,
+	0x4a038805, 0x04000000, 0x4202d800, 0x00000001,
+	0x497b5014, 0x0201f800, 0x00103b38, 0x8c5cbd3c,
+	0x04020858, 0x8c5cbd00, 0x04000036, 0x42000000,
+	0x0010b8ca, 0x0201f800, 0x0010aa47, 0x4a038805,
+	0x00000001, 0x4200b000, 0x000003e8, 0x4201d000,
+	0x00000064, 0x4c580000, 0x0201f800, 0x0010608e,
+	0x0201f800, 0x001018d3, 0x5c00b000, 0x04000004,
+	0x8058b040, 0x040207f6, 0x0401f004, 0x4a038805,
+	0x00000001, 0x0401f01f, 0x59c40006, 0x84000500,
+	0x48038806, 0x0201f800, 0x00106ede, 0x497b8880,
+	0x0201f800, 0x0010a9c0, 0x59c4000d, 0x8c000500,
+	0x02020800, 0x0010a9ce, 0x59c400a3, 0x82000500,
+	0xfcf8ffff, 0x480388a3, 0x4a03504c, 0x00000002,
+	0x4202d800, 0x00000004, 0x4a038805, 0x00000001,
+	0x0201f800, 0x001006d4, 0x0401fb3b, 0x497b5052,
+	0x4a035049, 0x00000001, 0x0201f800, 0x00100452,
+	0x825cbd00, 0xbbfffffe, 0x485f8805, 0x5c00c000,
+	0x5c00b800, 0x1c01f000, 0x59c41004, 0x480bc857,
+	0x8c081500, 0x04000006, 0x4803c856, 0x497b2807,
+	0x0201f800, 0x00106fa4, 0x0401f00a, 0x82080500,
+	0x000001f0, 0x04000007, 0x4803c856, 0x417a3000,
+	0x0201f800, 0x00106062, 0x0201f800, 0x00106fc6,
+	0x4a038805, 0x80000000, 0x1c01f000, 0x59c408a3,
+	0x4807c857, 0x84040d40, 0x480788a3, 0x1c01f000,
+	0x4d900000, 0x4dd00000, 0x4da40000, 0x4d140000,
+	0x4a038805, 0x40000000, 0x42000000, 0x0010b8c6,
+	0x0201f800, 0x0010aa47, 0x0201f800, 0x00106c55,
+	0x59c41004, 0x8c081500, 0x04000054, 0x598e600d,
+	0x497b2807, 0x813261c0, 0x04000032, 0x59300403,
+	0x82000580, 0x00000032, 0x0402002e, 0x5930001c,
+	0x48038833, 0x4a038807, 0x00018000, 0x4201d000,
+	0x00000002, 0x0201f800, 0x0010608e, 0x497b8807,
+	0x4201d000, 0x00000002, 0x0201f800, 0x0010608e,
+	0x0201f800, 0x00106e21, 0x4201d000, 0x00007530,
+	0x0201f800, 0x0010608e, 0x59c408a4, 0x82040d00,
+	0x0000000f, 0x82040d80, 0x00000000, 0x04000005,
+	0x42000000, 0x00200000, 0x0201f800, 0x00101949,
+	0x0201f800, 0x00106bbf, 0x59300008, 0x80000540,
+	0x02000800, 0x001005d8, 0x40025800, 0x4a025a04,
+	0x00000103, 0x5931d821, 0x58ef400b, 0x58ec0009,
+	0x0801f800, 0x0201f800, 0x0002077d, 0x0401f047,
+	0x598c000f, 0x82001c80, 0x000000c8, 0x0402100f,
+	0x80000000, 0x4803180f, 0x59c400a4, 0x82000500,
+	0x0000000f, 0x82000580, 0x00000002, 0x04020004,
+	0x42000000, 0x00200000, 0x0401fbf7, 0x0201f800,
+	0x0010604d, 0x0401f035, 0x4933c857, 0x0201f800,
+	0x00106e21, 0x813261c0, 0x04000030, 0x4a026203,
+	0x00000001, 0x42027000, 0x00000027, 0x0201f800,
+	0x000207a1, 0x0401f029, 0x8c081508, 0x04000027,
+	0x417a3000, 0x0201f800, 0x001070d8, 0x42032000,
+	0x0000bf32, 0x0201f800, 0x00106062, 0x59926004,
+	0x813261c0, 0x04000012, 0x42001800, 0x000000c8,
+	0x0201f800, 0x001070a4, 0x0402000d, 0x59c400a4,
+	0x82000500, 0x0000000f, 0x82000580, 0x00000002,
+	0x04020004, 0x42000000, 0x00200000, 0x0401fbce,
+	0x0201f800, 0x00106052, 0x0401f00c, 0x4933c857,
+	0x0201f800, 0x00106dc3, 0x813261c0, 0x04000007,
+	0x42027000, 0x0000004f, 0x4a026203, 0x00000003,
+	0x0201f800, 0x000207a1, 0x5c022800, 0x5c034800,
+	0x5c03a000, 0x5c032000, 0x0201f000, 0x00106c4b,
+	0x4803c857, 0x59a80821, 0x48035021, 0x80041580,
+	0x04000045, 0x800409c0, 0x04000023, 0x497b504c,
+	0x42000000, 0x0010b80d, 0x0201f800, 0x0010aa47,
+	0x0201f800, 0x0010aaf9, 0x42001000, 0x00008011,
+	0x59c40001, 0x82000500, 0x00018000, 0x82001d80,
+	0x00000000, 0x04000009, 0x82001d80, 0x00008000,
+	0x04000009, 0x82001d80, 0x00010000, 0x04000009,
+	0x0201f800, 0x001005d8, 0x42001800, 0x00000000,
+	0x0401f006, 0x42001800, 0x00000001, 0x0401f003,
+	0x42001800, 0x00000003, 0x0201f800, 0x00103a3e,
+	0x0401f021, 0x59a8084c, 0x800409c0, 0x04020007,
+	0x59c4000d, 0x8c000520, 0x04000004, 0x42001800,
+	0x00000003, 0x0401f002, 0x40041800, 0x0201f800,
+	0x0010aadd, 0x42001000, 0x00008012, 0x0201f800,
+	0x00103a3e, 0x0201f800, 0x001006d4, 0x0201f800,
+	0x0010ab33, 0x0402000c, 0x0401f853, 0x4d400000,
+	0x4d3c0000, 0x42028000, 0x00000028, 0x42027800,
+	0x00000408, 0x0201f800, 0x00101fe5, 0x5c027800,
+	0x5c028000, 0x1c01f000, 0x4803c857, 0x82000400,
+	0x0010210e, 0x50000800, 0x82040d00, 0x000000ff,
+	0x1c01f000, 0x4803c856, 0x4c580000, 0x4200b000,
+	0x00000010, 0x497b88ac, 0x497b88ad, 0x8058b040,
+	0x040207fe, 0x5c00b000, 0x1c01f000, 0x4807c857,
+	0x48075010, 0x80041108, 0x4200b000, 0x00000010,
+	0x497b88ac, 0x80000580, 0x800811c0, 0x04020006,
+	0x82040500, 0x0000000f, 0x82000400, 0x0010ab38,
+	0x50000000, 0x480388ad, 0x80081040, 0x8058b040,
+	0x040207f5, 0x1c01f000, 0x59a80005, 0x04000003,
+	0x84000546, 0x0401f002, 0x84000506, 0x48035005,
+	0x4803c857, 0x1c01f000, 0x4803c857, 0x4c080000,
+	0x4c040000, 0x4c000000, 0x59c40892, 0x4807c857,
+	0x80041580, 0x04000010, 0x80041480, 0x04021007,
+	0x80081080, 0x80081000, 0x4008b000, 0x42000000,
+	0x00000201, 0x0401f004, 0x4008b000, 0x42000000,
+	0x00000210, 0x48038886, 0x8058b040, 0x040207fe,
+	0x497b8886, 0x5c000000, 0x5c000800, 0x5c001000,
+	0x1c01f000, 0x4803c856, 0x0201f800, 0x00103b25,
+	0x04000005, 0x42028000, 0x0000002e, 0x0201f000,
+	0x0010a449, 0x1c01f000, 0x42000800, 0x00000002,
+	0x59a80005, 0x8c000514, 0x0402000b, 0x59c80835,
+	0x82040d00, 0x00001f00, 0x80040910, 0x80040800,
+	0x59a8006c, 0x80000540, 0x04000003, 0x42000800,
+	0x0000025a, 0x4807c857, 0x1c01f000, 0x4c000000,
+	0x59a80053, 0x4803c857, 0x82000580, 0x00000000,
+	0x5c000000, 0x1c01f000, 0x4c000000, 0x59a80053,
+	0x4803c857, 0x82000580, 0x00000001, 0x5c000000,
+	0x1c01f000, 0x4c000000, 0x59a80053, 0x4803c857,
+	0x82000580, 0x00000003, 0x5c000000, 0x1c01f000,
+	0x4c000000, 0x59a80053, 0x82000580, 0x00000002,
+	0x5c000000, 0x1c01f000, 0x4c000000, 0x4c040000,
+	0x4c080000, 0x4c380000, 0x59a80040, 0x82000c80,
+	0x00000007, 0x02021800, 0x001005d8, 0x0c01f806,
+	0x5c007000, 0x5c001000, 0x5c000800, 0x5c000000,
+	0x1c01f000, 0x0010166c, 0x0010167f, 0x00101693,
+	0x00101695, 0x001016bc, 0x001016be, 0x001016c0,
+	0x4803c856, 0x4a035042, 0x00000000, 0x42000000,
+	0x00000002, 0x0401fa1b, 0x42000000, 0x00000002,
+	0x0401f9ad, 0x0401fab2, 0x4803c856, 0x4a035040,
+	0x00000006, 0x42000800, 0x0000001e, 0x42001000,
+	0x001016c1, 0x0201f000, 0x0010606e, 0x497b5045,
+	0x4a035050, 0x00000036, 0x4a03504f, 0x0000002a,
+	0x4803c856, 0x4a035042, 0x00000001, 0x42000000,
+	0x00000002, 0x0401f998, 0x4803c856, 0x4a035040,
+	0x00000006, 0x42000800, 0x0000001e, 0x42001000,
+	0x001016c1, 0x0201f000, 0x0010606e, 0x0201f800,
+	0x001005d8, 0x4a035050, 0x00000036, 0x4803c856,
+	0x4a035042, 0x00000003, 0x42000800, 0x00000000,
+	0x0401faa3, 0x82040d00, 0x00000090, 0x82040580,
+	0x00000090, 0x04000009, 0x82040580, 0x00000010,
+	0x04000009, 0x82040580, 0x00000000, 0x04000008,
+	0x0201f800, 0x001005d8, 0x42000000, 0x00000001,
+	0x0401f005, 0x41780000, 0x0401f003, 0x42000000,
+	0x00000002, 0x0401f970, 0x497b5046, 0x4803c856,
+	0x4a035040, 0x00000006, 0x42000800, 0x0000001e,
+	0x42001000, 0x001016c1, 0x0201f000, 0x0010606e,
+	0x0201f800, 0x001005d8, 0x0201f800, 0x001005d8,
+	0x1c01f000, 0x4c000000, 0x4c040000, 0x4c080000,
+	0x4c380000, 0x59a80042, 0x82000c80, 0x00000007,
+	0x02021800, 0x001005d8, 0x0c01f806, 0x5c007000,
+	0x5c001000, 0x5c000800, 0x5c000000, 0x1c01f000,
+	0x001016d7, 0x001016f6, 0x0010174a, 0x00101761,
+	0x00101778, 0x00101781, 0x00101783, 0x0401f9fc,
+	0x0402001b, 0x59a81048, 0x42000800, 0x00000000,
+	0x0401fa63, 0x82040d00, 0x00000090, 0x82040580,
+	0x00000090, 0x04000009, 0x82040580, 0x00000010,
+	0x04000008, 0x82040580, 0x00000000, 0x04000007,
+	0x0201f800, 0x001005d8, 0x84081540, 0x0401f004,
+	0x84081542, 0x0401f002, 0x84081544, 0x480b5048,
+	0x4a035040, 0x00000001, 0x0401f003, 0x0401f8cb,
+	0x0401ff82, 0x1c01f000, 0x0401f88f, 0x04000052,
+	0x0401f9db, 0x0402002a, 0x42000800, 0x00000000,
+	0x0401fa43, 0x82040d00, 0x00000090, 0x82040580,
+	0x00000000, 0x04000044, 0x82040580, 0x00000010,
+	0x04000006, 0x82040580, 0x00000090, 0x04000009,
+	0x0201f800, 0x001005d8, 0x59c40801, 0x82040d00,
+	0x00018000, 0x82040580, 0x00000000, 0x04000036,
+	0x42000800, 0x00000000, 0x0401fa2d, 0x82040d00,
+	0x00000090, 0x82040580, 0x00000010, 0x04000006,
+	0x82040580, 0x00000090, 0x04000006, 0x02020800,
+	0x001005d8, 0x59a80048, 0x84000542, 0x0401f003,
+	0x59a80048, 0x84000540, 0x48035048, 0x59a80045,
+	0x80000000, 0x48035045, 0x82000580, 0x00000005,
+	0x04000003, 0x0401f861, 0x0401f01e, 0x497b5045,
+	0x59c40801, 0x82040d00, 0x00018000, 0x82040580,
+	0x00000000, 0x04000009, 0x82040580, 0x00008000,
+	0x04000009, 0x82040580, 0x00010000, 0x04000008,
+	0x0201f800, 0x001005d8, 0x42000000, 0x00000001,
+	0x0401f005, 0x41780000, 0x0401f003, 0x42000000,
+	0x00000002, 0x0401f94b, 0x4a035042, 0x00000002,
+	0x0401f004, 0x4a035040, 0x00000003, 0x0401f002,
+	0x0401ff42, 0x1c01f000, 0x0401f83b, 0x04000015,
+	0x59a8004f, 0x80000040, 0x4803504f, 0x0401f984,
+	0x04020005, 0x4a035040, 0x00000003, 0x497b5041,
+	0x0401f00c, 0x59a8004f, 0x80000540, 0x04020003,
+	0x0401f89e, 0x0401f002, 0x0401f84b, 0x0401f82f,
+	0x497b5045, 0x4a035042, 0x00000001, 0x0401ff2b,
+	0x1c01f000, 0x0401f824, 0x04000015, 0x0401f970,
+	0x0402000f, 0x59a80046, 0x80000000, 0x48035046,
+	0x82000580, 0x00000007, 0x0402000c, 0x4a035052,
+	0x0000000a, 0x497b5049, 0x59a80048, 0x8400055e,
+	0x48035048, 0x4803c857, 0x0401f005, 0x0401f817,
+	0x4a035042, 0x00000004, 0x0401ff3d, 0x1c01f000,
+	0x0401f80d, 0x04000007, 0x0401f959, 0x04020003,
+	0x0401ff1b, 0x0401f003, 0x0401f80c, 0x0401ff34,
+	0x1c01f000, 0x0201f800, 0x001005d8, 0x0201f800,
+	0x001005d8, 0x59a80050, 0x80000040, 0x48035050,
+	0x0400088d, 0x1c01f000, 0x4c040000, 0x42000800,
+	0x00000000, 0x0401f9b2, 0x82040d00, 0x00000090,
+	0x82040580, 0x00000090, 0x04000009, 0x82040580,
+	0x00000010, 0x04000009, 0x82040580, 0x00000000,
+	0x04000009, 0x0201f800, 0x001005d8, 0x42000000,
+	0x00000002, 0x0401f005, 0x42000000, 0x00000001,
+	0x0401f002, 0x41780000, 0x0401f8ea, 0x5c000800,
+	0x1c01f000, 0x4c040000, 0x59c40801, 0x82040d00,
+	0x00018000, 0x82040580, 0x00000000, 0x04000009,
+	0x82040580, 0x00008000, 0x04000009, 0x82040580,
+	0x00010000, 0x04000009, 0x0201f800, 0x001005d8,
+	0x42000000, 0x00000002, 0x0401f005, 0x42000000,
+	0x00000001, 0x0401f002, 0x41780000, 0x0401f866,
+	0x5c000800, 0x1c01f000, 0x4c040000, 0x59a80045,
+	0x80000000, 0x48035045, 0x82000580, 0x00000005,
+	0x04020018, 0x497b5045, 0x59c40801, 0x82040d00,
+	0x00018000, 0x82040580, 0x00000000, 0x04000009,
+	0x82040580, 0x00008000, 0x04000009, 0x82040580,
+	0x00010000, 0x04000009, 0x0201f800, 0x001005d8,
+	0x42000000, 0x00000002, 0x0401f005, 0x42000000,
+	0x00000001, 0x0401f002, 0x41780000, 0x0401f846,
+	0x42000800, 0x00000000, 0x0401f961, 0x82040d00,
+	0x00000090, 0x82040580, 0x00000090, 0x04000009,
+	0x82040580, 0x00000010, 0x04000009, 0x82040580,
+	0x00000000, 0x04000009, 0x0201f800, 0x001005d8,
+	0x42000000, 0x00000002, 0x0401f005, 0x42000000,
+	0x00000001, 0x0401f002, 0x41780000, 0x0401f899,
+	0x5c000800, 0x1c01f000, 0x4c200000, 0x59a80048,
+	0x82000500, 0x00007fff, 0x02000800, 0x001005d8,
+	0x59a84047, 0x80204102, 0x02001800, 0x001005d8,
+	0x48235047, 0x80204500, 0x040007fa, 0x8c000504,
+	0x04020007, 0x8c000502, 0x04020008, 0x8c000500,
+	0x04020008, 0x0201f800, 0x001005d8, 0x42000000,
+	0x00000002, 0x0401f005, 0x41780000, 0x0401f003,
+	0x42000000, 0x00000001, 0x0401f80f, 0x5c004000,
+	0x1c01f000, 0x04011000, 0x4a03c840, 0x0010b440,
+	0x4a03c842, 0x00000009, 0x40000000, 0x040117ff,
+	0x4a035047, 0x00000004, 0x4a03503e, 0x00000000,
+	0x1c01f000, 0x59a80858, 0x82040d80, 0x01391077,
+	0x04020008, 0x59e00813, 0x8c040d00, 0x04000005,
+	0x82000d80, 0x00000002, 0x04020002, 0x41780000,
+	0x4c000000, 0x0401f9b1, 0x5c000000, 0x800001c0,
+	0x04000040, 0x82000d80, 0x00000001, 0x0402001d,
+	0x42000800, 0x000000a0, 0x0401f909, 0x82040540,
+	0x00000004, 0x42000800, 0x000000a0, 0x0401f909,
+	0x42000800, 0x000000c0, 0x0401f901, 0x82040540,
+	0x00000020, 0x42000800, 0x000000c0, 0x0401f901,
+	0x59c40001, 0x82000500, 0xfffe7fff, 0x82000540,
+	0x00000000, 0x48038801, 0x59a80054, 0x80000110,
+	0x42000800, 0x000000e0, 0x0401f8f6, 0x0401f03c,
+	0x82000d80, 0x00000002, 0x02020800, 0x001005d8,
+	0x42000800, 0x000000a0, 0x0401f8e9, 0x82040500,
+	0xfffffffb, 0x42000800, 0x000000a0, 0x0401f8e9,
+	0x42000800, 0x000000c0, 0x0401f8e1, 0x82040500,
+	0xffffffdf, 0x42000800, 0x000000c0, 0x0401f8e1,
+	0x59c40001, 0x82000500, 0xfffe7fff, 0x82000540,
+	0x00010000, 0x48038801, 0x59a80056, 0x80000110,
+	0x42000800, 0x000000e0, 0x0401f8d6, 0x0401f01c,
+	0x42000800, 0x000000a0, 0x0401f8cd, 0x82040540,
+	0x00000004, 0x42000800, 0x000000a0, 0x0401f8cd,
+	0x42000800, 0x000000c0, 0x0401f8c5, 0x82040500,
+	0xffffffdf, 0x42000800, 0x000000c0, 0x0401f8c5,
+	0x59c40001, 0x82000500, 0xfffe7fff, 0x82000540,
+	0x00008000, 0x48038801, 0x59a80055, 0x80000110,
+	0x42000800, 0x000000e0, 0x0401f8ba, 0x0401f163,
+	0x4803c857, 0x59a80858, 0x82040d80, 0x01391077,
+	0x04020008, 0x59e00813, 0x8c040d00, 0x04000005,
+	0x82000d80, 0x00000002, 0x04020002, 0x41780000,
+	0x4c000000, 0x0401f94d, 0x5c000000, 0x800001c0,
+	0x04000026, 0x82000d80, 0x00000001, 0x04020010,
+	0x59a8006c, 0x80000540, 0x04000004, 0x42001000,
+	0x00000000, 0x0401fa0a, 0x42000800, 0x00000000,
+	0x0401f897, 0x82040540, 0x00000090, 0x42000800,
+	0x00000000, 0x0401f897, 0x0401f024, 0x82000d80,
+	0x00000002, 0x02020800, 0x001005d8, 0x59a8006c,
+	0x80000540, 0x04000004, 0x42001000, 0x00010000,
+	0x0401f9f7, 0x42000800, 0x00000000, 0x0401f884,
+	0x82040500, 0xffffff6f, 0x42000800, 0x00000000,
+	0x0401f884, 0x0401f011, 0x59a8006c, 0x80000540,
+	0x04000004, 0x42001000, 0x00008000, 0x0401f9e8,
+	0x42000800, 0x00000000, 0x0401f875, 0x82040500,
+	0xffffff6f, 0x82000540, 0x00000010, 0x42000800,
+	0x00000000, 0x0401f873, 0x0401f124, 0x4c580000,
+	0x4200b000, 0x00000014, 0x8058b040, 0x04000043,
+	0x59c4000d, 0x8c000520, 0x040207fc, 0x0401f85c,
+	0x59c4000d, 0x8c000520, 0x040207f8, 0x59c40808,
+	0x84040d50, 0x48078808, 0x4200b000, 0x000000c8,
+	0x8058b040, 0x040207ff, 0x4200b000, 0x00000014,
+	0x8058b040, 0x04000031, 0x59c4000d, 0x8c000520,
+	0x0402002e, 0x42000800, 0x00001000, 0x50040800,
+	0x82040c80, 0x24220001, 0x04020003, 0x8c000504,
+	0x040007f4, 0x0401f842, 0x59c4000d, 0x8c000520,
+	0x04020022, 0x42000800, 0x00001000, 0x50040800,
+	0x82040c80, 0x24220001, 0x04020003, 0x8c000504,
+	0x040007e8, 0x4200b000, 0x0000000a, 0x8058b040,
+	0x04000003, 0x0401f832, 0x0401f7fd, 0x4200b000,
+	0x00000064, 0x59c4000d, 0x8c00051e, 0x0400000f,
+	0x8058b040, 0x040207fc, 0x42000000, 0x00001000,
+	0x50000000, 0x82000480, 0x24220001, 0x04020004,
+	0x59c40808, 0x84040d10, 0x48078808, 0x80000580,
+	0x4803c857, 0x0401f00c, 0x42000000, 0x00001000,
+	0x50000000, 0x82000480, 0x24220001, 0x04020004,
+	0x59c40808, 0x84040d10, 0x48078808, 0x82000540,
+	0x00000001, 0x5c00b000, 0x1c01f000, 0x42000800,
+	0x000000a0, 0x0401f816, 0x82040500, 0xfffffffe,
+	0x42000800, 0x000000a0, 0x0401f816, 0x42000800,
+	0x00000000, 0x0401f80e, 0x82040500, 0xfffffffe,
+	0x42000800, 0x00000000, 0x0401f00e, 0x40000000,
+	0x40000000, 0x40000000, 0x40000000, 0x40000000,
+	0x1c01f000, 0x480b8805, 0x1c01f000, 0x4807880e,
+	0x59c4080f, 0x82040d00, 0x000000ff, 0x1c01f000,
+	0x900001c0, 0x80040d40, 0x84040d40, 0x4807880e,
+	0x1c01f000, 0x82000d80, 0x00200000, 0x04000009,
+	0x82000d80, 0x02000000, 0x04000006, 0x82000d80,
+	0x01000000, 0x04000006, 0x59c408a3, 0x0401f006,
+	0x59c408a3, 0x84040d30, 0x0401f003, 0x59c408a3,
+	0x84040d32, 0x80040540, 0x480388a3, 0x480788a3,
+	0x1c01f000, 0x59c400a3, 0x84000556, 0x480388a3,
+	0x84000516, 0x480388a3, 0x1c01f000, 0x485fc857,
+	0x4863c857, 0x4c640000, 0x4d3c0000, 0x4d400000,
+	0x0201f800, 0x00106ede, 0x4863500a, 0x0201f800,
+	0x0010ab33, 0x0402006c, 0x82600d00, 0x0000ff00,
+	0x800409c0, 0x0400000c, 0x4200c800, 0x00000001,
+	0x59a80010, 0x82000500, 0x000000ff, 0x80041110,
+	0x80081580, 0x04000021, 0x82041580, 0x0000ff00,
+	0x0400000a, 0x59c410a3, 0x82081500, 0x00008000,
+	0x04000009, 0x59c410a7, 0x82081500, 0x0000ff00,
+	0x82081580, 0x0000ff00, 0x4200c800, 0x00000000,
+	0x04000012, 0x59a80005, 0x8c000502, 0x04020008,
+	0x8c000500, 0x0402000d, 0x599c1017, 0x8c08151a,
+	0x0400003e, 0x84000542, 0x48035005, 0x4200c800,
+	0x00000002, 0x42028000, 0x00000004, 0x42027800,
+	0x00000008, 0x0401f008, 0x59a80805, 0x84040d40,
+	0x48075005, 0x42028000, 0x00000004, 0x42027800,
+	0x00000400, 0x59a80006, 0x8c000502, 0x04020006,
+	0x59a80805, 0x8c040d0a, 0x04020033, 0x84040d4a,
+	0x48075005, 0x42000000, 0x0010b812, 0x0201f800,
+	0x0010aa47, 0x59a8180a, 0x42001000, 0x00008013,
+	0x0201f800, 0x00103a3e, 0x0201f800, 0x00103b25,
+	0x04000015, 0x4d400000, 0x82600500, 0x000000ff,
+	0x42028800, 0x0000ffff, 0x40643000, 0x42028000,
+	0x0000000e, 0x0201f800, 0x0010a446, 0x42000800,
+	0x00000001, 0x42001000, 0x00000100, 0x0201f800,
+	0x0010618b, 0x5c028000, 0x599c0817, 0x8c040d0a,
+	0x04020011, 0x493fc857, 0x4943c857, 0x0201f800,
+	0x00101fe5, 0x0401f00c, 0x0201f800, 0x00103b25,
+	0x04000009, 0x42028000, 0x0000000f, 0x42028800,
+	0x0000ffff, 0x42003000, 0x00000000, 0x0201f800,
+	0x0010a449, 0x497b8880, 0x5c028000, 0x5c027800,
+	0x5c00c800, 0x1c01f000, 0x42000800, 0x000000a0,
+	0x0401ff5f, 0x82040540, 0x00000002, 0x42000800,
+	0x000000a0, 0x0401f75f, 0x42000800, 0x00000000,
+	0x0401ff57, 0x82040540, 0x00000002, 0x42000800,
+	0x00000000, 0x0401f757, 0x42000800, 0x000000a0,
+	0x0401ff4f, 0x82040500, 0xfffffffd, 0x42000800,
+	0x000000a0, 0x0401f74f, 0x42000800, 0x00000000,
+	0x0401ff47, 0x82040500, 0xfffffffd, 0x42000800,
+	0x00000000, 0x0401f747, 0x59c408a8, 0x0401ff38,
+	0x0401ff37, 0x59c400a8, 0x80040d80, 0x040207fb,
+	0x1c01f000, 0x4803c856, 0x4a038807, 0x00000001,
+	0x497b8807, 0x59c40005, 0x48038805, 0x497b506c,
+	0x497b506d, 0x41785800, 0x42006000, 0x00000001,
+	0x42006800, 0x00000003, 0x0401f824, 0x0401f82f,
+	0x40400000, 0x4803c857, 0x82408580, 0x00000000,
+	0x0402001d, 0x41785800, 0x42006000, 0x0000001e,
+	0x42006800, 0x00000014, 0x0401f818, 0x0401f823,
+	0x40400000, 0x4803c857, 0x82408580, 0x00000800,
+	0x04020011, 0x42005800, 0x00000001, 0x42006000,
+	0x0000001e, 0x42006800, 0x00000014, 0x0401f80b,
+	0x0401f816, 0x40400000, 0x4803c857, 0x82408580,
+	0x0000ffff, 0x04020004, 0x4a03506c, 0x00000001,
+	0x4803c856, 0x1c01f000, 0x41785000, 0x0401f812,
+	0x0401f838, 0x40347000, 0x40340800, 0x0401f03d,
+	0x42005000, 0x00000001, 0x0401f80b, 0x0401f831,
+	0x40340800, 0x0401f037, 0x42005000, 0x00000002,
+	0x0401f805, 0x0401f81d, 0x0401f835, 0x40048000,
+	0x1c01f000, 0x0401f808, 0x0401f814, 0x40280800,
+	0x0401f826, 0x402c0800, 0x0401f827, 0x40300800,
+	0x0401f025, 0x42000800, 0x0000ffff, 0x42001000,
+	0x00000001, 0x0401f829, 0x42001000, 0x00000010,
+	0x0401f826, 0x42000800, 0x0000ffff, 0x42001000,
+	0x00000010, 0x0401f021, 0x41780800, 0x42001000,
+	0x00000002, 0x0401f01d, 0x0401f92e, 0x4a03d000,
+	0x00050004, 0x0401f92b, 0x4a03d000, 0x00050005,
+	0x0401f928, 0x4a03d000, 0x00050004, 0x42000800,
+	0x00000001, 0x42001000, 0x00000001, 0x0401f00f,
+	0x42000800, 0x00000002, 0x42001000, 0x00000002,
+	0x0401f00a, 0x42001000, 0x00000005, 0x0401f007,
+	0x42001000, 0x00000010, 0x0401f004, 0x42001000,
+	0x00000010, 0x0401f01b, 0x0401f912, 0x82082c00,
+	0x0010ab38, 0x50142800, 0x82081500, 0xffffffff,
+	0x04000013, 0x0401f90b, 0x80081040, 0x80142902,
+	0x40040000, 0x80140500, 0x04000007, 0x4a03d000,
+	0x00070006, 0x0401f903, 0x4a03d000, 0x00070007,
+	0x0401f006, 0x4a03d000, 0x00070004, 0x0401f8fd,
+	0x4a03d000, 0x00070005, 0x0401f7ec, 0x1c01f000,
+	0x41780800, 0x82082c00, 0x0010ab38, 0x50142800,
+	0x82081500, 0xffffffff, 0x04000010, 0x0401f8f1,
+	0x4a03d000, 0x00050001, 0x0401f8ee, 0x59e81800,
+	0x80081040, 0x80142902, 0x8c0c1d06, 0x04000004,
+	0x40140000, 0x80040d40, 0x0401f8e6, 0x4a03d000,
+	0x00070000, 0x0401f7ef, 0x1c01f000, 0x480bc857,
+	0x480b506d, 0x59c40001, 0x82000500, 0xffffefff,
+	0x48038801, 0x41781800, 0x0401f8c4, 0x41785800,
+	0x42006000, 0x0000001e, 0x42006800, 0x00000004,
+	0x0401ff7a, 0x42006800, 0x0000003c, 0x0401ff7d,
+	0x41785800, 0x42006000, 0x0000001e, 0x42006800,
+	0x00000004, 0x0401ff71, 0x41786800, 0x0401ff75,
+	0x41785800, 0x42006000, 0x0000001e, 0x41786800,
+	0x0401ff6a, 0x42006800, 0x00000002, 0x0401ff6d,
+	0x42006800, 0x00000001, 0x0401ff64, 0x42006800,
+	0x000000f5, 0x0401ff67, 0x41785800, 0x42006000,
+	0x0000001e, 0x42006800, 0x00000004, 0x0401ff5b,
+	0x42006800, 0x00000020, 0x0401ff5e, 0x59a8106d,
+	0x0401f865, 0x42001800, 0x000200f5, 0x0401f897,
+	0x59a8106d, 0x0401f879, 0x41785800, 0x42006000,
+	0x0000001e, 0x42006800, 0x00000004, 0x0401ff4b,
+	0x41786800, 0x0401ff4f, 0x59c40001, 0x82000540,
+	0x00001000, 0x48038801, 0x41785800, 0x42006000,
+	0x0000001e, 0x42006800, 0x00000015, 0x0401ff3f,
+	0x0401ff4a, 0x40400000, 0x82000540, 0x00000002,
+	0x4c000000, 0x41785800, 0x42006000, 0x0000001e,
+	0x42006800, 0x00000015, 0x0401ff34, 0x5c000000,
+	0x40006800, 0x0401ff37, 0x41785800, 0x42006000,
+	0x0000001e, 0x42006800, 0x00000015, 0x0401ff2b,
+	0x0401ff36, 0x40400000, 0x82000500, 0x0000fffd,
+	0x4c000000, 0x41785800, 0x42006000, 0x0000001e,
+	0x42006800, 0x00000015, 0x0401ff20, 0x5c000000,
+	0x40006800, 0x0401ff23, 0x41785800, 0x42006000,
+	0x0000001e, 0x42006800, 0x00000014, 0x0401ff17,
+	0x0401ff22, 0x40400000, 0x82000540, 0x00000040,
+	0x4c000000, 0x41785800, 0x42006000, 0x0000001e,
+	0x42006800, 0x00000014, 0x0401ff0c, 0x5c000000,
+	0x40006800, 0x0401ff0f, 0x41785800, 0x42006000,
+	0x0000001e, 0x42006800, 0x00000014, 0x0401ff03,
+	0x0401ff0e, 0x40400000, 0x82000500, 0x0000ffbf,
+	0x4c000000, 0x41785800, 0x42006000, 0x0000001e,
+	0x42006800, 0x00000014, 0x0401fef8, 0x5c000000,
+	0x40006800, 0x0401fefb, 0x4a038886, 0x00002020,
+	0x0401f04c, 0x480bc857, 0x82080580, 0x00010000,
+	0x04020007, 0x82040d40, 0x00010000, 0x42001800,
+	0x00000001, 0x0401f82d, 0x0401f00f, 0x82080580,
+	0x00008000, 0x04000007, 0x82040d40, 0x00000000,
+	0x42001800, 0x00900001, 0x0401f824, 0x0401f006,
+	0x82040d40, 0x00008000, 0x42001800, 0x00100001,
+	0x0401f81e, 0x1c01f000, 0x480bc857, 0x82080580,
+	0x00010000, 0x04020008, 0x42001800, 0x000000a1,
+	0x0401f816, 0x42001800, 0x000000c1, 0x0401f813,
+	0x0401f011, 0x82080580, 0x00008000, 0x04000008,
+	0x42001800, 0x000400a1, 0x0401f80c, 0x42001800,
+	0x002000c1, 0x0401f809, 0x0401f007, 0x42001800,
+	0x000400a1, 0x0401f805, 0x42001800, 0x000000c1,
+	0x0401f802, 0x1c01f000, 0x480fc857, 0x41785800,
+	0x42006000, 0x0000001e, 0x41786800, 0x0401feb7,
+	0x400c6800, 0x80346960, 0x0401feba, 0x42006800,
+	0x00000001, 0x0401feb1, 0x400c6800, 0x0401feb5,
+	0x42006800, 0x00000003, 0x0401feac, 0x0401feb7,
+	0x40400000, 0x8c000504, 0x040207fc, 0x1c01f000,
+	0x42000000, 0x00000064, 0x80000040, 0x040207ff,
+	0x1c01f000, 0x00020103, 0x00101bd5, 0x00101bdb,
+	0x00101be1, 0x00101be9, 0x00101bef, 0x00101bf7,
+	0x00101bff, 0x00101c09, 0x00101c0f, 0x00101c17,
+	0x00101c1f, 0x00101c29, 0x00101c31, 0x00101c3b,
+	0x00101c45, 0x000200f8, 0x00101c51, 0x00101c59,
+	0x00101c61, 0x00101c6b, 0x00101c73, 0x00101c7d,
+	0x00101c87, 0x00101c93, 0x00101c9b, 0x00101ca5,
+	0x00101caf, 0x00101cbb, 0x00101cc5, 0x00101cd1,
+	0x00101cdd, 0x000200fd, 0x00101ceb, 0x00101cf3,
+	0x00101cfb, 0x00101d05, 0x00101d0d, 0x00101d17,
+	0x00101d21, 0x00101d2d, 0x00101d35, 0x00101d3f,
+	0x00101d49, 0x00101d55, 0x00101d5f, 0x00101d6b,
+	0x00101d77, 0x00101d85, 0x00101d8d, 0x00101d97,
+	0x00101da1, 0x00101dad, 0x00101db7, 0x00101dc3,
+	0x00101dcf, 0x00101ddd, 0x00101de7, 0x00101df3,
+	0x00101dff, 0x00101e0d, 0x00101e19, 0x00101e27,
+	0x00101e35, 0x4c000000, 0x4df00000, 0x0201f800,
+	0x00020104, 0x0201f000, 0x00020101, 0x4c000000,
+	0x4df00000, 0x0201f800, 0x00101418, 0x0201f000,
+	0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+	0x00101418, 0x0201f800, 0x00020104, 0x0201f000,
+	0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+	0x00101155, 0x0201f000, 0x00020101, 0x4c000000,
+	0x4df00000, 0x0201f800, 0x00101155, 0x0201f800,
+	0x00020104, 0x0201f000, 0x00020101, 0x4c000000,
+	0x4df00000, 0x0201f800, 0x00101155, 0x0201f800,
+	0x00101418, 0x0201f000, 0x00020101, 0x4c000000,
+	0x4df00000, 0x0201f800, 0x00101155, 0x0201f800,
+	0x00101418, 0x0201f800, 0x00020104, 0x0201f000,
+	0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+	0x00101289, 0x0201f000, 0x00020101, 0x4c000000,
+	0x4df00000, 0x0201f800, 0x00101289, 0x0201f800,
+	0x00020104, 0x0201f000, 0x00020101, 0x4c000000,
+	0x4df00000, 0x0201f800, 0x00101418, 0x0201f800,
+	0x00101289, 0x0201f000, 0x00020101, 0x4c000000,
+	0x4df00000, 0x0201f800, 0x00101418, 0x0201f800,
+	0x00101289, 0x0201f800, 0x00020104, 0x0201f000,
+	0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+	0x00101155, 0x0201f800, 0x00101289, 0x0201f000,
+	0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+	0x00101155, 0x0201f800, 0x00101289, 0x0201f800,
+	0x00020104, 0x0201f000, 0x00020101, 0x4c000000,
+	0x4df00000, 0x0201f800, 0x00101155, 0x0201f800,
+	0x00101418, 0x0201f800, 0x00101289, 0x0201f000,
+	0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+	0x00101155, 0x0201f800, 0x00101418, 0x0201f800,
+	0x00101289, 0x0201f800, 0x00020104, 0x0201f000,
+	0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+	0x00020729, 0x0201f800, 0x00020104, 0x0201f000,
+	0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+	0x00101418, 0x0201f800, 0x00020729, 0x0201f000,
+	0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+	0x00101418, 0x0201f800, 0x00020729, 0x0201f800,
+	0x00020104, 0x0201f000, 0x00020101, 0x4c000000,
+	0x4df00000, 0x0201f800, 0x00101155, 0x0201f800,
+	0x00020729, 0x0201f000, 0x00020101, 0x4c000000,
+	0x4df00000, 0x0201f800, 0x00101155, 0x0201f800,
+	0x00020729, 0x0201f800, 0x00020104, 0x0201f000,
+	0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+	0x00101155, 0x0201f800, 0x00101418, 0x0201f800,
+	0x00020729, 0x0201f000, 0x00020101, 0x4c000000,
+	0x4df00000, 0x0201f800, 0x00101155, 0x0201f800,
+	0x00101418, 0x0201f800, 0x00020729, 0x0201f800,
+	0x00020104, 0x0201f000, 0x00020101, 0x4c000000,
+	0x4df00000, 0x0201f800, 0x00020729, 0x0201f800,
+	0x00101289, 0x0201f000, 0x00020101, 0x4c000000,
+	0x4df00000, 0x0201f800, 0x00020729, 0x0201f800,
+	0x00101289, 0x0201f800, 0x00020104, 0x0201f000,
+	0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+	0x00101418, 0x0201f800, 0x00020729, 0x0201f800,
+	0x00101289, 0x0201f000, 0x00020101, 0x4c000000,
+	0x4df00000, 0x0201f800, 0x00101418, 0x0201f800,
+	0x00020729, 0x0201f800, 0x00101289, 0x0201f800,
+	0x00020104, 0x0201f000, 0x00020101, 0x4c000000,
+	0x4df00000, 0x0201f800, 0x00101155, 0x0201f800,
+	0x00020729, 0x0201f800, 0x00101289, 0x0201f000,
+	0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+	0x00101155, 0x0201f800, 0x00020729, 0x0201f800,
+	0x00101289, 0x0201f800, 0x00020104, 0x0201f000,
+	0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+	0x00101155, 0x0201f800, 0x00101418, 0x0201f800,
+	0x00020729, 0x0201f800, 0x00101289, 0x0201f000,
+	0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+	0x00101155, 0x0201f800, 0x00101418, 0x0201f800,
+	0x00020729, 0x0201f800, 0x00101289, 0x0201f800,
+	0x00020104, 0x0201f000, 0x00020101, 0x4c000000,
+	0x4df00000, 0x0201f800, 0x00020015, 0x0201f800,
+	0x00020104, 0x0201f000, 0x00020101, 0x4c000000,
+	0x4df00000, 0x0201f800, 0x00101418, 0x0201f800,
+	0x00020015, 0x0201f000, 0x00020101, 0x4c000000,
+	0x4df00000, 0x0201f800, 0x00101418, 0x0201f800,
+	0x00020015, 0x0201f800, 0x00020104, 0x0201f000,
+	0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+	0x00101155, 0x0201f800, 0x00020015, 0x0201f000,
+	0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+	0x00101155, 0x0201f800, 0x00020015, 0x0201f800,
+	0x00020104, 0x0201f000, 0x00020101, 0x4c000000,
+	0x4df00000, 0x0201f800, 0x00101418, 0x0201f800,
+	0x00101155, 0x0201f800, 0x00020015, 0x0201f000,
+	0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+	0x00101418, 0x0201f800, 0x00101155, 0x0201f800,
+	0x00020015, 0x0201f800, 0x00020104, 0x0201f000,
+	0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+	0x00020015, 0x0201f800, 0x00101289, 0x0201f000,
+	0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+	0x00020015, 0x0201f800, 0x00101289, 0x0201f800,
+	0x00020104, 0x0201f000, 0x00020101, 0x4c000000,
+	0x4df00000, 0x0201f800, 0x00101418, 0x0201f800,
+	0x00020015, 0x0201f800, 0x00101289, 0x0201f000,
+	0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+	0x00101418, 0x0201f800, 0x00020015, 0x0201f800,
+	0x00101289, 0x0201f800, 0x00020104, 0x0201f000,
+	0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+	0x00020015, 0x0201f800, 0x00101289, 0x0201f800,
+	0x00101155, 0x0201f000, 0x00020101, 0x4c000000,
+	0x4df00000, 0x0201f800, 0x00020015, 0x0201f800,
+	0x00101289, 0x0201f800, 0x00101155, 0x0201f800,
+	0x00020104, 0x0201f000, 0x00020101, 0x4c000000,
+	0x4df00000, 0x0201f800, 0x00101418, 0x0201f800,
+	0x00020015, 0x0201f800, 0x00101289, 0x0201f800,
+	0x00101155, 0x0201f000, 0x00020101, 0x4c000000,
+	0x4df00000, 0x0201f800, 0x00101418, 0x0201f800,
+	0x00020015, 0x0201f800, 0x00101289, 0x0201f800,
+	0x00101155, 0x0201f800, 0x00020104, 0x0201f000,
+	0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+	0x00020729, 0x0201f800, 0x00020015, 0x0201f000,
+	0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+	0x00020729, 0x0201f800, 0x00020015, 0x0201f800,
+	0x00020104, 0x0201f000, 0x00020101, 0x4c000000,
+	0x4df00000, 0x0201f800, 0x00101418, 0x0201f800,
+	0x00020729, 0x0201f800, 0x00020015, 0x0201f000,
+	0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+	0x00101418, 0x0201f800, 0x00020729, 0x0201f800,
+	0x00020015, 0x0201f800, 0x00020104, 0x0201f000,
+	0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+	0x00020729, 0x0201f800, 0x00020015, 0x0201f800,
+	0x00101155, 0x0201f000, 0x00020101, 0x4c000000,
+	0x4df00000, 0x0201f800, 0x00020729, 0x0201f800,
+	0x00020015, 0x0201f800, 0x00101155, 0x0201f800,
+	0x00020104, 0x0201f000, 0x00020101, 0x4c000000,
+	0x4df00000, 0x0201f800, 0x00101418, 0x0201f800,
+	0x00020729, 0x0201f800, 0x00020015, 0x0201f800,
+	0x00101155, 0x0201f000, 0x00020101, 0x4c000000,
+	0x4df00000, 0x0201f800, 0x00101418, 0x0201f800,
+	0x00020729, 0x0201f800, 0x00020015, 0x0201f800,
+	0x00101155, 0x0201f800, 0x00020104, 0x0201f000,
+	0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+	0x00020729, 0x0201f800, 0x00020015, 0x0201f800,
+	0x00101289, 0x0201f000, 0x00020101, 0x4c000000,
+	0x4df00000, 0x0201f800, 0x00020729, 0x0201f800,
+	0x00020015, 0x0201f800, 0x00101289, 0x0201f800,
+	0x00020104, 0x0201f000, 0x00020101, 0x4c000000,
+	0x4df00000, 0x0201f800, 0x00101418, 0x0201f800,
+	0x00020729, 0x0201f800, 0x00020015, 0x0201f800,
+	0x00101289, 0x0201f000, 0x00020101, 0x4c000000,
+	0x4df00000, 0x0201f800, 0x00101418, 0x0201f800,
+	0x00020729, 0x0201f800, 0x00020015, 0x0201f800,
+	0x00101289, 0x0201f800, 0x00020104, 0x0201f000,
+	0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+	0x00101155, 0x0201f800, 0x00020729, 0x0201f800,
+	0x00020015, 0x0201f800, 0x00101289, 0x0201f000,
+	0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+	0x00101155, 0x0201f800, 0x00020729, 0x0201f800,
+	0x00020015, 0x0201f800, 0x00101289, 0x0201f800,
+	0x00020104, 0x0201f000, 0x00020101, 0x4c000000,
+	0x4df00000, 0x0201f800, 0x00101155, 0x0201f800,
+	0x00101418, 0x0201f800, 0x00020729, 0x0201f800,
+	0x00020015, 0x0201f800, 0x00101289, 0x0201f000,
+	0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+	0x00101155, 0x0201f800, 0x00101418, 0x0201f800,
+	0x00020729, 0x0201f800, 0x00020015, 0x0201f800,
+	0x00101289, 0x0201f800, 0x00020104, 0x0201f000,
+	0x00020101, 0x4c5c0000, 0x4c600000, 0x4178b800,
+	0x0201f800, 0x001048ec, 0x040200fd, 0x59a8c026,
+	0x0201f800, 0x0010513b, 0x04000003, 0x8c60c506,
+	0x0400000e, 0x8c60c500, 0x04020004, 0x8c60c50e,
+	0x040008f6, 0x0401f0f2, 0x0401fab4, 0x040200f0,
+	0x0201f800, 0x0010513b, 0x04020004, 0x4a03501c,
+	0x0000ffff, 0x0401f0ea, 0x8c60c504, 0x04000004,
+	0x4a03501c, 0x0000ffff, 0x0401f0e5, 0x59a8c010,
+	0x8260c500, 0x000000ff, 0x59a81013, 0x8c081500,
+	0x0400005d, 0x8c081502, 0x0402005b, 0x59a8b81c,
+	0x825c0d80, 0x0000ffff, 0x04020003, 0x4200b800,
+	0x00000001, 0x805c1104, 0x82086400, 0x0010be21,
+	0x50300800, 0x825c0500, 0x00000003, 0x0c01f001,
+	0x00101e81, 0x00101e7c, 0x00101e80, 0x00101e7e,
+	0x80040910, 0x0401f004, 0x80040930, 0x0401f002,
+	0x80040920, 0x82040500, 0x000000ff, 0x82000d80,
+	0x000000ff, 0x0400000f, 0x4c000000, 0x82000400,
+	0x0010210e, 0x50000800, 0x80040910, 0x82040580,
+	0x00000080, 0x5c000000, 0x04000030, 0x80600d80,
+	0x0400002e, 0x80000540, 0x0400002c, 0x0401f00b,
+	0x59a81005, 0x82081500, 0x00000003, 0x0402002b,
+	0x59a81013, 0x84081542, 0x480b5013, 0x4a03501c,
+	0x0000ffff, 0x0401f028, 0x4c000000, 0x59a80005,
+	0x8c000514, 0x42001000, 0x00000010, 0x02020800,
+	0x00104c6d, 0x5c000000, 0x0402001c, 0x417a8800,
+	0x0201f800, 0x00105c9a, 0x04020016, 0x0201f800,
+	0x001045e5, 0x04000006, 0x0201f800, 0x00104c62,
+	0x0401f8b1, 0x0400000f, 0x0401f00c, 0x599c0019,
+	0x8c00050e, 0x04020009, 0x0201f800, 0x001045a6,
+	0x04020008, 0x0201f800, 0x00104c62, 0x0401f9e1,
+	0x0401f8be, 0x04000003, 0x805cb800, 0x0401f7b2,
+	0x485f501c, 0x0401f086, 0x4a03501c, 0x0000ffff,
+	0x0401f083, 0x42003000, 0x0000007e, 0x59a8001c,
+	0x82001580, 0x0000ffff, 0x04020005, 0x80000d80,
+	0x4018b000, 0x4803c856, 0x0401f009, 0x8018b480,
+	0x04001004, 0x40000800, 0x4803c856, 0x0401f004,
+	0x4a03501c, 0x0000ffff, 0x0401f071, 0x4c040000,
+	0x4c580000, 0x82040400, 0x0010210e, 0x50000000,
+	0x82000500, 0x000000ff, 0x80604580, 0x0400005c,
+	0x0201f800, 0x00105c9b, 0x04020061, 0x59a80005,
+	0x8c000514, 0x42001000, 0x00000010, 0x02020800,
+	0x00104c6d, 0x5c00b000, 0x5c000800, 0x040207d7,
+	0x4c040000, 0x4c580000, 0x845cbd00, 0x0201f800,
+	0x00020245, 0x04000008, 0x599c0019, 0x8c00050e,
+	0x04020047, 0x0201f800, 0x001045ab, 0x0402004c,
+	0x0401f002, 0x845cbd40, 0x0201f800, 0x00104c62,
+	0x0201f800, 0x001049e7, 0x04020007, 0x59a80005,
+	0x8c000502, 0x04000033, 0x59340200, 0x8c00050e,
+	0x04020030, 0x59a81013, 0x8c081502, 0x04000025,
+	0x0201f800, 0x00104a09, 0x04000031, 0x8c5cbd00,
+	0x04020004, 0x0201f800, 0x001045ff, 0x0401f02c,
+	0x0401f9cd, 0x0400002a, 0x42026000, 0x0010bde9,
+	0x49366009, 0x497a6008, 0x417a7800, 0x0401f925,
+	0x42000000, 0x0010b864, 0x0201f800, 0x0010aa47,
+	0x0201f800, 0x00103b25, 0x0400001d, 0x41782800,
+	0x42003000, 0x00000008, 0x4d400000, 0x4d440000,
+	0x59368c03, 0x42028000, 0x00000029, 0x0201f800,
+	0x0010a446, 0x5c028800, 0x5c028000, 0x0401f010,
+	0x4937c857, 0x599c0019, 0x8c00050e, 0x0402000c,
+	0x0401f96c, 0x0401f849, 0x04000011, 0x0401f008,
+	0x59a80013, 0x8c000500, 0x04000003, 0x0401f9a6,
+	0x04000003, 0x0401f828, 0x04000009, 0x5c00b000,
+	0x5c000800, 0x80040800, 0x8058b040, 0x04020798,
+	0x4a03501c, 0x0000ffff, 0x0401f005, 0x4937c857,
+	0x5c00b000, 0x5c000800, 0x4807501c, 0x5c00c000,
+	0x5c00b800, 0x1c01f000, 0x4803c856, 0x4a03501c,
+	0x00000001, 0x42028800, 0x000007fe, 0x42003000,
+	0x00fffffe, 0x0201f800, 0x001045a6, 0x0402000c,
+	0x0401f948, 0x0401f825, 0x04000009, 0x59a80026,
+	0x8400054e, 0x48035026, 0x0201f800, 0x0010930f,
+	0x82000540, 0x00000001, 0x1c01f000, 0x80000580,
+	0x0401f7fe, 0x4937c857, 0x0201f800, 0x00107942,
+	0x04000015, 0x49366009, 0x4a026406, 0x00000001,
+	0x417a7800, 0x0201f800, 0x00104567, 0x59a8001b,
+	0x80000000, 0x4803501b, 0x42027000, 0x00000004,
+	0x599c0019, 0x8c00050e, 0x04000003, 0x42027000,
+	0x00000000, 0x0201f800, 0x000207a1, 0x82000540,
+	0x00000001, 0x1c01f000, 0x4937c857, 0x0201f800,
+	0x00107942, 0x0400001c, 0x49366009, 0x59340403,
+	0x82000580, 0x000007fe, 0x04000005, 0x4d3c0000,
+	0x417a7800, 0x0401f8b7, 0x5c027800, 0x4a026406,
+	0x00000001, 0x417a7800, 0x0201f800, 0x00104567,
+	0x42000800, 0x00000003, 0x0201f800, 0x00104571,
+	0x59a8001b, 0x80000000, 0x4803501b, 0x42027000,
+	0x00000002, 0x0201f800, 0x000207a1, 0x82000540,
+	0x00000001, 0x1c01f000, 0x4803c856, 0x42028800,
+	0x000007fc, 0x42003000, 0x00fffffc, 0x0201f800,
+	0x001045a6, 0x04020005, 0x0401f805, 0x04000003,
+	0x4a035027, 0x0000ffff, 0x1c01f000, 0x4937c857,
+	0x0201f800, 0x00107942, 0x04000014, 0x49366009,
+	0x4a026406, 0x00000001, 0x417a7800, 0x0201f800,
+	0x00104567, 0x42000800, 0x00000003, 0x0201f800,
+	0x00104571, 0x59a80028, 0x80000000, 0x48035028,
+	0x42027000, 0x00000002, 0x0201f800, 0x000207a1,
+	0x82000540, 0x00000001, 0x1c01f000, 0x480bc857,
+	0x492fc857, 0x4c5c0000, 0x4008b800, 0x42028800,
+	0x000007fd, 0x42003000, 0x00fffffd, 0x0201f800,
+	0x001045a6, 0x0402001a, 0x0201f800, 0x0002075a,
+	0x04000017, 0x49366009, 0x5934000a, 0x84000544,
+	0x4802680a, 0x812e59c0, 0x04000005, 0x592c0404,
+	0x8c00051e, 0x04000002, 0x48ee6021, 0x492e6008,
+	0x4a026406, 0x00000001, 0x485e601c, 0x42027000,
+	0x00000022, 0x0201f800, 0x000207a1, 0x82000540,
+	0x00000001, 0x5c00b800, 0x1c01f000, 0x80000580,
+	0x0401f7fd, 0x5c000000, 0x4c000000, 0x4803c857,
+	0x4943c857, 0x493fc857, 0x4d340000, 0x4d440000,
+	0x4c580000, 0x4d2c0000, 0x4c5c0000, 0x0201f800,
+	0x00106c55, 0x4df00000, 0x0201f800, 0x001069f1,
+	0x0201f800, 0x00106aac, 0x0201f800, 0x00106737,
+	0x0201f800, 0x0010848a, 0x5c03e000, 0x02000800,
+	0x00106c4b, 0x4200b000, 0x000007f0, 0x417a8800,
+	0x0201f800, 0x00020245, 0x0402001f, 0x8d3e7d14,
+	0x04000005, 0x59340212, 0x82000500, 0x0000ff00,
+	0x04000019, 0x8d3e7d06, 0x04000004, 0x59340200,
+	0x8c00050e, 0x04020014, 0x8d3e7d18, 0x0400000f,
+	0x5934b80f, 0x805cb9c0, 0x04000009, 0x49425a06,
+	0x592cb800, 0x0201f800, 0x000202ce, 0x805cb9c0,
+	0x040207fb, 0x497a680f, 0x497a6810, 0x4a026c00,
+	0x00000707, 0x0401f004, 0x4937c857, 0x0201f800,
+	0x001042b4, 0x81468800, 0x8058b040, 0x040207dd,
+	0x8d3e7d02, 0x04000011, 0x497b501d, 0x42028800,
+	0x000007f0, 0x4200b000, 0x00000010, 0x0201f800,
+	0x00020245, 0x04020006, 0x4937c857, 0x4a026c00,
+	0x00000707, 0x0201f800, 0x001042b4, 0x81468800,
+	0x8058b040, 0x040207f6, 0x5c00b800, 0x5c025800,
+	0x5c00b000, 0x5c028800, 0x5c026800, 0x1c01f000,
+	0x5c000000, 0x4c000000, 0x4803c857, 0x4933c857,
+	0x493fc857, 0x4d340000, 0x4d400000, 0x4d440000,
+	0x4d2c0000, 0x4c5c0000, 0x0201f800, 0x00106c55,
+	0x4df00000, 0x59326809, 0x813669c0, 0x04000020,
+	0x59368c03, 0x42028000, 0x00000029, 0x0201f800,
+	0x00106a50, 0x0201f800, 0x00106ab4, 0x0201f800,
+	0x001067fd, 0x0201f800, 0x0010a2ff, 0x4937c857,
+	0x8d3e7d18, 0x04000010, 0x5934b80f, 0x805cb9c0,
+	0x0400000a, 0x405e5800, 0x49425a06, 0x592cb800,
+	0x0201f800, 0x000202ce, 0x805cb9c0, 0x040207fa,
+	0x497a680f, 0x497a6810, 0x4a026c00, 0x00000707,
+	0x0401f003, 0x0201f800, 0x001042b4, 0x5c03e000,
+	0x02000800, 0x00106c4b, 0x5c00b800, 0x5c025800,
+	0x5c028800, 0x5c028000, 0x5c026800, 0x1c01f000,
+	0x4933c857, 0x59a80026, 0x8c000508, 0x04020012,
+	0x59305009, 0x482bc857, 0x836c0580, 0x00000002,
+	0x0402000d, 0x0401f813, 0x0402000b, 0x58280403,
+	0x82000580, 0x000007fc, 0x04000008, 0x59a8001b,
+	0x80000040, 0x4803c857, 0x02001800, 0x001005d8,
+	0x4803501b, 0x1c01f000, 0x59a80028, 0x80000040,
+	0x4803c857, 0x040017fc, 0x48035028, 0x1c01f000,
+	0x59300008, 0x800001c0, 0x04020009, 0x59300403,
+	0x82000580, 0x00000001, 0x04020004, 0x82000540,
+	0x00000001, 0x0401f002, 0x80000580, 0x1c01f000,
+	0x4937c857, 0x59340200, 0x84000502, 0x48026a00,
+	0x1c01f000, 0x4933c857, 0x493fc857, 0x4947c857,
+	0x4d3c0000, 0x4d400000, 0x4d340000, 0x4d440000,
+	0x4c580000, 0x0201f800, 0x00106c55, 0x4df00000,
+	0x813e79c0, 0x04020004, 0x4200b000, 0x00000001,
+	0x0401f004, 0x4200b000, 0x000007f0, 0x417a8800,
+	0x41440000, 0x81ac0400, 0x50000000, 0x80026d40,
+	0x04000019, 0x42027800, 0x00000001, 0x0201f800,
+	0x001048f6, 0x42028000, 0x00000029, 0x417a7800,
+	0x0201f800, 0x00106a50, 0x0201f800, 0x00106ab4,
+	0x0201f800, 0x001067fd, 0x0201f800, 0x001049e7,
+	0x04020005, 0x4937c857, 0x4a026c00, 0x00000404,
+	0x0401f003, 0x0201f800, 0x00104a14, 0x0201f800,
+	0x0010a2ff, 0x81468800, 0x8058b040, 0x040207e1,
+	0x5c03e000, 0x02000800, 0x00106c4b, 0x5c00b000,
+	0x5c028800, 0x5c026800, 0x5c028000, 0x5c027800,
+	0x1c01f000, 0x4937c857, 0x4947c857, 0x4c5c0000,
+	0x4c600000, 0x4c640000, 0x59a80013, 0x8c000500,
+	0x0400001f, 0x599c0017, 0x8c00050a, 0x0402001c,
+	0x5934ba02, 0x825cbd00, 0x000000ff, 0x485fc857,
+	0x4178c000, 0x4178c800, 0x82600400, 0x0010be21,
+	0x50002000, 0x8060c1c0, 0x04000008, 0x82100500,
+	0x000000ff, 0x82002d80, 0x000000ff, 0x0400000c,
+	0x805c0580, 0x0400000d, 0x80102110, 0x8064c800,
+	0x82640580, 0x00000004, 0x040207f5, 0x8060c000,
+	0x82600580, 0x00000020, 0x040207eb, 0x4813c857,
+	0x82000540, 0x00000001, 0x5c00c800, 0x5c00c000,
+	0x5c00b800, 0x1c01f000, 0x59a80026, 0x4803c857,
+	0x8c000512, 0x1c01f000, 0x00007eef, 0x00007de8,
+	0x00007ce4, 0x000080e2, 0x00007be1, 0x000080e0,
+	0x000080dc, 0x000080da, 0x00007ad9, 0x000080d6,
+	0x000080d5, 0x000080d4, 0x000080d3, 0x000080d2,
+	0x000080d1, 0x000079ce, 0x000078cd, 0x000080cc,
+	0x000080cb, 0x000080ca, 0x000080c9, 0x000080c7,
+	0x000080c6, 0x000077c5, 0x000076c3, 0x000080bc,
+	0x000080ba, 0x000075b9, 0x000080b6, 0x000074b5,
+	0x000073b4, 0x000072b3, 0x000080b2, 0x000080b1,
+	0x000080ae, 0x000071ad, 0x000080ac, 0x000070ab,
+	0x00006faa, 0x00006ea9, 0x000080a7, 0x00006da6,
+	0x00006ca5, 0x00006ba3, 0x00006a9f, 0x0000699e,
+	0x0000689d, 0x0000809b, 0x00008098, 0x00006797,
+	0x00006690, 0x0000658f, 0x00006488, 0x00006384,
+	0x00006282, 0x00008081, 0x00008080, 0x0000617c,
+	0x0000607a, 0x00008079, 0x00005f76, 0x00008075,
+	0x00008074, 0x00008073, 0x00008072, 0x00008071,
+	0x0000806e, 0x00005e6d, 0x0000806c, 0x00005d6b,
+	0x00005c6a, 0x00005b69, 0x00008067, 0x00005a66,
+	0x00005965, 0x00005863, 0x0000575c, 0x0000565a,
+	0x00005559, 0x00008056, 0x00008055, 0x00005454,
+	0x00005353, 0x00005252, 0x00005151, 0x0000504e,
+	0x00004f4d, 0x0000804c, 0x0000804b, 0x00004e4a,
+	0x00004d49, 0x00008047, 0x00004c46, 0x00008045,
+	0x00008043, 0x0000803c, 0x0000803a, 0x00008039,
+	0x00008036, 0x00004b35, 0x00008034, 0x00004a33,
+	0x00004932, 0x00004831, 0x0000802e, 0x0000472d,
+	0x0000462c, 0x0000452b, 0x0000442a, 0x00004329,
+	0x00004227, 0x00008026, 0x00008025, 0x00004123,
+	0x0000401f, 0x00003f1e, 0x00003e1d, 0x00003d1b,
+	0x00003c18, 0x00008017, 0x00008010, 0x00003b0f,
+	0x00003a08, 0x00008004, 0x00003902, 0x00008001,
+	0x00008000, 0x00008000, 0x00003800, 0x00003700,
+	0x00003600, 0x00008000, 0x00003500, 0x00008000,
+	0x00008000, 0x00008000, 0x00003400, 0x00008000,
+	0x00008000, 0x00008000, 0x00008000, 0x00008000,
+	0x00008000, 0x00003300, 0x00003200, 0x00008000,
+	0x00008000, 0x00008000, 0x00008000, 0x00008000,
+	0x00008000, 0x00003100, 0x00003000, 0x00008000,
+	0x00008000, 0x00002f00, 0x00008000, 0x00002e00,
+	0x00002d00, 0x00002c00, 0x00008000, 0x00008000,
+	0x00008000, 0x00002b00, 0x00008000, 0x00002a00,
+	0x00002900, 0x00002800, 0x00008000, 0x00002700,
+	0x00002600, 0x00002500, 0x00002400, 0x00002300,
+	0x00002200, 0x00008000, 0x00008000, 0x00002100,
+	0x00002000, 0x00001f00, 0x00001e00, 0x00001d00,
+	0x00001c00, 0x00008000, 0x00008000, 0x00001b00,
+	0x00001a00, 0x00008000, 0x00001900, 0x00008000,
+	0x00008000, 0x00008000, 0x00008000, 0x00008000,
+	0x00008000, 0x00001800, 0x00008000, 0x00001700,
+	0x00001600, 0x00001500, 0x00008000, 0x00001400,
+	0x00001300, 0x00001200, 0x00001100, 0x00001000,
+	0x00000f00, 0x00008000, 0x00008000, 0x00000e00,
+	0x00000d00, 0x00000c00, 0x00000b00, 0x00000a00,
+	0x00000900, 0x00008000, 0x00008000, 0x00000800,
+	0x00000700, 0x00008000, 0x00000600, 0x00008000,
+	0x00008000, 0x00008000, 0x00000500, 0x00000400,
+	0x00000300, 0x00008000, 0x00000200, 0x00008000,
+	0x00008000, 0x00008000, 0x00000100, 0x00008000,
+	0x00008000, 0x00008000, 0x00008000, 0x00008000,
+	0x00008000, 0x00000000, 0x00008000, 0x00008000,
+	0x00008000, 0x00008000, 0x00008000, 0x00008000,
+	0x00008000, 0x00008000, 0x00008000, 0x00008000,
+	0x00008000, 0x00008000, 0x00008000, 0x00008000,
+	0x00008000, 0x00008000, 0x0201f800, 0x001007d3,
+	0x02000800, 0x001005d8, 0x492f4016, 0x1c01f000,
+	0x83a0ac00, 0x00000006, 0x83a00580, 0x0010b4a4,
+	0x0400000c, 0x492fc857, 0x812e59c0, 0x02000800,
+	0x001005d8, 0x832ca400, 0x00000006, 0x4200b000,
+	0x0000000d, 0x0201f800, 0x0010ab17, 0x0401f00f,
+	0x4200b000, 0x00000010, 0x83e0a400, 0x00000020,
+	0x50500000, 0x8050a000, 0x50500800, 0x900409c0,
+	0x80040540, 0x4400a800, 0x8050a000, 0x8054a800,
+	0x8058b040, 0x040207f7, 0x1c01f000, 0x59a00206,
+	0x4803c857, 0x82000c80, 0x0000007f, 0x040210c9,
+	0x59a80821, 0x0c01f001, 0x001022c0, 0x00102300,
+	0x00102300, 0x0010234b, 0x0010236d, 0x00102300,
+	0x001022c0, 0x0010238f, 0x001023a0, 0x00102300,
+	0x00102300, 0x001023ad, 0x001023c5, 0x001023dd,
+	0x00102300, 0x001023e7, 0x001023f4, 0x00102300,
+	0x0010241d, 0x00102300, 0x0010247a, 0x00102300,
+	0x00102300, 0x00102300, 0x00102300, 0x00102300,
+	0x00102300, 0x00102300, 0x00102300, 0x00102300,
+	0x00102300, 0x00102300, 0x00102491, 0x00102300,
+	0x001024e3, 0x00102300, 0x00102300, 0x00102300,
+	0x00102300, 0x001024e8, 0x00102560, 0x00102300,
+	0x00102567, 0x00102300, 0x00102300, 0x00102300,
+	0x00102300, 0x00102300, 0x00102569, 0x001025ea,
+	0x00102727, 0x00102300, 0x00102300, 0x00102300,
+	0x00102300, 0x00102300, 0x00102736, 0x00102300,
+	0x00102300, 0x00102300, 0x00102300, 0x00102300,
+	0x00102300, 0x00102300, 0x00102753, 0x001027a6,
+	0x00102802, 0x00102816, 0x00102835, 0x00102a70,
+	0x00102dff, 0x00102300, 0x00102300, 0x00102300,
+	0x00102300, 0x00102300, 0x00102300, 0x00102300,
+	0x00102300, 0x00102300, 0x00102300, 0x00102300,
+	0x00102300, 0x00102fb4, 0x00103028, 0x00102300,
+	0x00102300, 0x00103094, 0x00102300, 0x00103126,
+	0x001031d8, 0x00102300, 0x00102300, 0x0010320f,
+	0x0010326b, 0x00102300, 0x001032bd, 0x00103419,
+	0x00102300, 0x0010342d, 0x001034b8, 0x00102300,
+	0x00102300, 0x00102300, 0x00102300, 0x00103522,
+	0x00103526, 0x00103545, 0x00102300, 0x001035e7,
+	0x00102300, 0x00102300, 0x00103615, 0x00102300,
+	0x00103643, 0x00102300, 0x00102300, 0x001036aa,
+	0x001037b7, 0x00103814, 0x00102300, 0x0010387a,
+	0x00102300, 0x00102300, 0x001038d3, 0x00103936,
+	0x00102300, 0x48efc857, 0x4031d800, 0x58ef400b,
+	0x58ec0002, 0x82000580, 0x00000200, 0x04000045,
+	0x48efc857, 0x4a034206, 0x00004000, 0x0201f800,
+	0x00103a15, 0x83a00580, 0x0010b4a4, 0x0400000d,
+	0x58ee580a, 0x4d2c0000, 0x0401f856, 0x41a25800,
+	0x0201f800, 0x001007f4, 0x40ee5800, 0x0201f800,
+	0x001007f4, 0x5c025800, 0x0201f000, 0x000202da,
+	0x04026007, 0x59a0001d, 0x84000542, 0x4803401d,
+	0x4a01d809, 0x001022d4, 0x1c01f000, 0x59a00206,
+	0x82000d80, 0x00004000, 0x04000006, 0x900001c0,
+	0x82000540, 0x00000011, 0x4803c011, 0x0401f005,
+	0x900001c0, 0x82000540, 0x00000010, 0x4803c011,
+	0x0401f845, 0x59e00017, 0x8c000508, 0x0402000c,
+	0x4203e000, 0x30000001, 0x4203e000, 0x40000000,
+	0x40ee5800, 0x0201f800, 0x001007f4, 0x59a0001d,
+	0x84000504, 0x4803401d, 0x1c01f000, 0x4a03c017,
+	0x00000000, 0x59a00206, 0x82000d80, 0x00004000,
+	0x040007f0, 0x4a03c017, 0x00000001, 0x0401f7ed,
+	0x4803c856, 0x4a034206, 0x00004001, 0x0401f7c0,
+	0x4803c856, 0x4a034206, 0x00004002, 0x0401f7bc,
+	0x4803c856, 0x4a034206, 0x00004003, 0x0401f7b8,
+	0x4803c856, 0x4a034206, 0x00004005, 0x0401f7b4,
+	0x4803c856, 0x4a034206, 0x00004006, 0x0401f7b0,
+	0x4803c856, 0x4a034206, 0x0000400b, 0x0401f7ac,
+	0x4803c856, 0x4a034206, 0x0000400c, 0x0401f7a8,
+	0x4803c856, 0x4a034206, 0x0000400c, 0x0401f7a4,
+	0x48efc857, 0x58eca80a, 0x8054a9c0, 0x02000800,
+	0x001005d8, 0x83a0a400, 0x00000006, 0x8254ac00,
+	0x00000006, 0x4200b000, 0x0000000d, 0x0201f000,
+	0x0010ab17, 0x59a00206, 0x4803c857, 0x59a00406,
+	0x4803c857, 0x59a00207, 0x4803c857, 0x59a00407,
+	0x4803c857, 0x59a00208, 0x4803c857, 0x59a00408,
+	0x4803c857, 0x59a00209, 0x4803c857, 0x83e0ac00,
+	0x00000020, 0x83a0a400, 0x00000006, 0x4200b000,
+	0x00000010, 0x50500000, 0x4400a800, 0x8054a800,
+	0x900001c0, 0x4400a800, 0x8054a800, 0x8050a000,
+	0x8058b040, 0x040207f8, 0x1c01f000, 0x59a00406,
+	0x800000c2, 0x59a00a07, 0x900409c0, 0x80040540,
+	0x84000540, 0x59a00c07, 0x8c040d00, 0x04000018,
+	0x59a80805, 0x8c040d0e, 0x040207ba, 0x42000800,
+	0x00000064, 0x80040840, 0x04000007, 0x4a030000,
+	0x00000001, 0x40000000, 0x59801000, 0x8c081500,
+	0x040007f9, 0x04000005, 0x48030004, 0x4a030000,
+	0x00000000, 0x0401f75b, 0x4a030000, 0x00000000,
+	0x4a034406, 0x00000004, 0x040007a2, 0x4803880e,
+	0x0401f754, 0x59a00406, 0x800000c2, 0x59a00c07,
+	0x8c040d00, 0x0400001a, 0x59a80805, 0x8c040d0e,
+	0x0402079c, 0x42000800, 0x00000064, 0x80040840,
+	0x04000007, 0x4a030000, 0x00000001, 0x40000000,
+	0x59801000, 0x8c081500, 0x040007f9, 0x04000007,
+	0x48030004, 0x59800805, 0x48074406, 0x4a030000,
+	0x00000000, 0x0401f73b, 0x4a030000, 0x00000000,
+	0x4a034406, 0x00000004, 0x04000782, 0x4803880e,
+	0x59c4080f, 0x48074406, 0x0401f732, 0x59a01c06,
+	0x59a00207, 0x900c19c0, 0x800c1d40, 0x580c0803,
+	0x80000580, 0x500c1000, 0x80080400, 0x800c1800,
+	0x80040840, 0x040207fc, 0x48034406, 0x900001c0,
+	0x48034207, 0x800001c0, 0x04000722, 0x0401f769,
+	0x4a034406, 0x00000004, 0x4a034207, 0x00000000,
+	0x4a034407, 0x00000010, 0x59a8000d, 0x48034208,
+	0x900001c0, 0x48034408, 0x4a034209, 0x00000002,
+	0x0401f714, 0x59a00407, 0x59a01207, 0x900811c0,
+	0x80081540, 0x59a00409, 0x59a01a09, 0x900c19c0,
+	0x800c1d40, 0x59a00a08, 0x59a00408, 0x900409c0,
+	0x80040d40, 0x59a0020a, 0x82002480, 0x00000010,
+	0x04001754, 0x59a02406, 0x900001c0, 0x80100540,
+	0x59a8280d, 0x80142480, 0x0400174e, 0x0201f000,
+	0x00103a25, 0x59a00407, 0x59a01207, 0x900811c0,
+	0x80081540, 0x59a00409, 0x59a01a09, 0x900c19c0,
+	0x800c1d40, 0x59a00a08, 0x59a00408, 0x900409c0,
+	0x80040d40, 0x59a0020a, 0x82002480, 0x00000010,
+	0x0400173c, 0x59a02406, 0x900001c0, 0x80100540,
+	0x59a8280d, 0x80142480, 0x04001736, 0x0201f000,
+	0x00103a28, 0x59a00a0a, 0x59a00406, 0x900409c0,
+	0x80040d40, 0x59a01407, 0x59a00207, 0x900811c0,
+	0x80081540, 0x44080800, 0x0401f6da, 0x59a00a0a,
+	0x59a00406, 0x900409c0, 0x80040d40, 0x50040000,
+	0x82000d00, 0x0000ffff, 0x48074207, 0x82000d00,
+	0xffff0000, 0x900409c0, 0x48074407, 0x0401f6cd,
+	0x59a00406, 0x8c000500, 0x04000020, 0x59a01207,
+	0x59a01c07, 0x59a02208, 0x480b5054, 0x480f5055,
+	0x48135056, 0x59c40801, 0x82040d00, 0x00018000,
+	0x82040580, 0x00000000, 0x04000009, 0x82040580,
+	0x00008000, 0x04000008, 0x82040580, 0x00010000,
+	0x04000007, 0x0201f800, 0x001005d8, 0x40080000,
+	0x0401f004, 0x400c0000, 0x0401f002, 0x40100000,
+	0x80000110, 0x42000800, 0x000000e0, 0x0201f800,
+	0x00101944, 0x0401f007, 0x59a81054, 0x59a81855,
+	0x59a82056, 0x480b4207, 0x480f4407, 0x48134208,
+	0x0401f6a4, 0x4d2c0000, 0x4d340000, 0x4d300000,
+	0x4d440000, 0x59a28c06, 0x0201f800, 0x00020245,
+	0x04000006, 0x5c028800, 0x5c026000, 0x5c026800,
+	0x5c025800, 0x0401f6e7, 0x59a04407, 0x59a00207,
+	0x900001c0, 0x80204540, 0x0401f81e, 0x04000009,
+	0x4a034208, 0x00000001, 0x4a034406, 0x0000ffff,
+	0x4a034207, 0x0000ffff, 0x497b4407, 0x0401f00b,
+	0x0401f822, 0x0400000e, 0x4a034208, 0x00000002,
+	0x59300402, 0x48034406, 0x59300202, 0x48034207,
+	0x59300206, 0x48034407, 0x5c028800, 0x5c026000,
+	0x5c026800, 0x5c025800, 0x0401f67a, 0x5c028800,
+	0x5c026000, 0x5c026800, 0x5c025800, 0x0401f6c1,
+	0x4937c856, 0x4823c856, 0x4d2c0000, 0x5934000f,
+	0x80025d40, 0x04000007, 0x592c0005, 0x80200580,
+	0x592c0000, 0x040207fb, 0x82000540, 0x00000001,
+	0x5c025800, 0x1c01f000, 0x4823c857, 0x4d2c0000,
+	0x4d300000, 0x42026000, 0x0010d1c0, 0x59300406,
+	0x82000d80, 0x00000003, 0x04000004, 0x82000d80,
+	0x00000006, 0x04020007, 0x59325808, 0x812e59c0,
+	0x04000004, 0x592c0005, 0x80200580, 0x0400000a,
+	0x83326400, 0x00000024, 0x41580000, 0x81300480,
+	0x040017ef, 0x80000580, 0x5c026000, 0x5c025800,
+	0x1c01f000, 0x82000540, 0x00000001, 0x5c026000,
+	0x5c025800, 0x1c01f000, 0x83a00580, 0x0010b4a4,
+	0x04020684, 0x59a80005, 0x8c00050e, 0x04020003,
+	0x4a030000, 0x00000000, 0x4a034206, 0x00004000,
+	0x4a03c011, 0x40000010, 0x0401fea7, 0x59e00017,
+	0x8c000508, 0x04000003, 0x4a03c017, 0x00000000,
+	0x4203e000, 0x30000001, 0x4203e000, 0x40000000,
+	0x0401f000, 0x800409c0, 0x04000004, 0x4a034406,
+	0x00000001, 0x0401f677, 0x836c0580, 0x00000003,
+	0x04020010, 0x59a80010, 0x497b4406, 0x0201f800,
+	0x0010513b, 0x0400000f, 0x82000d00, 0x00ffff00,
+	0x0402000c, 0x82000c00, 0x0010210e, 0x50040800,
+	0x80040910, 0x82041580, 0x00000080, 0x04020004,
+	0x4a034406, 0x00000007, 0x0401f662, 0x48074406,
+	0x82000d00, 0x0000ffff, 0x48074207, 0x80000120,
+	0x48034407, 0x59a80026, 0x82001500, 0x00000100,
+	0x480b4409, 0x8c000502, 0x0400001f, 0x8c000506,
+	0x04000009, 0x82000d00, 0x0000000a, 0x82040d80,
+	0x0000000a, 0x04020004, 0x4a034209, 0x00000001,
+	0x0401f022, 0x8c00050a, 0x04000009, 0x82000d00,
+	0x00000022, 0x82040d80, 0x00000022, 0x04020004,
+	0x4a034209, 0x00000003, 0x0401f018, 0x8c000508,
+	0x04000009, 0x82000d00, 0x00000012, 0x82040d80,
+	0x00000012, 0x04020004, 0x4a034209, 0x00000002,
+	0x0401f00e, 0x0201f800, 0x0010513b, 0x04020004,
+	0x4a034209, 0x00000004, 0x0401f5e6, 0x8c000506,
+	0x04000004, 0x4a034406, 0x00000005, 0x0401f62d,
+	0x4a034209, 0x00000000, 0x0401f5de, 0x59a80037,
+	0x48034407, 0x59a80038, 0x48034209, 0x0401f5d9,
+	0x42007800, 0x0010b8ec, 0x59a00406, 0x4803c857,
+	0x82000c80, 0x00000006, 0x04021622, 0x0c01f001,
+	0x001024f6, 0x001024f7, 0x00102505, 0x00102518,
+	0x00102539, 0x001024f6, 0x0401f61a, 0x836c0580,
+	0x00000000, 0x04000613, 0x59a00a07, 0x59a00407,
+	0x900001c0, 0x80040d40, 0x4807c857, 0x59a00a08,
+	0x59a00408, 0x900001c0, 0x80040d40, 0x4807c857,
+	0x0401f056, 0x836c0580, 0x00000000, 0x04000605,
+	0x59a00407, 0x59a01207, 0x900001c0, 0x80081540,
+	0x59a00408, 0x59a01a08, 0x900001c0, 0x800c1d40,
+	0x42000000, 0x0010c1bf, 0x480fc857, 0x480bc857,
+	0x42000800, 0x00001000, 0x0201f000, 0x00103a28,
+	0x59a00a07, 0x59a00407, 0x900001c0, 0x80041d40,
+	0x820c0c80, 0x0010ab4a, 0x040215f2, 0x820c0c80,
+	0x00100000, 0x040015ef, 0x480fc857, 0x823c7c00,
+	0x00000009, 0x503c0800, 0x800409c0, 0x04000006,
+	0x823c0580, 0x0000000d, 0x040005e6, 0x803c7800,
+	0x0401f7f9, 0x59e41001, 0x82080d00, 0xfffeffcf,
+	0x4807c801, 0x440c7800, 0x46001800, 0x0201f800,
+	0x800c1800, 0x46001800, 0x001005cb, 0x480bc801,
+	0x0401f022, 0x59a01a07, 0x59a00407, 0x900001c0,
+	0x800c1d40, 0x480c7801, 0x59a02208, 0x59a00408,
+	0x900001c0, 0x80102540, 0x48107802, 0x59a00209,
+	0x80000040, 0x040015cb, 0x48007806, 0x80000000,
+	0x48007805, 0x42000800, 0x00004000, 0x40001000,
+	0x0201f800, 0x00106681, 0x80000540, 0x04000003,
+	0x49787801, 0x0401f5bf, 0x40040000, 0x800c1c00,
+	0x040015bc, 0x480c7803, 0x48107804, 0x49787808,
+	0x59a00409, 0x48007807, 0x59e40001, 0x4803c857,
+	0x82000540, 0x00040000, 0x4803c801, 0x0401f561,
+	0x59a80006, 0x48034406, 0x59a80007, 0x48034207,
+	0x59a80008, 0x48034407, 0x0401f55a, 0x0201f800,
+	0x001005d8, 0x4803c856, 0x4a03c013, 0x03800300,
+	0x4a03c014, 0x03800380, 0x59a00c06, 0x82040580,
+	0x000000a0, 0x04000004, 0x82040580, 0x000000a2,
+	0x0402002b, 0x59a0140a, 0x82080480, 0x00000100,
+	0x04021027, 0x59a0020b, 0x8c000500, 0x0402002e,
+	0x59a00a0a, 0x800409c0, 0x04000021, 0x82040480,
+	0x00000041, 0x0402101e, 0x82040c00, 0x00000003,
+	0x82040d00, 0x000000fc, 0x80040904, 0x59a00407,
+	0x59a01207, 0x900811c0, 0x80081540, 0x59a00409,
+	0x59a01a09, 0x900c19c0, 0x800c1d40, 0x0201f800,
+	0x00103a00, 0x04020006, 0x4a034406, 0x00000002,
+	0x4a03c014, 0x03800000, 0x0401f576, 0x832e5c00,
+	0x00000004, 0x412c0000, 0x0201f800, 0x00103a25,
+	0x4a01d809, 0x001025a2, 0x1c01f000, 0x4a03c014,
+	0x03800000, 0x0401f56f, 0x4031d800, 0x58ef400b,
+	0x58ee580d, 0x58ec0002, 0x82000580, 0x00000200,
+	0x0400055c, 0x59a00c06, 0x59a0140a, 0x59a0020b,
+	0x8c000500, 0x04020031, 0x832e5c00, 0x00000004,
+	0x41783800, 0x59a04a0a, 0x401c0000, 0x812c0400,
+	0x50004000, 0x82201d00, 0x000000ff, 0x4c040000,
+	0x0401f8ac, 0x5c000800, 0x0400002d, 0x80244840,
+	0x04000028, 0x80081000, 0x82201d00, 0x0000ff00,
+	0x800c1910, 0x4c040000, 0x0401f8a2, 0x5c000800,
+	0x04000023, 0x80244840, 0x0400001e, 0x80081000,
+	0x82201d00, 0x00ff0000, 0x800c1920, 0x4c040000,
+	0x0401f898, 0x5c000800, 0x04000019, 0x80244840,
+	0x04000014, 0x80081000, 0x82201d00, 0xff000000,
+	0x800c1930, 0x4c040000, 0x0401f88e, 0x5c000800,
+	0x0400000f, 0x80244840, 0x0400000a, 0x80081000,
+	0x801c3800, 0x0401f7d5, 0x59a0020a, 0x82000500,
+	0x000000ff, 0x40001800, 0x0401f882, 0x04000004,
+	0x4a03c014, 0x03800000, 0x0401f4da, 0x4a03c014,
+	0x03800000, 0x0401f523, 0x4803c856, 0x4a03c013,
+	0x03800300, 0x4a03c014, 0x03800380, 0x59a00c06,
+	0x82040580, 0x000000a0, 0x04000004, 0x82040580,
+	0x000000a2, 0x0402006c, 0x59a0140a, 0x82080480,
+	0x00000100, 0x04021068, 0x59a0020b, 0x8c000500,
+	0x0402005c, 0x59a01a0a, 0x800c19c0, 0x04000062,
+	0x820c0480, 0x00000041, 0x0402105f, 0x0201f800,
+	0x00103a00, 0x04020006, 0x4a034406, 0x00000002,
+	0x4a03c014, 0x03800000, 0x0401f502, 0x832e5c00,
+	0x00000004, 0x41783800, 0x59a04a0a, 0x401c0000,
+	0x812c0400, 0x40004000, 0x4c040000, 0x4c080000,
+	0x0401f874, 0x5c001000, 0x5c000800, 0x04000047,
+	0x44144000, 0x80244840, 0x0400002b, 0x80081000,
+	0x4c040000, 0x4c080000, 0x0401f86a, 0x5c001000,
+	0x5c000800, 0x0400003d, 0x50200000, 0x801428d0,
+	0x80140540, 0x44004000, 0x80244840, 0x0400001e,
+	0x80081000, 0x4c040000, 0x4c080000, 0x0401f85d,
+	0x5c001000, 0x5c000800, 0x04000030, 0x50200000,
+	0x801428e0, 0x80140540, 0x44004000, 0x80244840,
+	0x04000011, 0x80081000, 0x4c040000, 0x4c080000,
+	0x0401f850, 0x5c001000, 0x5c000800, 0x04000023,
+	0x50200000, 0x801428f0, 0x80140540, 0x44004000,
+	0x80244840, 0x04000004, 0x80081000, 0x801c3800,
+	0x0401f7cb, 0x59a00a0a, 0x82040c00, 0x00000003,
+	0x82040d00, 0x000000fc, 0x80040904, 0x59a00407,
+	0x59a01207, 0x900811c0, 0x80081540, 0x59a00409,
+	0x59a01a09, 0x900c19c0, 0x800c1d40, 0x4a03c014,
+	0x03800000, 0x412c0000, 0x0201f000, 0x00103a28,
+	0x0401f830, 0x04000005, 0x48174406, 0x4a03c014,
+	0x03800000, 0x0401f463, 0x4a03c014, 0x03800000,
+	0x0401f4ac, 0x4a03c014, 0x03800000, 0x0401f4ad,
+	0x0401f836, 0x04000010, 0x0401f862, 0x0402000f,
+	0x40080800, 0x0401f85f, 0x0402000c, 0x400c0800,
+	0x0401f85c, 0x04020009, 0x0401f84b, 0x42000000,
+	0x00030d40, 0x80000040, 0x040207ff, 0x82000540,
+	0x00000001, 0x1c01f000, 0x0401f843, 0x80000580,
+	0x0401f7fd, 0x0401f821, 0x0400000a, 0x82040d40,
+	0x00000001, 0x0401f84b, 0x04020007, 0x0401f87e,
+	0x0401f898, 0x0401f838, 0x82000540, 0x00000001,
+	0x1c01f000, 0x0401f834, 0x80000580, 0x0401f7fd,
+	0x40041800, 0x0401f811, 0x0400000c, 0x0401f83d,
+	0x0402000b, 0x40080800, 0x0401f83a, 0x04020008,
+	0x400c0800, 0x0401ffe8, 0x04000004, 0x0401f826,
+	0x82000540, 0x00000001, 0x1c01f000, 0x0401f822,
+	0x80000580, 0x0401f7fd, 0x4c040000, 0x42000800,
+	0x00000064, 0x4a03c013, 0x03800300, 0x80040840,
+	0x04000016, 0x59e00013, 0x82000500, 0x00000300,
+	0x82000580, 0x00000300, 0x040207f7, 0x42000000,
+	0x00000064, 0x80000040, 0x040207ff, 0x4a03c013,
+	0x01000000, 0x42000000, 0x00000064, 0x80000040,
+	0x040207ff, 0x4a03c013, 0x02000000, 0x82000540,
+	0x00000001, 0x0401f002, 0x80000580, 0x5c000800,
+	0x1c01f000, 0x4a03c013, 0x01000000, 0x42000000,
+	0x00000064, 0x80000040, 0x040207ff, 0x4a03c013,
+	0x02000200, 0x42000000, 0x00000064, 0x80000040,
+	0x040207ff, 0x4a03c013, 0x01000100, 0x1c01f000,
+	0x42002000, 0x00000008, 0x82040500, 0x00000080,
+	0x800000c2, 0x82000540, 0x01000000, 0x4803c013,
+	0x42000000, 0x00000064, 0x80000040, 0x040207ff,
+	0x4a03c013, 0x02000200, 0x42000000, 0x00000064,
+	0x80000040, 0x040207ff, 0x4a03c013, 0x02000000,
+	0x800408c2, 0x80102040, 0x040207ec, 0x4a03c013,
+	0x01000100, 0x42000000, 0x00000064, 0x80000040,
+	0x040207ff, 0x4a03c013, 0x02000200, 0x42000000,
+	0x00000064, 0x80000040, 0x040207ff, 0x59e00013,
+	0x82000500, 0x00000100, 0x4a03c013, 0x02000000,
+	0x4c040000, 0x42000800, 0x00000064, 0x59e00013,
+	0x82000500, 0x00000100, 0x80040840, 0x04000003,
+	0x80000540, 0x040207fa, 0x80000540, 0x5c000800,
+	0x1c01f000, 0x4a03c013, 0x01000100, 0x42001000,
+	0x00000008, 0x80000d80, 0x42000000, 0x00000064,
+	0x80000040, 0x040207ff, 0x4a03c013, 0x02000200,
+	0x42000000, 0x00000064, 0x80000040, 0x040207ff,
+	0x59e00013, 0x82000500, 0x00000100, 0x80000110,
+	0x800408c2, 0x80040d40, 0x4a03c013, 0x02000000,
+	0x80081040, 0x040207ed, 0x40042800, 0x1c01f000,
+	0x4a03c013, 0x01000100, 0x42000000, 0x00000064,
+	0x80000040, 0x040207ff, 0x4a03c013, 0x02000200,
+	0x42000000, 0x00000064, 0x80000040, 0x040207ff,
+	0x4a03c013, 0x02000000, 0x1c01f000, 0x59a00407,
+	0x59a80837, 0x48035037, 0x48074407, 0x59a00a09,
+	0x82040480, 0x00000014, 0x04021003, 0x42000800,
+	0x000007d0, 0x59a80038, 0x48075038, 0x48034209,
+	0x0201f000, 0x001022c0, 0x836c0580, 0x00000000,
+	0x0400000e, 0x59a80006, 0x59a00c06, 0x80041580,
+	0x82081500, 0x00000040, 0x02000000, 0x001022c0,
+	0x80080580, 0x48035006, 0x0201f800, 0x00100699,
+	0x0201f000, 0x001022c0, 0x59a00406, 0x59a80806,
+	0x48035006, 0x80040d80, 0x8c040d0c, 0x02020800,
+	0x00100699, 0x59a00207, 0x48035007, 0x59a00407,
+	0x48035008, 0x0201f000, 0x001022c0, 0x800409c0,
+	0x04000005, 0x4a034406, 0x00000001, 0x0201f000,
+	0x0010230c, 0x0201f800, 0x0010513b, 0x04020005,
+	0x4a034406, 0x00000016, 0x0201f000, 0x0010230c,
+	0x836c0580, 0x00000003, 0x04000005, 0x4a034406,
+	0x00000007, 0x0201f000, 0x0010230c, 0x59a00c06,
+	0x82040500, 0xffffff00, 0x02020000, 0x00102310,
+	0x82041580, 0x000000ff, 0x04020007, 0x59a80010,
+	0x82000500, 0x000000ff, 0x82001540, 0x0000ff00,
+	0x0401f011, 0x82040400, 0x0010210e, 0x50000000,
+	0x80000110, 0x82000580, 0x00000080, 0x02000000,
+	0x00102310, 0x59a80010, 0x82000500, 0x000000ff,
+	0x80041580, 0x02000000, 0x00102310, 0x840409c0,
+	0x80041540, 0x0201f800, 0x0002075a, 0x04020005,
+	0x4a034406, 0x00000003, 0x0201f000, 0x0010230c,
+	0x48ee6021, 0x480a621c, 0x4a02641c, 0x0000bc09,
+	0x4a026406, 0x00000001, 0x0201f800, 0x00103a00,
+	0x04020007, 0x0201f800, 0x0002077d, 0x4a034406,
+	0x00000002, 0x0201f000, 0x0010230c, 0x497a5a04,
+	0x497a5805, 0x4a025c04, 0x00008000, 0x4a01d809,
+	0x001027f9, 0x492e6008, 0x42027000, 0x00000032,
+	0x0201f000, 0x000207a1, 0x800409c0, 0x04000005,
+	0x4a034406, 0x00000001, 0x0201f000, 0x0010230c,
+	0x0201f800, 0x0010513b, 0x04020005, 0x4a034406,
+	0x00000016, 0x0201f000, 0x0010230c, 0x836c0580,
+	0x00000003, 0x04000005, 0x4a034406, 0x00000007,
+	0x0201f000, 0x0010230c, 0x59a00c06, 0x82040500,
+	0xffffff00, 0x02020000, 0x00102310, 0x82041580,
+	0x000000ff, 0x04020007, 0x59a80010, 0x82000500,
+	0x000000ff, 0x82001540, 0x0000ff00, 0x0401f011,
+	0x82040400, 0x0010210e, 0x50000000, 0x80000110,
+	0x82000580, 0x00000080, 0x02000000, 0x00102310,
+	0x59a80010, 0x82000500, 0x000000ff, 0x80041580,
+	0x02000000, 0x00102310, 0x840409c0, 0x80041540,
+	0x0201f800, 0x0002075a, 0x04020005, 0x4a034406,
+	0x00000003, 0x0201f000, 0x0010230c, 0x48ee6021,
+	0x480a621c, 0x4a02641c, 0x0000bc05, 0x4a026406,
+	0x00000001, 0x0201f800, 0x00103a00, 0x04020007,
+	0x0201f800, 0x0002077d, 0x4a034406, 0x00000002,
+	0x0201f000, 0x0010230c, 0x497a5a04, 0x497a5805,
+	0x4a025c04, 0x00008000, 0x4a01d809, 0x001027f9,
+	0x492e6008, 0x42027000, 0x00000032, 0x0201f000,
+	0x000207a1, 0x592c0005, 0x82000580, 0x01000000,
+	0x02020000, 0x001022c0, 0x4a034406, 0x00000004,
+	0x0201f000, 0x0010230c, 0x497b4406, 0x497b4207,
+	0x0201f800, 0x00103b25, 0x04000008, 0x59a80066,
+	0x59a8086a, 0x80040480, 0x59a80867, 0x48074406,
+	0x80041480, 0x480b4207, 0x49674407, 0x59a8000e,
+	0x48034209, 0x495f4409, 0x59a80020, 0x4803420b,
+	0x0201f000, 0x001022c0, 0x800409c0, 0x04000005,
+	0x4a034406, 0x00000001, 0x0201f000, 0x0010230c,
+	0x59a00406, 0x8c000500, 0x0402000f, 0x59a80069,
+	0x81640480, 0x04001008, 0x59a8000b, 0x81500580,
+	0x04000009, 0x59a8006a, 0x59a81066, 0x80080580,
+	0x04000005, 0x4a034406, 0x00000018, 0x0201f000,
+	0x0010230c, 0x82000540, 0x00000001, 0x0201f800,
+	0x001015fe, 0x0201f800, 0x00103c80, 0x0201f000,
+	0x001022c0, 0x4803c856, 0x800409c0, 0x02020000,
+	0x00102314, 0x59a00406, 0x8c00051e, 0x04000008,
+	0x4803c856, 0x59a0020b, 0x82000480, 0x00000800,
+	0x04001015, 0x0201f000, 0x00102310, 0x4803c856,
+	0x59a0020b, 0x599c0a01, 0x80040480, 0x04021003,
+	0x0201f000, 0x00102310, 0x59a8000e, 0x81640580,
+	0x04000009, 0x4a034406, 0x00000018, 0x0201f000,
+	0x0010230c, 0x4a034406, 0x00000005, 0x0201f000,
+	0x0010230c, 0x59a80026, 0x8c00050a, 0x040007fa,
+	0x59a00406, 0x8c00051e, 0x04000036, 0x0201f800,
+	0x0002075a, 0x040007f4, 0x0201f800, 0x00103a00,
+	0x040007f1, 0x497a5a04, 0x59a00406, 0x4802620a,
+	0x59a00209, 0x4802640a, 0x59a00409, 0x4802620b,
+	0x59a0020d, 0x4802620c, 0x59a0040d, 0x4802640c,
+	0x59a0020e, 0x4802620d, 0x59a0040e, 0x4802640d,
+	0x59a00210, 0x4802620e, 0x59a00410, 0x4802640e,
+	0x59a0020b, 0x82000500, 0x0000fffc, 0x80000104,
+	0x4802640b, 0x0401f9d9, 0x040007d7, 0x48ee6021,
+	0x58ee580d, 0x5930020e, 0x59301c0e, 0x900c19c0,
+	0x800c1d40, 0x5930020c, 0x5930140c, 0x900811c0,
+	0x80081540, 0x592c0a05, 0x832c0400, 0x00000006,
+	0x0201f800, 0x00103a25, 0x4a01d809, 0x001029e5,
+	0x4a034000, 0x00000001, 0x49334001, 0x1c01f000,
+	0x0201f800, 0x00106c55, 0x0201f800, 0x00100ae0,
+	0x0401f86d, 0x497b5057, 0x4201d000, 0x00002710,
+	0x0201f800, 0x001060c6, 0x59c40880, 0x4c040000,
+	0x59c408a3, 0x4c040000, 0x497b4002, 0x0401f876,
+	0x0401f893, 0x4a03a005, 0x10000000, 0x0401f8b4,
+	0x0401f901, 0x04000048, 0x59c80001, 0x800001c0,
+	0x040007fc, 0x59c80018, 0x82000500, 0xf0000000,
+	0x59c00808, 0x82040d00, 0x0fffffff, 0x80040540,
+	0x48038008, 0x0201f800, 0x00100ec1, 0x59c00006,
+	0x4a038006, 0x10000000, 0x59c00009, 0x82000d00,
+	0x00e00000, 0x04020024, 0x4a03900d, 0x00000000,
+	0x59c80020, 0x82000500, 0xff000000, 0x82000580,
+	0x32000000, 0x0402001c, 0x4a03900d, 0x00000001,
+	0x59c80020, 0x82000500, 0xff000000, 0x82000580,
+	0xe1000000, 0x04020014, 0x4a03900d, 0x00000000,
+	0x59c80020, 0x82000500, 0x00ffffff, 0x4a03900d,
+	0x00000000, 0x59c80821, 0x82040d00, 0x00ffffff,
+	0x80040580, 0x04020008, 0x59a80010, 0x80040580,
+	0x04020005, 0x59c40005, 0x82000500, 0x000000f0,
+	0x04000006, 0x4803c856, 0x0401f8d7, 0x4a035057,
+	0x00000001, 0x0401f002, 0x0401f8e1, 0x42000000,
+	0x00000064, 0x80000040, 0x02000800, 0x001005d8,
+	0x59c00807, 0x82040d00, 0x0000000c, 0x040007fa,
+	0x0401f003, 0x4a035057, 0x00000001, 0x0401f8da,
+	0x0201f800, 0x00106f36, 0x0401f818, 0x4201d000,
+	0x000186a0, 0x0201f800, 0x001060c6, 0x5c000800,
+	0x480788a3, 0x5c000800, 0x48078880, 0x59a80057,
+	0x800001c0, 0x02000000, 0x001022c0, 0x0201f000,
+	0x00102318, 0x599c0201, 0x48035059, 0x41780800,
+	0x42001000, 0x00003b10, 0x0201f800, 0x001066a0,
+	0x480b505a, 0x1c01f000, 0x0201f800, 0x00106c4b,
+	0x59b800ea, 0x82000500, 0x00000007, 0x82000580,
+	0x00000003, 0x04020003, 0x4a0370e8, 0x00000001,
+	0x1c01f000, 0x42038000, 0x00007700, 0x4a038006,
+	0x30000000, 0x59c00007, 0x8c00050a, 0x040207fe,
+	0x59c00006, 0x59a00209, 0x59a00c09, 0x900409c0,
+	0x80040d40, 0x48078001, 0x59a0020e, 0x59a00c0e,
+	0x900409c0, 0x80040d40, 0x48078000, 0x59a0020b,
+	0x82000500, 0x0000fffc, 0x48038002, 0x48038003,
+	0x48038005, 0x497b9009, 0x59e00003, 0x82000540,
+	0x00008060, 0x4803c003, 0x1c01f000, 0x41780800,
+	0x8007a0ca, 0x83d3a400, 0x00007600, 0x42000800,
+	0x00000040, 0x0201f800, 0x00101345, 0x4a03a00a,
+	0x00000001, 0x4a03a005, 0x20000000, 0x59d00006,
+	0x4a03a005, 0x30000000, 0x59d00006, 0x8c00050a,
+	0x040207fe, 0x59d00005, 0x59a00210, 0x59a00c10,
+	0x900409c0, 0x80040d40, 0x4807a001, 0x59a0020d,
+	0x59a00c0d, 0x900409c0, 0x80040d40, 0x4807a000,
+	0x59a0020b, 0x82000500, 0x0000fffc, 0x4803a003,
+	0x4803a002, 0x4803a008, 0x1c01f000, 0x59a00002,
+	0x4803c857, 0x800001c0, 0x0402004a, 0x59a8005a,
+	0x48038880, 0x59c400a3, 0x82000540, 0x00002008,
+	0x8400053a, 0x480388a3, 0x59c40008, 0x8400054e,
+	0x82000500, 0xffffffe1, 0x48038808, 0x59c80040,
+	0x84000534, 0x48039040, 0x0401f902, 0x04020013,
+	0x59a80010, 0x800000d0, 0x82000540, 0x00000011,
+	0x48039120, 0x59a80010, 0x82000500, 0x00ffffff,
+	0x82000540, 0x32000000, 0x48039121, 0x4a039123,
+	0xe1290008, 0x59a80010, 0x82000500, 0x00ffffff,
+	0x48039122, 0x0401f016, 0x59a80010, 0x82000500,
+	0x000000ff, 0x900009c0, 0x840001c0, 0x80040540,
+	0x82000540, 0x00000000, 0x48039120, 0x59a80010,
+	0x82000500, 0x000000ff, 0x82000540, 0x01000000,
+	0x48039121, 0x4a039123, 0x08210008, 0x59a80010,
+	0x82000500, 0x000000ff, 0x48039122, 0x497b9124,
+	0x59a80c5b, 0x80040800, 0x4807545b, 0x900409c0,
+	0x82040540, 0x0000aaaa, 0x48039125, 0x497b9126,
+	0x497b9127, 0x0401f8cf, 0x04020004, 0x4a039100,
+	0x0000e980, 0x0401f003, 0x4a039100, 0x0000e9a0,
+	0x1c01f000, 0x82000540, 0x00000001, 0x0402500d,
+	0x4203e000, 0x80000000, 0x40e81000, 0x41780800,
+	0x42000000, 0x00000064, 0x0201f800, 0x001066a0,
+	0x59940024, 0x80080400, 0x48032824, 0x80000580,
+	0x1c01f000, 0x4d900000, 0x4dd00000, 0x4da40000,
+	0x4d140000, 0x417a3000, 0x0201f800, 0x001070d8,
+	0x0201f800, 0x00106dc3, 0x5c022800, 0x5c034800,
+	0x5c03a000, 0x5c032000, 0x1c01f000, 0x59c80007,
+	0x8c000500, 0x04000003, 0x4a03900d, 0x00000030,
+	0x1c01f000, 0x4a038805, 0x00020000, 0x42000800,
+	0x0000003c, 0x0201f800, 0x00101345, 0x4a038891,
+	0x0000ffff, 0x59c80035, 0x48039035, 0x4a03900d,
+	0x00000040, 0x42038000, 0x00007700, 0x0201f800,
+	0x00100ec1, 0x42038000, 0x00007720, 0x0201f800,
+	0x00100ec1, 0x4a03a005, 0x20000000, 0x4a03a005,
+	0x30000000, 0x59d00806, 0x8c040d0a, 0x040207fe,
+	0x1c01f000, 0x4d300000, 0x4031d800, 0x58ef400b,
+	0x58ee580d, 0x58ec0002, 0x82000580, 0x00000200,
+	0x5c026000, 0x02000000, 0x00102304, 0x4d300000,
+	0x59a26001, 0x59a00000, 0x4000b000, 0x80000000,
+	0x48034000, 0x592c0001, 0x80000540, 0x0400001e,
+	0x40025800, 0x8058b040, 0x040207fb, 0x58ec1007,
+	0x58ec1808, 0x592c0a05, 0x4d2c0000, 0x58ec000d,
+	0x40025800, 0x592c0204, 0x5c025800, 0x82000580,
+	0x00000103, 0x04000008, 0x832c0400, 0x00000006,
+	0x0201f800, 0x00103a25, 0x4a01d809, 0x001029e5,
+	0x0401f007, 0x832c0400, 0x00000006, 0x0201f800,
+	0x00103a28, 0x4a01d809, 0x001029e5, 0x5c026000,
+	0x1c01f000, 0x58ec000d, 0x40025800, 0x592c0204,
+	0x82000580, 0x00000103, 0x04020006, 0x0201f800,
+	0x0002077d, 0x5c026000, 0x0201f000, 0x001022c0,
+	0x58ec000d, 0x40025800, 0x592c0404, 0x8400055e,
+	0x48025c04, 0x42028800, 0x000007fd, 0x42003000,
+	0x00fffffd, 0x0201f800, 0x001045a6, 0x04000003,
+	0x80000580, 0x0401f004, 0x59a26001, 0x0201f800,
+	0x0010937d, 0x5c026000, 0x02000000, 0x0010230c,
+	0x4d300000, 0x4a01d809, 0x00102a38, 0x0401f7dc,
+	0x592c0005, 0x82000580, 0x01000000, 0x02000000,
+	0x00102318, 0x4d300000, 0x59a26001, 0x5930020b,
+	0x59301c0a, 0x900001c0, 0x800c1d40, 0x5930040d,
+	0x5930120d, 0x900001c0, 0x80081540, 0x592c0a05,
+	0x832c0400, 0x00000006, 0x0201f800, 0x00103a28,
+	0x4a01d809, 0x001029e5, 0x4a034000, 0x00000001,
+	0x5c026000, 0x1c01f000, 0x4933c857, 0x4c300000,
+	0x5930040b, 0x82000c80, 0x0000000e, 0x04001004,
+	0x4a025a05, 0x0000000e, 0x0401f003, 0x48025a05,
+	0x0401f00c, 0x800409c0, 0x0400000a, 0x4c040000,
+	0x0201f800, 0x00103a00, 0x5c000800, 0x04000003,
+	0x40040000, 0x0401f7f0, 0x80000580, 0x0401f003,
+	0x82000540, 0x00000001, 0x5c006000, 0x1c01f000,
+	0x59a00206, 0x82000580, 0x00000044, 0x1c01f000,
+	0x4807c857, 0x800409c0, 0x0400000c, 0x0201f800,
+	0x00101650, 0x04020009, 0x42000000, 0x00000002,
+	0x0201f800, 0x0010188c, 0x42000000, 0x00000002,
+	0x0201f800, 0x00101821, 0x59a00406, 0x82000500,
+	0x00000007, 0x0c01f001, 0x00102a8c, 0x00102aa1,
+	0x00102ab7, 0x00102a8a, 0x00102a8a, 0x00102a8a,
+	0x00102a8a, 0x00102a8a, 0x0201f000, 0x00102310,
+	0x42000800, 0x000000c0, 0x0201f800, 0x0010193f,
+	0x82040540, 0x00000002, 0x42000800, 0x000000c0,
+	0x0201f800, 0x00101944, 0x42000800, 0x00000000,
+	0x0201f800, 0x0010193f, 0x82040540, 0x00000008,
+	0x42000800, 0x00000000, 0x0201f800, 0x00101944,
+	0x0401f00b, 0x42000800, 0x000000c0, 0x0201f800,
+	0x0010193f, 0x82040540, 0x00000001, 0x42000800,
+	0x000000c0, 0x0201f800, 0x00101944, 0x59c80040,
+	0x4c000000, 0x59a80010, 0x4c000000, 0x59c400a3,
+	0x4c000000, 0x59c40008, 0x4c000000, 0x0401f911,
+	0x04000021, 0x0201f800, 0x001005d8, 0x59a80821,
+	0x800409c0, 0x02020000, 0x00102314, 0x0201f800,
+	0x0010513b, 0x04020005, 0x4a034406, 0x00000016,
+	0x0201f000, 0x0010230c, 0x836c0580, 0x00000003,
+	0x02020000, 0x00102314, 0x59c408a4, 0x82040d00,
+	0x0000000f, 0x82040580, 0x00000000, 0x02020000,
+	0x00102314, 0x59c80040, 0x4c000000, 0x59a80010,
+	0x4c000000, 0x59c400a3, 0x4c000000, 0x59c40008,
+	0x4c000000, 0x59c40080, 0x4c000000, 0x59a0020f,
+	0x59a0bc0f, 0x905cb9c0, 0x805cbd40, 0x41784800,
+	0x41785000, 0x41785800, 0x41789000, 0x41789800,
+	0x0401fe21, 0x0201f800, 0x00106c55, 0x0201f800,
+	0x00100ae0, 0x4178c000, 0x497b4002, 0x0401f95c,
+	0x0401f9aa, 0x59a0020c, 0x59a00c0c, 0x80040d40,
+	0x04000002, 0x0401f9fb, 0x0401f9fa, 0x0401fe68,
+	0x8060c1c0, 0x04020014, 0x0401fa98, 0x0401feb2,
+	0x0402000e, 0x0201f800, 0x001018d3, 0x04020008,
+	0x4a034406, 0x00000017, 0x0201f800, 0x0010230c,
+	0x4203e000, 0x50000000, 0x0401f000, 0x42005800,
+	0x0000aaaa, 0x0401f058, 0x59c80001, 0x800001c0,
+	0x040007ee, 0x59c80801, 0x800409c0, 0x04000006,
+	0x0401fa70, 0x40240000, 0x80280540, 0x802c0540,
+	0x0402004d, 0x59a00002, 0x82000580, 0xfeedbeef,
+	0x04000004, 0x42008800, 0x10000000, 0x0401f003,
+	0x42008800, 0x10000004, 0x0401fa19, 0x4a034002,
+	0xfeedbeef, 0x0401fa71, 0x0401fa97, 0x0401fea8,
+	0x59c40005, 0x8c000534, 0x04000004, 0x42005800,
+	0x0000bbbb, 0x0401f038, 0x0401fe83, 0x04020007,
+	0x42005800, 0x0000cccc, 0x485f420f, 0x905cb9c0,
+	0x485f440f, 0x0401f030, 0x59a0040c, 0x800001c0,
+	0x0400000e, 0x59a26000, 0x5930000d, 0x800001c0,
+	0x040207be, 0x59a26001, 0x5930080d, 0x800409c0,
+	0x040207ba, 0x804891c0, 0x040207b8, 0x804c99c0,
+	0x040207b6, 0x0401f87a, 0x805cb840, 0x04000005,
+	0x40240000, 0x80280540, 0x802c0540, 0x0402001a,
+	0x42000000, 0x00030d40, 0x80000040, 0x04020012,
+	0x59c00007, 0x82000500, 0x000501c0, 0x0402000b,
+	0x0201f800, 0x001018d3, 0x04020008, 0x4a034406,
+	0x00000017, 0x0201f800, 0x0010230c, 0x4203e000,
+	0x50000000, 0x0401f000, 0x42005800, 0x0000dddd,
+	0x0401f005, 0x59c00807, 0x82040d00, 0x0000000c,
+	0x040007ea, 0x0401fe5c, 0x59a0040c, 0x800001c0,
+	0x04000002, 0x0401f856, 0x0401fe6b, 0x40240000,
+	0x80280540, 0x802c0540, 0x04020003, 0x805cb9c0,
+	0x04020781, 0x0201f800, 0x00106f36, 0x0401fda3,
+	0x4201d000, 0x000186a0, 0x0201f800, 0x001060c6,
+	0x5c000800, 0x48078880, 0x5c000800, 0x48078808,
+	0x5c000800, 0x480788a3, 0x5c000800, 0x48075010,
+	0x5c000800, 0x48079040, 0x0201f800, 0x00100969,
+	0x59a00406, 0x82000500, 0x00000003, 0x82000580,
+	0x00000002, 0x0400002c, 0x42000800, 0x000000c0,
+	0x0201f800, 0x0010193f, 0x82040500, 0xfffffffc,
+	0x42000800, 0x000000c0, 0x0201f800, 0x00101944,
+	0x42000800, 0x00000000, 0x0201f800, 0x0010193f,
+	0x82040500, 0xfffffff7, 0x42000800, 0x00000000,
+	0x0201f800, 0x00101944, 0x42000800, 0x00000000,
+	0x0201f800, 0x0010193f, 0x82040500, 0xfffffffb,
+	0x42000800, 0x00000000, 0x0201f800, 0x00101944,
+	0x4a0388a7, 0x0000f7f7, 0x42006000, 0xbeffffff,
+	0x42006800, 0x80018000, 0x0201f800, 0x0010427d,
+	0x42006000, 0xfffeffff, 0x41786800, 0x0201f800,
+	0x0010427d, 0x402c0000, 0x80280540, 0x80240540,
+	0x02000000, 0x001022c0, 0x48274406, 0x482b4207,
+	0x482f4407, 0x0201f000, 0x0010231c, 0x59a26000,
+	0x813261c0, 0x0400000e, 0x59325808, 0x812e59c0,
+	0x0400000b, 0x0201f800, 0x0002077d, 0x0201f800,
+	0x001007fd, 0x59a26001, 0x59325808, 0x0201f800,
+	0x0002077d, 0x0201f800, 0x001007fd, 0x1c01f000,
+	0x42000800, 0x000000ef, 0x0201f800, 0x001015eb,
+	0x59c400a3, 0x8400055a, 0x8400053a, 0x480388a3,
+	0x0201f800, 0x0010163b, 0x0402000a, 0x42000000,
+	0x00000001, 0x0201f800, 0x0010188c, 0x42000000,
+	0x00000001, 0x0201f800, 0x00101821, 0x0401f013,
+	0x0201f800, 0x00101642, 0x04020008, 0x41780000,
+	0x0201f800, 0x0010188c, 0x41780000, 0x0201f800,
+	0x00101821, 0x0401f009, 0x42000000, 0x00000002,
+	0x0201f800, 0x0010188c, 0x42000000, 0x00000002,
+	0x0201f800, 0x00101821, 0x42000800, 0x00000000,
+	0x0201f800, 0x0010193f, 0x82040540, 0x00000004,
+	0x42000800, 0x00000000, 0x0201f800, 0x00101944,
+	0x4201d000, 0x00000014, 0x0201f800, 0x0010608e,
+	0x59c40008, 0x8400054e, 0x82000500, 0xffffffe1,
+	0x48038808, 0x4a0388a7, 0x0000f7f7, 0x42001000,
+	0x04000001, 0x0201f800, 0x0010193d, 0x42006000,
+	0xbe20bfff, 0x42006800, 0x80018000, 0x0201f800,
+	0x0010427d, 0x42006000, 0xfffeffff, 0x41786800,
+	0x0201f800, 0x0010427d, 0x4200b000, 0x00001388,
+	0x4201d000, 0x00000014, 0x4c580000, 0x0201f800,
+	0x0010608e, 0x0201f800, 0x001018d3, 0x5c00b000,
+	0x04000004, 0x8058b040, 0x040207f6, 0x0401f025,
+	0x59c40005, 0x8c000534, 0x04020007, 0x59c400a4,
+	0x82000500, 0x0000000f, 0x82000580, 0x00000008,
+	0x0402001c, 0x42006000, 0x00020000, 0x0201f800,
+	0x00104282, 0x4201d000, 0x00000064, 0x0201f800,
+	0x0010608e, 0x42006000, 0xfeffffff, 0x42006800,
+	0x02000000, 0x0201f800, 0x0010427d, 0x42006000,
+	0xfdffffff, 0x41786800, 0x0201f800, 0x0010427d,
+	0x4a038805, 0x04000001, 0x59c400a4, 0x82000500,
+	0x0000000f, 0x82000580, 0x00000000, 0x04000003,
+	0x82000540, 0x00000001, 0x1c01f000, 0x4803c856,
+	0x42038000, 0x00007700, 0x0201f800, 0x00100ec1,
+	0x59c00006, 0x59a0040c, 0x800001c0, 0x0400003f,
+	0x59a03c0c, 0x59a00209, 0x59a01c09, 0x900c19c0,
+	0x800c1d40, 0x59a0020e, 0x59a0240e, 0x901021c0,
+	0x80102540, 0x59a0020b, 0x82000500, 0x0000fffc,
+	0x59a0140b, 0x900811c0, 0x80081540, 0x480b8003,
+	0x0201f800, 0x0002075a, 0x02000800, 0x001005d8,
+	0x49334000, 0x0201f800, 0x001007e4, 0x4a025a04,
+	0x00000018, 0x4a025805, 0x00abcdef, 0x492e6008,
+	0x492e600b, 0x481e600d, 0x4a02600c, 0x00000004,
+	0x832c0400, 0x00000011, 0x4802600a, 0x42001000,
+	0x0000000c, 0x821c0d80, 0x00000001, 0x04000004,
+	0x801c3840, 0x0401f963, 0x0401f004, 0x41783800,
+	0x0401f960, 0x0401f011, 0x821c0c80, 0x00000005,
+	0x04001005, 0x40043800, 0x42001000, 0x0000003c,
+	0x0401f006, 0x80001580, 0x82081400, 0x0000000c,
+	0x801c3840, 0x040207fd, 0x832c0400, 0x00000005,
+	0x0401f950, 0x040207f1, 0x497b9009, 0x59e00003,
+	0x82000540, 0x00008060, 0x4803c003, 0x4a038009,
+	0x00e00000, 0x1c01f000, 0x4803c856, 0x41780800,
+	0x8007a0ca, 0x83d3a400, 0x00007600, 0x42000800,
+	0x00000040, 0x0201f800, 0x00101345, 0x4a03a00a,
+	0x00000001, 0x4a03a005, 0x20000000, 0x59d00006,
+	0x4a03a005, 0x30000000, 0x59d00006, 0x8c00050a,
+	0x040207fe, 0x59d00005, 0x59a0020c, 0x800001c0,
+	0x0400003f, 0x59a03a0c, 0x59a00210, 0x59a01c10,
+	0x900c19c0, 0x800c1d40, 0x59a0020d, 0x59a0240d,
+	0x901021c0, 0x80102540, 0x59a0120b, 0x82081500,
+	0x0000fffc, 0x59a0040b, 0x900001c0, 0x80081540,
+	0x480ba003, 0x0201f800, 0x0002075a, 0x02000800,
+	0x001005d8, 0x49334001, 0x0201f800, 0x001007e4,
+	0x4a025a04, 0x00000018, 0x4a025805, 0x00abcdef,
+	0x492e6008, 0x492e600b, 0x481e600d, 0x4a02600c,
+	0x00000004, 0x832c0400, 0x00000011, 0x4802600a,
+	0x42001000, 0x0000000c, 0x821c0d80, 0x00000001,
+	0x04000004, 0x801c3840, 0x0401f906, 0x0401f004,
+	0x41783800, 0x0401f903, 0x0401f011, 0x821c0c80,
+	0x00000005, 0x04001005, 0x40043800, 0x42001000,
+	0x0000003c, 0x0401f006, 0x80001580, 0x82081400,
+	0x0000000c, 0x801c3840, 0x040207fd, 0x832c0400,
+	0x00000005, 0x0401f8f3, 0x040207f1, 0x1c01f000,
+	0x4803c856, 0x59a0020c, 0x800001c0, 0x04000024,
+	0x824c0580, 0x00000002, 0x04000040, 0x59a26001,
+	0x5930380d, 0x801c39c0, 0x0400003c, 0x801c3840,
+	0x481e600d, 0x5932580b, 0x5930080a, 0x50042000,
+	0x58041801, 0x58041002, 0x82081500, 0xfffffffc,
+	0x5930000c, 0x80000000, 0x82000d80, 0x00000005,
+	0x04020009, 0x497a600c, 0x592e5801, 0x812e59c0,
+	0x0400001a, 0x492e600b, 0x832c0c00, 0x00000005,
+	0x0401f005, 0x4802600c, 0x5930080a, 0x82040c00,
+	0x00000003, 0x4806600a, 0x0401f010, 0x59a0120b,
+	0x82081500, 0x0000fffc, 0x59a0040b, 0x900001c0,
+	0x80081540, 0x480ba003, 0x59a0020d, 0x59a0240d,
+	0x901021c0, 0x80102540, 0x59a00210, 0x59a01c10,
+	0x900c19c0, 0x800c1d40, 0x4201d000, 0x00003a98,
+	0x0201f800, 0x001060c6, 0x480ba002, 0x59a80059,
+	0x4803a008, 0x4813a000, 0x480fa001, 0x4a03a005,
+	0x10000000, 0x02005800, 0x001005d8, 0x804c9800,
+	0x82000540, 0x00000001, 0x1c01f000, 0x4847c857,
+	0x59a0040c, 0x800001c0, 0x04000024, 0x82480580,
+	0x00000002, 0x04000042, 0x59a26000, 0x5930380d,
+	0x801c39c0, 0x0400003e, 0x801c3840, 0x481e600d,
+	0x5932580b, 0x5930080a, 0x50042000, 0x58041801,
+	0x58041002, 0x82081500, 0xfffffffc, 0x5930000c,
+	0x80000000, 0x82000d80, 0x00000005, 0x04020009,
+	0x497a600c, 0x592e5801, 0x812e59c0, 0x0400001d,
+	0x492e600b, 0x832c0c00, 0x00000005, 0x0401f005,
+	0x4802600c, 0x5930080a, 0x82040c00, 0x00000003,
+	0x4806600a, 0x0401f013, 0x82440580, 0x10000000,
+	0x0402001f, 0x59a0020e, 0x59a0240e, 0x901021c0,
+	0x80102540, 0x59a00209, 0x59a01c09, 0x900c19c0,
+	0x800c1d40, 0x59a0020b, 0x82000500, 0x0000fffc,
+	0x59a0140b, 0x900811c0, 0x80081540, 0x480b8003,
+	0x48138000, 0x480f8001, 0x480b8002, 0x59c80018,
+	0x82000500, 0xf0000000, 0x59c02008, 0x82102500,
+	0x0fffffff, 0x80100540, 0x48038008, 0x48478006,
+	0x80489000, 0x8260c540, 0x00000001, 0x1c01f000,
+	0x59c00009, 0x4803c857, 0x82000d00, 0x00e00000,
+	0x0400000d, 0x485f420f, 0x905cb9c0, 0x485f440f,
+	0x8c00052e, 0x04000002, 0x80285000, 0x8c00052c,
+	0x04000002, 0x80244800, 0x8c00052a, 0x04000002,
+	0x802c5800, 0x1c01f000, 0x59a0020c, 0x800001c0,
+	0x04000024, 0x59d00806, 0x4807c857, 0x8c040d3e,
+	0x04000020, 0x4a03a005, 0x20000000, 0x4a03a005,
+	0x30000000, 0x59d00806, 0x8c040d0a, 0x040207fe,
+	0x824c0480, 0x00000003, 0x02021800, 0x001005d8,
+	0x404c0000, 0x0c01f001, 0x00102da1, 0x00102da3,
+	0x00102da9, 0x0201f800, 0x001005d8, 0x80000040,
+	0x40009800, 0x0401ff43, 0x0400000a, 0x0401ff41,
+	0x0401f008, 0x80000040, 0x40009800, 0x59d00806,
+	0x4807c857, 0x8c040d3e, 0x040207e3, 0x0401ff39,
+	0x1c01f000, 0x59a0040c, 0x800001c0, 0x04000024,
+	0x59c00807, 0x4807c857, 0x8c040d3e, 0x04000020,
+	0x59c00807, 0x4a038006, 0x20000000, 0x82480480,
+	0x00000003, 0x02021800, 0x001005d8, 0x40480000,
+	0x0c01f001, 0x00102dc4, 0x00102dc6, 0x00102dce,
+	0x0201f800, 0x001005d8, 0x80000040, 0x40009000,
+	0x42008800, 0x10000004, 0x0401ff65, 0x0400000c,
+	0x0401ff63, 0x0401f00a, 0x80000040, 0x40009000,
+	0x59c00807, 0x4807c857, 0x8c040d3e, 0x040207e5,
+	0x42008800, 0x10000004, 0x0401ff59, 0x1c01f000,
+	0x492fc857, 0x4000a800, 0x4a03b805, 0x20000000,
+	0x59dc0006, 0x4a03b805, 0x30000000, 0x4813b800,
+	0x480fb801, 0x480bb802, 0x4857b803, 0x4a03b805,
+	0x30000002, 0x59dc0006, 0x4a03b805, 0x70000001,
+	0x59dc0006, 0x4a03b805, 0x10000000, 0x59dc0006,
+	0x8c00053e, 0x040007fe, 0x4a03b805, 0x20000000,
+	0x59dc0006, 0x59dc2000, 0x59dc1801, 0x801c39c0,
+	0x0400000a, 0x4d2c0000, 0x0201f800, 0x001007e4,
+	0x5c000800, 0x02000800, 0x001005d8, 0x4a025a04,
+	0x0000000a, 0x492c0801, 0x1c01f000, 0x42006000,
+	0x00102fb2, 0x0201f800, 0x00101345, 0x4a03902c,
+	0x00200000, 0x4200b000, 0x000001f4, 0x59c8002c,
+	0x8c00052c, 0x04000007, 0x8058b040, 0x040207fc,
+	0x42000000, 0x00004003, 0x41781000, 0x0401f196,
+	0x50301000, 0x41784800, 0x4a03902d, 0x00008000,
+	0x4200b000, 0x000001f4, 0x59c8002c, 0x8c000534,
+	0x04000007, 0x8058b040, 0x040207fc, 0x42000000,
+	0x00004003, 0x41781000, 0x0401f187, 0x0401f8f8,
+	0x80244800, 0x40240000, 0x82000580, 0x000003b1,
+	0x040207fb, 0x0401f988, 0x41784800, 0x0401f920,
+	0x80244800, 0x40240000, 0x82000580, 0x000003b1,
+	0x040207fb, 0x80306000, 0x82300580, 0x00102fb4,
+	0x040207e0, 0x59a80863, 0x800409c0, 0x04000007,
+	0x42000000, 0x00004004, 0x42001000, 0x00000002,
+	0x59a81862, 0x0401f16c, 0x42006000, 0x00102fb2,
+	0x4a035064, 0x00000004, 0x50301000, 0x41784800,
+	0x4a03902d, 0x00004000, 0x4200b000, 0x000001f4,
+	0x59c8002c, 0x8c000532, 0x04000007, 0x8058b040,
+	0x040207fc, 0x42000000, 0x00004003, 0x41781000,
+	0x0401f159, 0x0401f8ca, 0x80244800, 0x40240000,
+	0x82000580, 0x00000154, 0x040207fb, 0x0401f95a,
+	0x41784800, 0x0401f8f2, 0x80244800, 0x40240000,
+	0x82000580, 0x00000154, 0x040207fb, 0x80306000,
+	0x82300580, 0x00102fb4, 0x040207e0, 0x59a80863,
+	0x800409c0, 0x04000007, 0x42000000, 0x00004004,
+	0x42001000, 0x00000004, 0x59a81862, 0x0401f13e,
+	0x42006000, 0x00102fb2, 0x497b5064, 0x50301000,
+	0x41784800, 0x4a03902d, 0x00001000, 0x4200b000,
+	0x000001f4, 0x59c8002c, 0x8c00052e, 0x04000007,
+	0x8058b040, 0x040207fc, 0x42000000, 0x00004003,
+	0x41781000, 0x0401f12c, 0x0401f89d, 0x80244800,
+	0x40240000, 0x82000580, 0x00000088, 0x040207fb,
+	0x0401f92d, 0x41784800, 0x0401f8c5, 0x80244800,
+	0x40240000, 0x82000580, 0x00000088, 0x040207fb,
+	0x80306000, 0x82300580, 0x00102fb4, 0x040207e0,
+	0x59a80863, 0x800409c0, 0x04000007, 0x42000000,
+	0x00004004, 0x42001000, 0x00000001, 0x59a81862,
+	0x0401f111, 0x42006000, 0x00102fb2, 0x50301000,
+	0x41784800, 0x4a03902d, 0x00000800, 0x0401f87c,
+	0x80244800, 0x40240000, 0x82000580, 0x00000018,
+	0x040207fb, 0x0401f90c, 0x41784800, 0x0401f8a4,
+	0x80244800, 0x40240000, 0x82000580, 0x00000018,
+	0x040207fb, 0x80306000, 0x82300580, 0x00102fb4,
+	0x040207eb, 0x59a80863, 0x800409c0, 0x04000007,
+	0x42000000, 0x00004004, 0x42001000, 0x00000010,
+	0x59a81862, 0x0401f0f0, 0x42006000, 0x00102fb2,
+	0x50301000, 0x41784800, 0x4a03902d, 0x00000400,
+	0x0401f85b, 0x80244800, 0x40240000, 0x82000580,
+	0x00000088, 0x040207fb, 0x0401f8eb, 0x41784800,
+	0x0401f883, 0x80244800, 0x40240000, 0x82000580,
+	0x00000088, 0x040207fb, 0x80306000, 0x82300580,
+	0x00102fb4, 0x040207eb, 0x59a80863, 0x800409c0,
+	0x04000007, 0x42000000, 0x00004004, 0x42001000,
+	0x00000008, 0x59a81862, 0x0401f0cf, 0x42006000,
+	0x00102fb2, 0x50301000, 0x41784800, 0x4a03902d,
+	0x00002000, 0x4200b000, 0x000001f4, 0x59c8002c,
+	0x8c000530, 0x04000007, 0x8058b040, 0x040207fc,
+	0x42000000, 0x00004003, 0x41781000, 0x0401f0be,
+	0x59c8002c, 0x82000500, 0xffe0ffff, 0x82080d00,
+	0x001f0000, 0x80040540, 0x4803902c, 0x0401f828,
+	0x80244800, 0x40240000, 0x82000580, 0x00000110,
+	0x040207fb, 0x0401f8b8, 0x41784800, 0x0401f850,
+	0x59c80034, 0x82080d00, 0x001f0000, 0x82000500,
+	0x001f0000, 0x80040580, 0x04000006, 0x59a80063,
+	0x80000000, 0x48035063, 0x40240000, 0x48035062,
+	0x80244800, 0x40240000, 0x82000580, 0x00000110,
+	0x040207ef, 0x80306000, 0x82300580, 0x00102fb4,
+	0x040207cd, 0x59a80863, 0x800409c0, 0x04000006,
+	0x42000000, 0x00004004, 0x42001000, 0x00000020,
+	0x59a81862, 0x0201f000, 0x001022c0, 0x59c8002c,
+	0x82000500, 0xffff0000, 0x82080d00, 0x0000ffff,
+	0x80040540, 0x4803902c, 0x40080000, 0x48039028,
+	0x48039029, 0x59a80064, 0x82000580, 0x00000004,
+	0x04000004, 0x40080000, 0x4803902a, 0x4803902b,
+	0x59c8082d, 0x82040d00, 0xfffffc00, 0x40240000,
+	0x80040d40, 0x4807902d, 0x4200b000, 0x000001f4,
+	0x59c8002c, 0x82000500, 0x18000000, 0x04000007,
+	0x8058b040, 0x040207fb, 0x42000000, 0x00004003,
+	0x41781000, 0x0401f06c, 0x4a03902e, 0x00000001,
+	0x4200b000, 0x000001f4, 0x59c8002e, 0x8c000500,
+	0x04000006, 0x8058b040, 0x040207fc, 0x42000000,
+	0x00004003, 0x0401f060, 0x1c01f000, 0x41783800,
+	0x59c8082d, 0x82040d00, 0xfffffc00, 0x40240000,
+	0x80040d40, 0x4807902d, 0x4200b000, 0x000001f4,
+	0x59c8002c, 0x82000500, 0x18000000, 0x04000007,
+	0x8058b040, 0x040207fb, 0x42000000, 0x00004003,
+	0x41781000, 0x0401f04c, 0x59c80030, 0x59c80830,
+	0x80040580, 0x040207fd, 0x40041800, 0x59c80031,
+	0x59c80831, 0x80040580, 0x040207fd, 0x40042000,
+	0x59c80032, 0x59c80832, 0x80040580, 0x040207fd,
+	0x40042800, 0x59c80033, 0x59c80833, 0x80040580,
+	0x040207fd, 0x40043000, 0x400c0000, 0x80080580,
+	0x04000002, 0x801c3800, 0x40100000, 0x80080580,
+	0x04000002, 0x801c3800, 0x59a80064, 0x82000580,
+	0x00000004, 0x04000009, 0x40140000, 0x80080580,
+	0x04000002, 0x801c3800, 0x40180000, 0x80080580,
+	0x04000002, 0x801c3800, 0x59a80064, 0x82000580,
+	0x00000004, 0x0400000d, 0x59c80034, 0x59c80834,
+	0x80040580, 0x040207fd, 0x82040500, 0x0000ffff,
+	0x82080d00, 0x0000ffff, 0x80040580, 0x0400000e,
+	0x801c3800, 0x0401f00c, 0x59c80034, 0x59c80834,
+	0x80040580, 0x040207fd, 0x82040500, 0x000000ff,
+	0x82080d00, 0x000000ff, 0x80040580, 0x04000002,
+	0x801c3800, 0x801c39c0, 0x04000006, 0x59a80063,
+	0x801c0400, 0x48035063, 0x40240000, 0x48035062,
+	0x1c01f000, 0x48034206, 0x48074406, 0x480b4207,
+	0x480f4407, 0x48134208, 0x48174408, 0x0201f000,
+	0x001022c3, 0x42000000, 0x00600000, 0x80000040,
+	0x040207ff, 0x1c01f000, 0x5a5a5a5a, 0xa5a5a5a5,
+	0x59a00c0a, 0x800409c0, 0x02000000, 0x00102310,
+	0x82040480, 0x00000021, 0x02021000, 0x00102310,
+	0x82040480, 0x00000011, 0x04001003, 0x42000800,
+	0x00000010, 0x59a00208, 0x59a01407, 0x900811c0,
+	0x80081540, 0x59a00207, 0x59a01c06, 0x900c19c0,
+	0x800c1d40, 0x0201f800, 0x00103a00, 0x04000006,
+	0x0201f800, 0x00103a25, 0x4a01d809, 0x00102fd5,
+	0x1c01f000, 0x4a034406, 0x00000002, 0x0201f000,
+	0x0010230c, 0x4031d800, 0x58ef400b, 0x58ec0002,
+	0x82000580, 0x00000200, 0x02000000, 0x00102304,
+	0x59a00c0a, 0x82040480, 0x00000011, 0x04001003,
+	0x42000800, 0x00000010, 0x59a0040b, 0x59a0120b,
+	0x900811c0, 0x80081540, 0x59a00209, 0x59a01c08,
+	0x900c19c0, 0x800c1d40, 0x58ec0003, 0x0201f800,
+	0x00103a28, 0x4a01d809, 0x00102ff0, 0x1c01f000,
+	0x4031d800, 0x58ef400b, 0x58ec0002, 0x82000580,
+	0x00000200, 0x02000000, 0x00102304, 0x59a00c0a,
+	0x82040480, 0x00000011, 0x02001000, 0x001022c0,
+	0x82040c80, 0x00000010, 0x59a00208, 0x59a01407,
+	0x900811c0, 0x80081540, 0x59a00207, 0x59a01c06,
+	0x900c19c0, 0x800c1d40, 0x82081400, 0x00000040,
+	0x58ec0003, 0x0201f800, 0x00103a25, 0x4a01d809,
+	0x0010300e, 0x1c01f000, 0x4031d800, 0x58ef400b,
+	0x58ec0002, 0x82000580, 0x00000200, 0x02000000,
+	0x00102304, 0x59a0040a, 0x82000c80, 0x00000010,
+	0x59a0040b, 0x59a0120b, 0x900811c0, 0x80081540,
+	0x59a00209, 0x59a01c08, 0x900c19c0, 0x800c1d40,
+	0x82081400, 0x00000040, 0x58ec0003, 0x0201f800,
+	0x00103a28, 0x4a01d809, 0x001022b9, 0x1c01f000,
+	0x48efc857, 0x59a00207, 0x59a01407, 0x900001c0,
+	0x80081540, 0x59a00209, 0x59a01c09, 0x900001c0,
+	0x800c1d40, 0x59a00406, 0x48034000, 0x480b4001,
+	0x480f4002, 0x0201f800, 0x00103a00, 0x04020005,
+	0x4a034406, 0x00000002, 0x0201f000, 0x0010230c,
+	0x42000800, 0x00000010, 0x0201f800, 0x00103a25,
+	0x4a01d809, 0x00103043, 0x1c01f000, 0x4031d800,
+	0x58ef400b, 0x58ee580d, 0x58ec0002, 0x82000580,
+	0x00000200, 0x02000000, 0x00102304, 0x48efc857,
+	0x49a3c857, 0x492fc857, 0x592c0a04, 0x80040910,
+	0x04020005, 0x4a034406, 0x00000019, 0x0201f000,
+	0x0010230c, 0x4805d80c, 0x0401f00a, 0x4031d800,
+	0x58ef400b, 0x58ec0002, 0x82000580, 0x00000200,
+	0x02000000, 0x00102304, 0x48efc857, 0x49a3c857,
+	0x48efc857, 0x49a3c857, 0x58ec000c, 0x80000040,
+	0x04000012, 0x4801d80c, 0x0201f800, 0x00103a00,
+	0x04020005, 0x4a034406, 0x00000002, 0x0201f000,
+	0x0010230c, 0x42000800, 0x00000010, 0x58ec1007,
+	0x58ec1808, 0x0201f800, 0x00103a25, 0x4a01d809,
+	0x00103057, 0x1c01f000, 0x58ee580d, 0x48efc857,
+	0x49a3c857, 0x492fc857, 0x492f3006, 0x592c0404,
+	0x8400055e, 0x48025c04, 0x4a01d809, 0x00103081,
+	0x1c01f000, 0x58ee580d, 0x48efc857, 0x49a3c857,
+	0x492fc857, 0x592c0404, 0x8400051e, 0x48025c04,
+	0x59a00000, 0x59a01001, 0x59a01802, 0x80081400,
+	0x820c1c40, 0x00000000, 0x832c0400, 0x00000004,
+	0x42000800, 0x00000010, 0x0201f000, 0x00103a28,
+	0x800409c0, 0x04000005, 0x4a034406, 0x00000001,
+	0x0201f000, 0x0010230c, 0x836c0580, 0x00000003,
+	0x04000005, 0x4a034406, 0x00000007, 0x0201f000,
+	0x0010230c, 0x59a0320b, 0x82183500, 0x000000ff,
+	0x59a28c06, 0x0201f800, 0x00020245, 0x02020000,
+	0x00102310, 0x83440580, 0x000007fd, 0x04000008,
+	0x0201f800, 0x001049e7, 0x04000005, 0x4a034406,
+	0x00000009, 0x0201f000, 0x0010230c, 0x0201f800,
+	0x00103a00, 0x04020005, 0x4a034406, 0x00000002,
+	0x0201f000, 0x0010230c, 0x801831c0, 0x0400000a,
+	0x412c0800, 0x0201f800, 0x00103a00, 0x04020005,
+	0x4a034406, 0x00000002, 0x0201f000, 0x0010230c,
+	0x40065800, 0x4a025c04, 0x00008000, 0x497a5a04,
+	0x0201f800, 0x00109100, 0x04020005, 0x4a034406,
+	0x00000003, 0x0201f000, 0x0010230c, 0x4a01d809,
+	0x001030d2, 0x1c01f000, 0x592c0005, 0x82000580,
+	0x01000000, 0x04020005, 0x4a034406, 0x00000004,
+	0x0201f000, 0x0010230c, 0x592c0406, 0x82002d00,
+	0x0000ff00, 0x82000500, 0x000000ff, 0x80000904,
+	0x80040800, 0x82040480, 0x00000006, 0x04001003,
+	0x42000800, 0x00000005, 0x832ca400, 0x00000006,
+	0x4050a800, 0x4004b000, 0x0201f800, 0x0010ab28,
+	0x59a00407, 0x59a01207, 0x900811c0, 0x80081540,
+	0x59a00409, 0x59a01a09, 0x900c19c0, 0x800c1d40,
+	0x832c0400, 0x00000006, 0x4c140000, 0x0201f800,
+	0x00103a28, 0x5c002800, 0x801429c0, 0x04000003,
+	0x4a01d809, 0x001030ff, 0x1c01f000, 0x4031d800,
+	0x58ef400b, 0x58ee580d, 0x58ec0002, 0x82000580,
+	0x00000200, 0x02000000, 0x00102304, 0x812e59c0,
+	0x02000800, 0x001005d8, 0x592c0006, 0x82000500,
+	0xff000000, 0x80000904, 0x800409c0, 0x02000000,
+	0x00102304, 0x82040480, 0x0000000e, 0x04001003,
+	0x42000800, 0x0000000d, 0x592e5801, 0x812e59c0,
+	0x02000800, 0x001005d8, 0x832ca400, 0x00000005,
+	0x4050a800, 0x4004b000, 0x0201f800, 0x0010ab28,
+	0x58ec1007, 0x58ec1808, 0x832c0400, 0x00000005,
+	0x0201f000, 0x00103a28, 0x0201f800, 0x00103a00,
+	0x04020005, 0x4a034406, 0x00000002, 0x0201f000,
+	0x0010230c, 0x59a00c06, 0x82040500, 0x0000ff00,
+	0x840001c0, 0x82001480, 0x00000007, 0x02021000,
+	0x00102310, 0x0c01f001, 0x0010313d, 0x00103144,
+	0x0010314b, 0x0010314b, 0x0010314b, 0x0010314d,
+	0x00103152, 0x42000800, 0x0000000d, 0x42003800,
+	0x00103166, 0x4a034000, 0x0010b4eb, 0x0401f013,
+	0x42000800, 0x0000000d, 0x42003800, 0x00103166,
+	0x4a034000, 0x0010b4f8, 0x0401f00c, 0x0201f000,
+	0x00102310, 0x42000800, 0x00000008, 0x42003800,
+	0x00103179, 0x0401f005, 0x42000800, 0x00000004,
+	0x42003800, 0x001031c3, 0x59a00207, 0x59a01407,
+	0x900001c0, 0x80081540, 0x59a00209, 0x59a01c09,
+	0x900001c0, 0x800c1d40, 0x832c0400, 0x00000005,
+	0x4c1c0000, 0x0201f800, 0x00103a25, 0x5c003800,
+	0x481dd809, 0x1c01f000, 0x4031d800, 0x58ef400b,
+	0x58ee580d, 0x58ec0002, 0x82000580, 0x00000200,
+	0x02000000, 0x00102304, 0x4a03501f, 0x00000001,
+	0x4200b000, 0x0000000d, 0x59a0a800, 0x832ca400,
+	0x00000005, 0x0201f800, 0x0010ab17, 0x0201f000,
+	0x001022c0, 0x4031d800, 0x58ef400b, 0x58ee580d,
+	0x58ec0002, 0x82000580, 0x00000200, 0x02000000,
+	0x00102304, 0x832ca400, 0x00000005, 0x50500000,
+	0x82001500, 0x000c0016, 0x02020000, 0x00102310,
+	0x82500c00, 0x00000003, 0x50040000, 0x82001500,
+	0x00000001, 0x02020000, 0x00102310, 0x50500000,
+	0x82001500, 0x00000028, 0x0400001d, 0x82081580,
+	0x00000028, 0x02020000, 0x00102310, 0x80500800,
+	0x50040000, 0x82001500, 0x00000013, 0x82081580,
+	0x00000013, 0x02020000, 0x00102310, 0x80040800,
+	0x50040000, 0x82001500, 0x00010000, 0x82081580,
+	0x00010000, 0x02020000, 0x00102310, 0x836c0580,
+	0x00000000, 0x04000012, 0x599c0019, 0x8c00050e,
+	0x0402000f, 0x0201f000, 0x00102310, 0x80500800,
+	0x50040000, 0x82001500, 0x00000013, 0x02020000,
+	0x00102310, 0x80040800, 0x50040000, 0x82001500,
+	0x00010000, 0x02020000, 0x00102310, 0x4200b000,
+	0x00000008, 0x4200a800, 0x0010b4e3, 0x0201f800,
+	0x0010ab17, 0x0201f000, 0x001022c0, 0x4031d800,
+	0x58ef400b, 0x58ee580d, 0x58ec0002, 0x82000580,
+	0x00000200, 0x02000000, 0x00102304, 0x4200b000,
+	0x00000004, 0x4200a800, 0x0010b8fa, 0x832ca400,
+	0x00000005, 0x0201f800, 0x0010ab17, 0x59a80005,
+	0x84000550, 0x48035005, 0x0201f000, 0x001022c0,
+	0x0201f800, 0x00103a00, 0x04020005, 0x4a034406,
+	0x00000002, 0x0201f000, 0x0010230c, 0x59a00c06,
+	0x82040500, 0x0000ff00, 0x840001c0, 0x82001480,
+	0x00000006, 0x02021000, 0x00102310, 0x0c01f001,
+	0x001031ee, 0x001031f3, 0x001031f8, 0x001031f8,
+	0x001031f8, 0x001031fa, 0x42000800, 0x0000000d,
+	0x4200a000, 0x0010b4eb, 0x0401f00c, 0x42000800,
+	0x0000000d, 0x4200a000, 0x0010b4f8, 0x0401f007,
+	0x0201f000, 0x00102310, 0x42000800, 0x00000008,
+	0x4200a000, 0x0010b4e3, 0x4004b000, 0x832cac00,
+	0x00000005, 0x0201f800, 0x0010ab17, 0x59a00207,
+	0x59a01407, 0x900001c0, 0x80081540, 0x59a00209,
+	0x59a01c09, 0x900001c0, 0x800c1d40, 0x832c0400,
+	0x00000005, 0x0201f000, 0x00103a28, 0x836c0580,
+	0x00000000, 0x04020005, 0x4a034406, 0x00000007,
+	0x0201f000, 0x0010230c, 0x59a00406, 0x800001c0,
+	0x0400001a, 0x59a80005, 0x8c000514, 0x04000005,
+	0x42000000, 0x00000001, 0x40000800, 0x0401f003,
+	0x59a00207, 0x59a80853, 0x48035053, 0x0201f800,
+	0x0010163b, 0x04000022, 0x0201f800, 0x00101642,
+	0x0400001f, 0x0201f800, 0x00101649, 0x0400001c,
+	0x0201f800, 0x00101650, 0x04000019, 0x48075053,
+	0x0201f000, 0x00102310, 0x59c40801, 0x82040d00,
+	0x00018000, 0x82040580, 0x00000000, 0x04020004,
+	0x4a034406, 0x00000000, 0x0401f00d, 0x82040580,
+	0x00008000, 0x04020004, 0x4a034406, 0x00000001,
+	0x0401f007, 0x82040580, 0x00010000, 0x02020800,
+	0x001005d8, 0x4a034406, 0x00000003, 0x59a00406,
+	0x82000580, 0x00000002, 0x0402001f, 0x59c40006,
+	0x84000500, 0x48038806, 0x0201f800, 0x00106ede,
+	0x497b8880, 0x0201f800, 0x0010a9c0, 0x0201f800,
+	0x0010a9ce, 0x42000000, 0x0010b8ca, 0x0201f800,
+	0x0010aa47, 0x82000540, 0x00000001, 0x0201f800,
+	0x0010518c, 0x4a038808, 0x00000000, 0x4202d800,
+	0x00000004, 0x42001000, 0x00000001, 0x0201f800,
+	0x0010193d, 0x4a035049, 0x00000001, 0x0201f800,
+	0x001006d4, 0x0201f000, 0x001022c0, 0x800409c0,
+	0x04000005, 0x4a034406, 0x00000001, 0x0201f000,
+	0x0010230c, 0x836c0580, 0x00000003, 0x04000005,
+	0x4a034406, 0x00000007, 0x0201f000, 0x0010230c,
+	0x59a28c06, 0x59a0320b, 0x82183500, 0x000000ff,
+	0x0201f800, 0x00020245, 0x02020000, 0x00102310,
+	0x83440580, 0x000007fd, 0x04000008, 0x0201f800,
+	0x001049e7, 0x04000005, 0x42000800, 0x00000009,
+	0x0201f000, 0x0010230c, 0x0201f800, 0x00103a00,
+	0x04020005, 0x4a034406, 0x00000002, 0x0201f000,
+	0x0010230c, 0x497a5a04, 0x4a025c04, 0x00008000,
+	0x0201f800, 0x00109115, 0x04020005, 0x4a034406,
+	0x00000003, 0x0201f000, 0x0010230c, 0x4a01d809,
+	0x0010329e, 0x1c01f000, 0x592c0005, 0x82000d00,
+	0x0000ffff, 0x82000500, 0xffff0000, 0x82000580,
+	0x01000000, 0x04020005, 0x4a034406, 0x00000004,
+	0x0201f000, 0x0010230c, 0x80040904, 0x832ca400,
+	0x00000005, 0x4050a800, 0x4004b000, 0x0201f800,
+	0x0010ab28, 0x59a00207, 0x59a01407, 0x900001c0,
+	0x80081540, 0x59a00209, 0x59a01c09, 0x900001c0,
+	0x800c1d40, 0x832c0400, 0x00000005, 0x0201f000,
+	0x00103a28, 0x496fc857, 0x836c0580, 0x00000000,
+	0x04000005, 0x4a034406, 0x0000001a, 0x0201f000,
+	0x0010230c, 0x0201f800, 0x0010513b, 0x02020800,
+	0x00104142, 0x42000800, 0x00000020, 0x59a00407,
+	0x59a01207, 0x900811c0, 0x80081540, 0x59a00409,
+	0x59a01a09, 0x900c19c0, 0x800c1d40, 0x419c0000,
+	0x49a3c857, 0x0201f800, 0x00103a25, 0x4a01d809,
+	0x001032da, 0x1c01f000, 0x4833c857, 0x4031d800,
+	0x58ef400b, 0x58ec0002, 0x82000580, 0x00000200,
+	0x02000000, 0x00102304, 0x599c0200, 0x800001c0,
+	0x02000000, 0x00102310, 0x59a80005, 0x8c000512,
+	0x04000004, 0x599c0019, 0x8400050c, 0x48033819,
+	0x0201f800, 0x001097d7, 0x59a80005, 0x8c000514,
+	0x04000004, 0x599c0017, 0x84000508, 0x48033817,
+	0x0201f800, 0x00103b25, 0x04020004, 0x8c00050a,
+	0x02020000, 0x00102310, 0x4803c857, 0x8c000504,
+	0x04020004, 0x59c408a3, 0x84040d7a, 0x480788a3,
+	0x8c000502, 0x04020004, 0x59c408a3, 0x84040d08,
+	0x480788a3, 0x599c0c02, 0x8c000500, 0x04020004,
+	0x8c000516, 0x04000012, 0x0401f001, 0x82041480,
+	0x0000007f, 0x02021000, 0x00102310, 0x82041400,
+	0x0010210e, 0x50081000, 0x82081500, 0x000000ff,
+	0x8c000500, 0x04020006, 0x480b5010, 0x42000800,
+	0x00000003, 0x0201f800, 0x00106c78, 0x599c0019,
+	0x8c00050e, 0x0402000b, 0x59a80806, 0x8c040d14,
+	0x04000008, 0x42000800, 0x0010b4e3, 0x50040800,
+	0x82040d00, 0x00000028, 0x02020000, 0x00102310,
+	0x82000500, 0x00000030, 0x04000003, 0x80000108,
+	0x0401f003, 0x42000000, 0x00000002, 0x48039040,
+	0x42000800, 0x00000002, 0x82000400, 0x00103415,
+	0x50001000, 0x0201f800, 0x00106c78, 0x599c0201,
+	0x82000c80, 0x00000100, 0x02001000, 0x00102310,
+	0x82000c80, 0x00000841, 0x02021000, 0x00102310,
+	0x82000500, 0x00000007, 0x02020000, 0x00102310,
+	0x599c0401, 0x80000540, 0x02000000, 0x00102310,
+	0x599c0409, 0x599c0c07, 0x80040c80, 0x02021000,
+	0x00102310, 0x80000040, 0x02000000, 0x00102310,
+	0x599c0209, 0x599c0a07, 0x80040c80, 0x02021000,
+	0x00102310, 0x80000040, 0x02000000, 0x00102310,
+	0x0201f800, 0x001053cd, 0x0201f800, 0x00104cb6,
+	0x599c0201, 0x48035004, 0x0201f800, 0x001012ee,
+	0x599c020a, 0x800001c0, 0x04000003, 0x4803504d,
+	0x0401f003, 0x4a03504d, 0x000000c8, 0x0201f800,
+	0x00103b25, 0x04000004, 0x0201f800, 0x001060df,
+	0x417a5000, 0x836c0580, 0x00000000, 0x04020098,
+	0x599c0003, 0x599c0804, 0x9c0001c0, 0x9c0409c0,
+	0x48035002, 0x48075003, 0x599c1017, 0x8c08151c,
+	0x04000006, 0x599c0005, 0x599c0806, 0x9c0001c0,
+	0x9c0409c0, 0x0401f003, 0x82000500, 0xf0ffffff,
+	0x48035000, 0x48075001, 0x42001000, 0x0010b4eb,
+	0x48001000, 0x48041001, 0x42001000, 0x0010b4f8,
+	0x48001000, 0x48041001, 0x59a80005, 0x8c000514,
+	0x04020015, 0x599c1019, 0x82081500, 0x0000e000,
+	0x82080580, 0x00000000, 0x0402000c, 0x4a035053,
+	0x00000000, 0x42000000, 0x00000001, 0x0201f800,
+	0x0010188c, 0x42000000, 0x00000001, 0x0201f800,
+	0x00101821, 0x0401f02b, 0x82080580, 0x00002000,
+	0x0402000a, 0x4a035053, 0x00000001, 0x41780000,
+	0x0201f800, 0x0010188c, 0x41780000, 0x0201f800,
+	0x00101821, 0x0401f01f, 0x82080580, 0x00004000,
+	0x04020006, 0x4a035053, 0x00000002, 0x4a035049,
+	0x00000001, 0x0401f017, 0x82080580, 0x00006000,
+	0x02020000, 0x00102310, 0x59a80858, 0x82040d80,
+	0x01391077, 0x04020005, 0x59e00813, 0x8c040d00,
+	0x02020000, 0x00102310, 0x4a035053, 0x00000003,
+	0x42000000, 0x00000002, 0x0201f800, 0x0010188c,
+	0x42000000, 0x00000002, 0x0201f800, 0x00101821,
+	0x599c0019, 0x8c000520, 0x0400000d, 0x42000000,
+	0x00000004, 0x42000800, 0x00000040, 0x0201f800,
+	0x00101944, 0x42000000, 0x00000010, 0x42000800,
+	0x000000c0, 0x0201f800, 0x00101944, 0x4a035032,
+	0x0000aaaa, 0x599c1018, 0x82081500, 0x00000030,
+	0x59a8006c, 0x80000540, 0x0400000c, 0x82080580,
+	0x00000000, 0x02000000, 0x00102310, 0x599c1018,
+	0x82081500, 0xffffffcf, 0x82081540, 0x00000010,
+	0x480b3818, 0x0401f010, 0x82080d80, 0x00000000,
+	0x04000007, 0x82080d80, 0x00000010, 0x0400000a,
+	0x82080d80, 0x00000020, 0x04020002, 0x48075032,
+	0x0201f800, 0x00103aba, 0x04000008, 0x0201f800,
+	0x001015fe, 0x0201f800, 0x0010162a, 0x59a8002a,
+	0x80040540, 0x4803502a, 0x49f3c857, 0x42001000,
+	0x00105065, 0x0201f800, 0x00105f90, 0x42001000,
+	0x00105058, 0x0201f800, 0x00106084, 0x4a038805,
+	0xffffffff, 0x4a03c014, 0x00400040, 0x4a03c013,
+	0x00400000, 0x0201f800, 0x001048c7, 0x59a0001d,
+	0x84000540, 0x4803401d, 0x49f3c857, 0x0201f000,
+	0x001022c0, 0x00000018, 0x0000000c, 0x00000018,
+	0x00000020, 0x836c0580, 0x00000000, 0x04020005,
+	0x42000800, 0x00000007, 0x0201f000, 0x0010230c,
+	0x42000800, 0x00000020, 0x59a00407, 0x59a01207,
+	0x900811c0, 0x80081540, 0x59a00409, 0x59a01a09,
+	0x900c19c0, 0x800c1d40, 0x419c0000, 0x0201f000,
+	0x00103a28, 0x800409c0, 0x04000005, 0x4a034406,
+	0x00000001, 0x0201f000, 0x0010230c, 0x0201f800,
+	0x0010513b, 0x04020005, 0x4a034406, 0x00000016,
+	0x0201f000, 0x0010230c, 0x59a80013, 0x8c000500,
+	0x04000011, 0x4a034406, 0x00000000, 0x42000800,
+	0x00000020, 0x59a00407, 0x59a01207, 0x900811c0,
+	0x80081540, 0x59a00409, 0x59a01a09, 0x900c19c0,
+	0x800c1d40, 0x42000000, 0x0010be21, 0x0201f000,
+	0x00103a28, 0x4a034406, 0x00000001, 0x4200b000,
+	0x00000020, 0x4200a800, 0x0010be21, 0x4200a000,
+	0xffffffff, 0x4450a800, 0x8054a800, 0x8058b040,
+	0x040207fd, 0x4d440000, 0x4d340000, 0x42028800,
+	0xffffffff, 0x42002000, 0xffffffff, 0x42003000,
+	0x00000001, 0x42003800, 0x00000001, 0x42001800,
+	0x0010be21, 0x59a81010, 0x82081500, 0x000000ff,
+	0x40180000, 0x0c01f001, 0x0010346e, 0x00103471,
+	0x00103475, 0x00103479, 0x82102500, 0xffffff00,
+	0x0401f014, 0x82102500, 0xffff00ff, 0x840811c0,
+	0x0401f010, 0x82102500, 0xff00ffff, 0x900811c0,
+	0x0401f00c, 0x82102500, 0x00ffffff, 0x9c0801c0,
+	0x80102540, 0x44101800, 0x42003000, 0xffffffff,
+	0x42002000, 0xffffffff, 0x800c1800, 0x0401f003,
+	0x40080000, 0x80102540, 0x81468800, 0x83442c80,
+	0x0000007f, 0x04021014, 0x4c080000, 0x4c0c0000,
+	0x4c180000, 0x4c1c0000, 0x0201f800, 0x00020245,
+	0x5c003800, 0x5c003000, 0x5c001800, 0x5c001000,
+	0x040207f2, 0x0201f800, 0x001049f3, 0x040207ef,
+	0x80183000, 0x801c3800, 0x59341202, 0x40180000,
+	0x0c01f7ce, 0x82100580, 0xffffffff, 0x04000002,
+	0x44101800, 0x42001800, 0x0010be21, 0x500c0000,
+	0x82000500, 0xffffff00, 0x801c0540, 0x44001800,
+	0x5c026800, 0x5c028800, 0x42000800, 0x00000020,
+	0x59a00407, 0x59a01207, 0x900811c0, 0x80081540,
+	0x59a00409, 0x59a01a09, 0x900c19c0, 0x800c1d40,
+	0x42000000, 0x0010be21, 0x0201f000, 0x00103a28,
+	0x59a28c06, 0x59a0020b, 0x8c000500, 0x0400000e,
+	0x59a01208, 0x59a00408, 0x82000500, 0x000000ff,
+	0x900001c0, 0x80081540, 0x41784000, 0x0201f800,
+	0x00104919, 0x04000008, 0x48034406, 0x0201f000,
+	0x00102310, 0x0201f800, 0x00020245, 0x02020000,
+	0x00102310, 0x0201f800, 0x00103a00, 0x04020005,
+	0x4a034406, 0x00000002, 0x0201f000, 0x0010230c,
+	0x59a0020b, 0x8c000500, 0x04000005, 0x0201f800,
+	0x001049f3, 0x02020000, 0x00103ac4, 0x59a0020b,
+	0x8c000502, 0x04000019, 0x83440480, 0x000007f0,
+	0x04021016, 0x0201f800, 0x001049fc, 0x04020013,
+	0x497a5a04, 0x4a025c04, 0x00008000, 0x0201f800,
+	0x001090e6, 0x04020005, 0x4a034406, 0x00000003,
+	0x0201f000, 0x0010230c, 0x4a01d809, 0x001034f1,
+	0x1c01f000, 0x59a28c06, 0x0201f800, 0x00020245,
+	0x02020000, 0x00102310, 0x4200b000, 0x0000000a,
+	0x4134a000, 0x832e5c00, 0x00000002, 0x412ca800,
+	0x0201f800, 0x0010ab17, 0x832cac00, 0x00000006,
+	0x4054a000, 0x4200b000, 0x00000004, 0x0201f800,
+	0x0010ab28, 0x592c0802, 0x82040500, 0x00ff00ff,
+	0x900001c0, 0x82041500, 0xff00ff00, 0x80080540,
+	0x48025802, 0x592c0801, 0x82040500, 0x00ff00ff,
+	0x900001c0, 0x82041500, 0xff00ff00, 0x80080540,
+	0x48025801, 0x42000800, 0x0000000a, 0x59a00407,
+	0x59a01207, 0x900811c0, 0x80081540, 0x59a00409,
+	0x59a01a09, 0x900c19c0, 0x800c1d40, 0x412c0000,
+	0x0201f000, 0x00103a28, 0x496fc857, 0x496f4406,
+	0x0201f000, 0x001022c0, 0x59a28c06, 0x0201f800,
+	0x00020245, 0x02020000, 0x00102310, 0x836c0580,
+	0x00000003, 0x04000005, 0x4a034406, 0x00000007,
+	0x0201f000, 0x0010230c, 0x83340c00, 0x00000006,
+	0x59a0020b, 0x8c000500, 0x04000003, 0x83340c00,
+	0x00000008, 0x58040001, 0x48034409, 0x900001c0,
+	0x48034209, 0x50040000, 0x48034407, 0x900001c0,
+	0x48034207, 0x59340200, 0x48034406, 0x0201f000,
+	0x001022c0, 0x800409c0, 0x04000005, 0x4a034406,
+	0x00000001, 0x0201f000, 0x0010230c, 0x59a0220b,
+	0x8c102500, 0x0402002e, 0x8c102506, 0x04020006,
+	0x59a03208, 0x82180480, 0x00000003, 0x02021000,
+	0x00102310, 0x59a28c06, 0x0201f800, 0x00020245,
+	0x02020000, 0x00102310, 0x0201f800, 0x001049e7,
+	0x04000005, 0x4a034406, 0x00000009, 0x0201f000,
+	0x0010230c, 0x0201f800, 0x00103a00, 0x04020005,
+	0x4a034406, 0x00000002, 0x0201f000, 0x0010230c,
+	0x59a0220b, 0x8c102506, 0x04000004, 0x59343002,
+	0x82183500, 0x00ffffff, 0x497a5a04, 0x4a025c04,
+	0x00008000, 0x0201f800, 0x001090a8, 0x04020005,
+	0x4a034406, 0x00000003, 0x0201f000, 0x0010230c,
+	0x4a01d809, 0x001035d1, 0x1c01f000, 0x59a28c06,
+	0x0201f800, 0x00020245, 0x02020000, 0x00102310,
+	0x0201f800, 0x001049e7, 0x04000005, 0x4a034406,
+	0x00000009, 0x0201f000, 0x0010230c, 0x0201f800,
+	0x00103a00, 0x04020005, 0x4a034406, 0x00000002,
+	0x0201f000, 0x0010230c, 0x497a5a04, 0x4a025c04,
+	0x00008000, 0x0201f800, 0x00103a00, 0x04020005,
+	0x4a034406, 0x00000002, 0x0201f000, 0x0010230c,
+	0x592e5800, 0x0201f800, 0x001090bd, 0x04020005,
+	0x4a034406, 0x00000003, 0x0201f000, 0x0010230c,
+	0x4a01d809, 0x001035a3, 0x1c01f000, 0x592c2805,
+	0x82140d80, 0x01000000, 0x04020005, 0x4a034406,
+	0x00000004, 0x0201f000, 0x0010230c, 0x42000800,
+	0x00000008, 0x59a00207, 0x59a01407, 0x900001c0,
+	0x80081540, 0x59a00209, 0x59a01c09, 0x900001c0,
+	0x800c1d40, 0x832c0400, 0x00000005, 0x0201f800,
+	0x00103a28, 0x8c142d00, 0x04000003, 0x4a01d809,
+	0x001035be, 0x1c01f000, 0x4031d800, 0x58ef400b,
+	0x58ee580e, 0x58ec0002, 0x82000580, 0x00000200,
+	0x02000000, 0x00102304, 0x812e59c0, 0x02000800,
+	0x001005d8, 0x42000800, 0x00000008, 0x832c0400,
+	0x00000005, 0x58ec1007, 0x58ec1808, 0x0201f000,
+	0x00103a28, 0x592c0005, 0x82000580, 0x01000000,
+	0x04020005, 0x4a034406, 0x00000004, 0x0201f000,
+	0x0010230c, 0x59a00207, 0x59a01407, 0x900001c0,
+	0x80081540, 0x59a00209, 0x59a01c09, 0x900001c0,
+	0x800c1d40, 0x42000800, 0x00000006, 0x832c0400,
+	0x00000006, 0x0201f000, 0x00103a28, 0x59a00a0a,
+	0x800409c0, 0x02000000, 0x00102310, 0x82040480,
+	0x000000e7, 0x04001003, 0x42000800, 0x000000e6,
+	0x59a00207, 0x59a01407, 0x900001c0, 0x80081540,
+	0x59a00209, 0x59a01c09, 0x900001c0, 0x800c1d40,
+	0x83880400, 0x00000000, 0x0201f800, 0x00103a28,
+	0x4a01d809, 0x001035ff, 0x1c01f000, 0x4031d800,
+	0x58ef400b, 0x58ec0002, 0x82000580, 0x00000200,
+	0x02000000, 0x00102304, 0x58ef400b, 0x59a0020b,
+	0x8c000500, 0x04000008, 0x83880400, 0x00000000,
+	0x4803c840, 0x4a03c842, 0x00000006, 0x04011000,
+	0x497b8885, 0x4a034207, 0x000000e6, 0x0201f000,
+	0x001022c0, 0x800409c0, 0x04000005, 0x4a034406,
+	0x00000001, 0x0201f000, 0x0010230c, 0x0401fbe5,
+	0x04020005, 0x4a034406, 0x00000002, 0x0201f000,
+	0x0010230c, 0x497a5a04, 0x4a025c04, 0x00008000,
+	0x59a00406, 0x800001c0, 0x02000000, 0x00102310,
+	0x82001580, 0x000000ff, 0x04000005, 0x82001480,
+	0x00000004, 0x02021000, 0x00102310, 0x40001000,
+	0x0201f800, 0x00101fbf, 0x04020005, 0x4a034406,
+	0x00000003, 0x0201f000, 0x0010230c, 0x4a01d809,
+	0x0010363a, 0x1c01f000, 0x592c0005, 0x82000580,
+	0x01000000, 0x02020000, 0x001022c0, 0x4a034406,
+	0x00000004, 0x0201f000, 0x0010230c, 0x59a01406,
+	0x8c081508, 0x04020007, 0x800409c0, 0x04000005,
+	0x4a034406, 0x00000001, 0x0201f000, 0x0010230c,
+	0x59a01c07, 0x820c0480, 0x00001000, 0x02021000,
+	0x00102310, 0x497b2804, 0x497b2805, 0x497b281c,
+	0x497b281d, 0x497b281f, 0x497b2820, 0x497b2822,
+	0x497b2823, 0x80000580, 0x0201f800, 0x001015fe,
+	0x59a80805, 0x8c081500, 0x04000004, 0x82040d40,
+	0x00000011, 0x0401f004, 0x8c081506, 0x04000002,
+	0x84040d42, 0x84040d0a, 0x48075005, 0x4202d800,
+	0x00000001, 0x82081500, 0x000000e0, 0x8008010a,
+	0x0c020036, 0x0201f800, 0x0010513b, 0x04020009,
+	0x4a035033, 0x00000001, 0x0201f800, 0x001050a2,
+	0x0401f01f, 0x4a035033, 0x00000000, 0x0401f7fb,
+	0x497b5032, 0x0201f800, 0x00104142, 0x0201f800,
+	0x00106c55, 0x0201f800, 0x00106ede, 0x0201f800,
+	0x00106c4b, 0x59a00a07, 0x480788a7, 0x59c400a3,
+	0x82000500, 0xfeffffff, 0x82000540, 0x80018000,
+	0x40000800, 0x84040d20, 0x480388a3, 0x480788a3,
+	0x497b504e, 0x42000800, 0x0000002d, 0x42001000,
+	0x001041bc, 0x0201f800, 0x00105f69, 0x59a00407,
+	0x800000c2, 0x800008c4, 0x8005d400, 0x42000000,
+	0x0000ffff, 0x0201f800, 0x0010513b, 0x04000003,
+	0x59a00207, 0x80000110, 0x0201f800, 0x00103afc,
+	0x0201f000, 0x001022c0, 0x0010366d, 0x00103670,
+	0x00103678, 0x00102310, 0x00103675, 0x00102310,
+	0x00102310, 0x00102310, 0x836c0580, 0x00000003,
+	0x04000005, 0x4a034406, 0x00000007, 0x0201f000,
+	0x0010230c, 0x59a03c06, 0x59a00407, 0x59a04a07,
+	0x902449c0, 0x80244d40, 0x59a00409, 0x59a05209,
+	0x902851c0, 0x80285540, 0x0401fb46, 0x04020005,
+	0x4a034406, 0x00000002, 0x0201f000, 0x0010230c,
+	0x417a8800, 0x41783000, 0x497b4001, 0x497b4004,
+	0x832c4400, 0x00000005, 0x48234002, 0x8c1c3d04,
+	0x04020078, 0x0201f800, 0x00020245, 0x0402002a,
+	0x0201f800, 0x001049e7, 0x04000004, 0x0201f800,
+	0x001048e3, 0x04020024, 0x8c1c3d00, 0x04000008,
+	0x59340009, 0x44004000, 0x59340008, 0x80204000,
+	0x44004000, 0x80204000, 0x0401f007, 0x59340007,
+	0x44004000, 0x59340006, 0x80204000, 0x44004000,
+	0x80204000, 0x83440580, 0x000007fe, 0x0400000d,
+	0x83440580, 0x000007fc, 0x0400000a, 0x0201f800,
+	0x001049f3, 0x04000003, 0x85468d5e, 0x0401f005,
+	0x0201f800, 0x00104838, 0x04020002, 0x85468d5e,
+	0x45444000, 0x85468d1e, 0x80204000, 0x82183400,
+	0x00000003, 0x81468800, 0x83440480, 0x000007f0,
+	0x0400100e, 0x8c1c3d06, 0x04000010, 0x83440580,
+	0x000007f0, 0x04020004, 0x42028800, 0x000007fe,
+	0x0401f006, 0x83440580, 0x000007ff, 0x04020007,
+	0x42028800, 0x000007fc, 0x82180580, 0x0000000f,
+	0x0400000b, 0x0401f7c0, 0x801831c0, 0x04020006,
+	0x59a00801, 0x800408c4, 0x48074406, 0x0201f000,
+	0x001022c0, 0x4a034004, 0x00000001, 0x49474000,
+	0x59a00001, 0x80180400, 0x48034001, 0x481f4003,
+	0x4a01d801, 0x00000000, 0x4819d804, 0x59a00002,
+	0x4801d803, 0x4825d807, 0x4829d808, 0x4000a800,
+	0x4000a000, 0x4018b000, 0x0201f800, 0x0010ab17,
+	0x40ec1000, 0x0201f800, 0x00100858, 0x4a01d809,
+	0x0010372a, 0x1c01f000, 0x4031d800, 0x58ef400b,
+	0x58ec0002, 0x82000580, 0x00000200, 0x02000000,
+	0x00102304, 0x59a00004, 0x80000540, 0x04020008,
+	0x59a28800, 0x59a04002, 0x59a03803, 0x41783000,
+	0x58ec4807, 0x58ec5008, 0x0401f78f, 0x59a00801,
+	0x800408c4, 0x48074406, 0x0201f000, 0x001022c0,
+	0x0201f800, 0x00020245, 0x0402002f, 0x0201f800,
+	0x001049e7, 0x04000004, 0x0201f800, 0x001048e3,
+	0x04020029, 0x83440580, 0x000007fe, 0x04000011,
+	0x83440580, 0x000007fc, 0x0400000e, 0x0201f800,
+	0x001049f3, 0x04000005, 0x59340403, 0x8400055e,
+	0x48026c03, 0x0401f007, 0x0201f800, 0x00104838,
+	0x04020004, 0x59340403, 0x8400055e, 0x48026c03,
+	0x4134a000, 0x4020a800, 0x4200b000, 0x00000006,
+	0x0201f800, 0x0010ab17, 0x59340007, 0x4400a800,
+	0x59340006, 0x4800a801, 0x59340009, 0x4800a802,
+	0x59340008, 0x4800a803, 0x59340403, 0x8400051e,
+	0x48026c03, 0x82204400, 0x0000000a, 0x82183400,
+	0x0000000a, 0x81468800, 0x83440480, 0x000007f0,
+	0x0400100e, 0x8c1c3d06, 0x04000010, 0x83440580,
+	0x000007f0, 0x04020004, 0x42028800, 0x000007fe,
+	0x0401f006, 0x83440580, 0x000007ff, 0x04020007,
+	0x42028800, 0x000007fc, 0x82180580, 0x0000000a,
+	0x0400000b, 0x0401f7bb, 0x801831c0, 0x04020006,
+	0x59a00801, 0x800408c4, 0x48074406, 0x0201f000,
+	0x001022c0, 0x4a034004, 0x00000001, 0x49474000,
+	0x59a00001, 0x80180400, 0x48034001, 0x481f4003,
+	0x4a01d801, 0x00000000, 0x4819d804, 0x59a00002,
+	0x4801d803, 0x4825d807, 0x4829d808, 0x40ec1000,
+	0x0201f800, 0x00100858, 0x4a01d809, 0x001037a1,
+	0x1c01f000, 0x4031d800, 0x58ef400b, 0x58ec0002,
+	0x82000580, 0x00000200, 0x02000000, 0x00102304,
+	0x59a00004, 0x80000540, 0x04020008, 0x59a28800,
+	0x59a04002, 0x59a03803, 0x41783000, 0x58ec4807,
+	0x58ec5008, 0x0401f78f, 0x59a00801, 0x800408c4,
+	0x48074406, 0x0201f000, 0x001022c0, 0x42002800,
+	0x0000007e, 0x59a00c06, 0x59a01207, 0x59a01c07,
+	0x59a02209, 0x82040500, 0x0000ff00, 0x840001c0,
+	0x82003480, 0x00000020, 0x02001000, 0x00102310,
+	0x80140480, 0x02001000, 0x00102310, 0x82040500,
+	0x000000ff, 0x82003480, 0x00000020, 0x02001000,
+	0x00102310, 0x80140480, 0x02001000, 0x00102310,
+	0x82080500, 0x0000ff00, 0x840001c0, 0x82003480,
+	0x00000020, 0x02001000, 0x00102310, 0x80140480,
+	0x02001000, 0x00102310, 0x82080500, 0x000000ff,
+	0x82003480, 0x00000020, 0x02001000, 0x00102310,
+	0x80140480, 0x02001000, 0x00102310, 0x820c0500,
+	0x0000ff00, 0x840001c0, 0x82003480, 0x00000020,
+	0x02001000, 0x00102310, 0x80140480, 0x02001000,
+	0x00102310, 0x820c0500, 0x000000ff, 0x82003480,
+	0x00000020, 0x02001000, 0x00102310, 0x80140480,
+	0x02001000, 0x00102310, 0x82100500, 0x0000ff00,
+	0x840001c0, 0x82003480, 0x00000020, 0x02001000,
+	0x00102310, 0x80140480, 0x02001000, 0x00102310,
+	0x82100500, 0x000000ff, 0x82003480, 0x00000020,
+	0x02001000, 0x00102310, 0x80140480, 0x02001000,
+	0x00102310, 0x900401c0, 0x80080d40, 0x900c01c0,
+	0x80101d40, 0x83a83400, 0x0000003a, 0x44043000,
+	0x80183000, 0x440c3000, 0x0201f000, 0x001022c0,
+	0x0401f9ec, 0x04020005, 0x4a034406, 0x00000002,
+	0x0201f000, 0x0010230c, 0x42000800, 0x0000000c,
+	0x0401f853, 0x4a01d809, 0x00103820, 0x1c01f000,
+	0x4031d800, 0x58ee580d, 0x58ef400b, 0x58ec0002,
+	0x82000580, 0x00000200, 0x02000000, 0x00102304,
+	0x832ca400, 0x00000004, 0x4200b000, 0x0000000c,
+	0x40c8a800, 0x0201f800, 0x0010ab17, 0x58c80200,
+	0x80000540, 0x04000034, 0x58c80400, 0x82000500,
+	0xfffffffb, 0x04020030, 0x58c80401, 0x80000540,
+	0x0400002d, 0x82000480, 0x0000ff01, 0x0402102a,
+	0x58c80202, 0x82000480, 0x0000005c, 0x04001026,
+	0x0201f800, 0x001063a3, 0x58c80c08, 0x58c80204,
+	0x80040480, 0x04001020, 0x58c80204, 0x82000480,
+	0x00000005, 0x0402101c, 0x58c80205, 0x58c80c08,
+	0x80040902, 0x80040480, 0x04001017, 0x58c80c08,
+	0x0201f800, 0x001062f1, 0x0400001b, 0x0201f800,
+	0x001061b9, 0x04020012, 0x4979940b, 0x59c408a3,
+	0x82040d40, 0x00000002, 0x480788a3, 0x4a038830,
+	0x00000001, 0x4a038832, 0x01ffffff, 0x58c80202,
+	0x48030804, 0x0201f800, 0x0010619b, 0x0201f000,
+	0x001022c0, 0x0201f000, 0x00102310, 0x0201f800,
+	0x001063f5, 0x0201f800, 0x00106402, 0x0201f800,
+	0x001062e4, 0x0201f000, 0x0010230c, 0x4c000000,
+	0x59a01207, 0x59a00407, 0x900811c0, 0x80081540,
+	0x59a01a09, 0x59a00409, 0x900c19c0, 0x800c1d40,
+	0x5c000000, 0x0401f1ac, 0x59840000, 0x82000580,
+	0x00000000, 0x04000054, 0x59840002, 0x8c000504,
+	0x04000051, 0x84000546, 0x48030802, 0x0201f800,
+	0x001062e4, 0x59c408a3, 0x82040d00, 0xfffffffd,
+	0x480788a3, 0x4c5c0000, 0x4200b800, 0x0010ac00,
+	0x505e6800, 0x813669c0, 0x04000008, 0x5936600e,
+	0x813261c0, 0x04000005, 0x0201f800, 0x001062d5,
+	0x02000800, 0x001064ad, 0x805cb800, 0x825c0580,
+	0x0010b3f0, 0x040207f3, 0x59866003, 0x813261c0,
+	0x0400000b, 0x59300406, 0x82000580, 0x00000009,
+	0x02020800, 0x001005d8, 0x5930b800, 0x0201f800,
+	0x001062c1, 0x405e6000, 0x0401f7f5, 0x497b0803,
+	0x4200b800, 0x0010b51b, 0x505e6000, 0x813261c0,
+	0x04000011, 0x59300406, 0x82000580, 0x00000009,
+	0x0402000d, 0x59300203, 0x82000580, 0x00000004,
+	0x04020009, 0x59326809, 0x813669c0, 0x02020800,
+	0x001005d8, 0x0201f800, 0x00100e99, 0x0201f800,
+	0x001062c1, 0x4578b800, 0x805cb800, 0x825c0580,
+	0x0010b523, 0x040207e9, 0x42000800, 0x0010b519,
+	0x49780801, 0x49780800, 0x59a80069, 0x82000400,
+	0x00000007, 0x48035069, 0x0201f800, 0x001063f5,
+	0x0201f800, 0x00106402, 0x5c00b800, 0x0201f800,
+	0x001061b4, 0x0201f000, 0x001022c0, 0x836c0580,
+	0x00000003, 0x04000005, 0x4a034406, 0x00000007,
+	0x0201f000, 0x0010230c, 0x59a00407, 0x59a02207,
+	0x901021c0, 0x80102540, 0x59a00409, 0x59a02a09,
+	0x901429c0, 0x80142d40, 0x0401f91e, 0x04020005,
+	0x4a034406, 0x00000002, 0x0201f000, 0x0010230c,
+	0x417a8800, 0x41781800, 0x497b4001, 0x497b4003,
+	0x832c3400, 0x00000004, 0x481b4002, 0x41440000,
+	0x81ac0400, 0x50026800, 0x813669c0, 0x0400000b,
+	0x0201f800, 0x001049e7, 0x04020008, 0x59340002,
+	0x48003000, 0x49443001, 0x82183400, 0x00000002,
+	0x820c1c00, 0x00000002, 0x81468800, 0x83440480,
+	0x00000800, 0x04000005, 0x820c0480, 0x00000010,
+	0x0402100b, 0x0401f7ea, 0x800c19c0, 0x04020006,
+	0x59a00801, 0x80040902, 0x48074406, 0x0201f000,
+	0x001022c0, 0x4a034003, 0x00000001, 0x49474000,
+	0x59a00001, 0x800c0400, 0x48034001, 0x40ec1000,
+	0x4a001001, 0x00000000, 0x480c1004, 0x59a00002,
+	0x48001003, 0x48101007, 0x48141008, 0x0201f800,
+	0x00100858, 0x4a01d809, 0x00103920, 0x1c01f000,
+	0x4031d800, 0x58ef400b, 0x58ec0002, 0x82000580,
+	0x00000200, 0x02000000, 0x00102304, 0x59a00003,
+	0x80000540, 0x04020008, 0x59a28800, 0x59a03002,
+	0x41781800, 0x40ec1000, 0x58082007, 0x58082808,
+	0x0401f7bf, 0x59a00801, 0x80040902, 0x48074406,
+	0x0201f000, 0x001022c0, 0x800409c0, 0x04000005,
+	0x4a034406, 0x00000001, 0x0201f000, 0x0010230c,
+	0x59a80026, 0x8c00050a, 0x04020007, 0x8c000506,
+	0x04020005, 0x4a034406, 0x00000016, 0x0201f000,
+	0x0010230c, 0x0401f8bb, 0x04020005, 0x4a034406,
+	0x00000002, 0x0201f000, 0x0010230c, 0x59a00c06,
+	0x80040902, 0x59a00407, 0x59a01207, 0x900811c0,
+	0x80081540, 0x59a00409, 0x59a01a09, 0x900c19c0,
+	0x800c1d40, 0x832c0400, 0x00000005, 0x0401f8ce,
+	0x4a01d809, 0x0010395b, 0x1c01f000, 0x4031d800,
+	0x58ef400b, 0x58ee580d, 0x58ec0002, 0x82000580,
+	0x00000200, 0x02000000, 0x00102304, 0x592c0009,
+	0x0201f800, 0x00105c9a, 0x02000800, 0x001045a6,
+	0x02020000, 0x00102310, 0x49474001, 0x481a6802,
+	0x592c000a, 0x82001d80, 0x70000000, 0x04020007,
+	0x0401f890, 0x04020011, 0x4a034406, 0x00000002,
+	0x0201f000, 0x0010230c, 0x82001d80, 0x72000000,
+	0x02020000, 0x00102310, 0x0401f886, 0x04020885,
+	0x04020884, 0x04020005, 0x4a034406, 0x00000002,
+	0x0201f000, 0x0010230c, 0x58ee580d, 0x4a025c04,
+	0x00008000, 0x497a5a04, 0x592c3208, 0x80183102,
+	0x592c1801, 0x4a001805, 0x01000000, 0x0201f800,
+	0x001090d1, 0x04020005, 0x4a034406, 0x00000003,
+	0x0201f000, 0x0010230c, 0x4a01d809, 0x00103995,
+	0x1c01f000, 0x592c4000, 0x592c0005, 0x82000580,
+	0x01000000, 0x04020005, 0x4a034406, 0x00000004,
+	0x0201f000, 0x0010230c, 0x832c3c00, 0x00000005,
+	0x401ca000, 0x401ca800, 0x5820280a, 0x4200b000,
+	0x00000002, 0x82143580, 0x70000000, 0x04000003,
+	0x4200b000, 0x0000000f, 0x0201f800, 0x0010ab28,
+	0x401c0000, 0x58201006, 0x58201807, 0x58202205,
+	0x80102102, 0x82143580, 0x70000000, 0x04020008,
+	0x82103480, 0x00000002, 0x02001000, 0x00102310,
+	0x42000800, 0x00000002, 0x0401f06e, 0x82143580,
+	0x72000000, 0x02020000, 0x00102310, 0x82103480,
+	0x0000002a, 0x02001000, 0x00102310, 0x42000800,
+	0x0000000f, 0x0401f863, 0x4a01d809, 0x001039c9,
+	0x1c01f000, 0x4031d800, 0x58ef400b, 0x58ee580e,
+	0x58ec0002, 0x82000580, 0x00000200, 0x02000000,
+	0x00102304, 0x592e5800, 0x832c0c00, 0x00000005,
+	0x4004a000, 0x4004a800, 0x4200b000, 0x0000000f,
+	0x0201f800, 0x0010ab28, 0x40ec1000, 0x4a001001,
+	0x00000000, 0x4a001004, 0x0000000f, 0x48041003,
+	0x0201f800, 0x00100858, 0x4a01d809, 0x001039e5,
+	0x1c01f000, 0x4031d800, 0x58ef400b, 0x58ee580e,
+	0x58ec0002, 0x82000580, 0x00000200, 0x02000000,
+	0x00102304, 0x832c0c00, 0x00000005, 0x4004a000,
+	0x4004a800, 0x4200b000, 0x0000000c, 0x0201f800,
+	0x0010ab28, 0x40ec1000, 0x4a001001, 0x00000000,
+	0x4a001004, 0x0000000c, 0x48041003, 0x0201f800,
+	0x00100858, 0x4a01d809, 0x001022b9, 0x1c01f000,
+	0x0201f800, 0x001007e4, 0x04000010, 0x497a5800,
+	0x58ec000d, 0x80000540, 0x04020004, 0x492dd80d,
+	0x492dd80e, 0x0401f007, 0x58ec000e, 0x48025800,
+	0x82000400, 0x00000001, 0x452c0000, 0x492dd80e,
+	0x832c0400, 0x00000004, 0x492fc857, 0x4803c857,
+	0x1c01f000, 0x4d2c0000, 0x48efc857, 0x58ec400d,
+	0x4823c857, 0x802041c0, 0x04000007, 0x40225800,
+	0x592c4001, 0x497a5801, 0x0201f800, 0x001007f4,
+	0x0401f7f8, 0x4979d80d, 0x4979d80e, 0x5c025800,
+	0x1c01f000, 0x42003000, 0x00000001, 0x0401f003,
+	0x42003000, 0x00000000, 0x4803c857, 0x4807c857,
+	0x480bc857, 0x480fc857, 0x481bc857, 0x48efc857,
+	0x4819d801, 0x800409c0, 0x02000800, 0x001005d8,
+	0x4805d804, 0x4801d803, 0x4809d807, 0x480dd808,
+	0x40ec1000, 0x0201f800, 0x00100858, 0x4a01d809,
+	0x001022b9, 0x1c01f000, 0x80002d80, 0x480bc857,
+	0x480fc857, 0x4813c857, 0x4817c857, 0x4d2c0000,
+	0x4da00000, 0x42034000, 0x0010b4a4, 0x59a00017,
+	0x800001c0, 0x04020013, 0x04006012, 0x480bc020,
+	0x480fc021, 0x4813c022, 0x4817c023, 0x900811c0,
+	0x82081540, 0x00000012, 0x480bc011, 0x59e00017,
+	0x8c000508, 0x04020004, 0x4203e000, 0x30000001,
+	0x0401f053, 0x4a03c017, 0x00000002, 0x0401f7fb,
+	0x4c040000, 0x4c1c0000, 0x80000800, 0x48074017,
+	0x59a0381a, 0x481fc857, 0x801c39c0, 0x04020027,
+	0x82000480, 0x0000000a, 0x04021010, 0x59a00018,
+	0x80000000, 0x48034018, 0x59a00219, 0x82000400,
+	0x00000002, 0x82000c80, 0x00000013, 0x48034219,
+	0x04001003, 0x497b4219, 0x41780000, 0x59a03816,
+	0x801c3c00, 0x0401f030, 0x4803c856, 0x0201f800,
+	0x001007e4, 0x04000007, 0x492f401a, 0x492f401b,
+	0x412c3800, 0x497b421c, 0x497a5813, 0x0401f026,
+	0x59880051, 0x80000000, 0x48031051, 0x59a00017,
+	0x80000040, 0x48034017, 0x59a00219, 0x59a03816,
+	0x801c3c00, 0x0401f01c, 0x59a0021c, 0x82000400,
+	0x00000002, 0x82000c80, 0x00000012, 0x04021004,
+	0x4803421c, 0x801c3c00, 0x0401f013, 0x0201f800,
+	0x001007e4, 0x0402000b, 0x59880051, 0x80000000,
+	0x48031051, 0x59a00017, 0x80000040, 0x48034017,
+	0x4803c856, 0x59a0021c, 0x801c3c00, 0x0401f006,
+	0x492f401a, 0x492c3813, 0x412c3800, 0x497b421c,
+	0x497a5813, 0x48083c00, 0x480c3a00, 0x48103c01,
+	0x48143a01, 0x5c003800, 0x5c000800, 0x5c034000,
+	0x5c025800, 0x1c01f000, 0x480fc857, 0x4813c857,
+	0x481bc857, 0x42000000, 0x0010b813, 0x0201f800,
+	0x0010aa47, 0x801800d0, 0x40002800, 0x42001000,
+	0x00008014, 0x0401f786, 0x4c000000, 0x599c0017,
+	0x8c000512, 0x5c000000, 0x1c01f000, 0x4c000000,
+	0x599c0018, 0x8c00050e, 0x5c000000, 0x1c01f000,
+	0x59a80821, 0x800409c0, 0x04000005, 0x4a034406,
+	0x00000001, 0x0201f000, 0x0010230c, 0x836c0580,
+	0x00000003, 0x04000005, 0x4a034406, 0x00000007,
+	0x0201f000, 0x0010230c, 0x599c0017, 0x8c00050a,
+	0x04000005, 0x4a034406, 0x00000008, 0x0201f000,
+	0x0010230c, 0x59340405, 0x8c000508, 0x04020004,
+	0x8c00050a, 0x02020000, 0x001034db, 0x497a5a04,
+	0x497a5805, 0x4a025c04, 0x00008000, 0x0201f800,
+	0x00109176, 0x04020005, 0x4a034406, 0x00000003,
+	0x0201f000, 0x0010230c, 0x4a01d809, 0x00103aed,
+	0x1c01f000, 0x592c0005, 0x82000580, 0x01000000,
+	0x04020005, 0x4a034406, 0x00000004, 0x0201f000,
+	0x0010230c, 0x59a28c06, 0x0201f800, 0x00020245,
+	0x02020000, 0x00102310, 0x0201f000, 0x001034db,
+	0x82001580, 0x0000ffff, 0x04000009, 0x0201f800,
+	0x00105c9a, 0x02000800, 0x00020245, 0x0402000c,
+	0x0201f800, 0x00105fae, 0x0401f009, 0x42028800,
+	0x000007ef, 0x0201f800, 0x00020245, 0x02000800,
+	0x00105fae, 0x81468840, 0x040217fb, 0x1c01f000,
+	0x4803c856, 0x4c0c0000, 0x4d340000, 0x4d440000,
+	0x42028800, 0x000007fe, 0x0201f800, 0x00020245,
+	0x04020009, 0x5934180a, 0x820c1d00, 0x00000001,
+	0x820c1d80, 0x00000001, 0x42001000, 0x0000801b,
+	0x0401ff1e, 0x5c028800, 0x5c026800, 0x5c001800,
+	0x1c01f000, 0x599c0017, 0x8c000508, 0x1c01f000,
+	0x48efc857, 0x04011000, 0x48efc840, 0x4a03c842,
+	0x00000011, 0x40000000, 0x040117ff, 0x4a01d80f,
+	0xbeefbeef, 0x1c01f000, 0x497b4000, 0x497b4001,
+	0x497b4002, 0x497b4003, 0x497b4004, 0x1c01f000,
+	0x59c400a4, 0x4c580000, 0x4c500000, 0x4c540000,
+	0x82000500, 0x0000000f, 0x82000480, 0x00000007,
+	0x0400100a, 0x82006c80, 0x00000006, 0x02021800,
+	0x001005d8, 0x0c01f807, 0x5c00a800, 0x5c00a000,
+	0x5c00b000, 0x1c01f000, 0x0401f906, 0x0401f7fb,
+	0x00103b51, 0x00103b57, 0x00103b7c, 0x00103b9e,
+	0x00103c59, 0x59c40806, 0x8c040d00, 0x04020003,
+	0x84040d40, 0x48078806, 0x1c01f000, 0x59c40005,
+	0x8c000534, 0x02020000, 0x0010429e, 0x4a038805,
+	0xffffffff, 0x42006000, 0x00020000, 0x0201f800,
+	0x00104282, 0x59a80015, 0x82000500, 0xfffffffa,
+	0x84000542, 0x48035015, 0x497b5026, 0x42000800,
+	0x0010be21, 0x45780800, 0x497b5013, 0x42006000,
+	0xffefffff, 0x42006800, 0x40000000, 0x0201f800,
+	0x0010427d, 0x59c40006, 0x82000500, 0xffffff0f,
+	0x48038806, 0x42000800, 0x00000010, 0x42001000,
+	0x001041f3, 0x0201f800, 0x00105f83, 0x0401f001,
+	0x42006000, 0xffffffff, 0x42006800, 0x00800000,
+	0x0201f800, 0x0010427d, 0x4200b000, 0x000000c8,
+	0x59c400a4, 0x82000500, 0x0000000f, 0x82000580,
+	0x0000000a, 0x0400000f, 0x8058b040, 0x040207f9,
+	0x497b5014, 0x42006000, 0xbf7fffff, 0x42006800,
+	0x00018000, 0x0201f800, 0x0010427d, 0x42006000,
+	0xfffeffff, 0x41786800, 0x0201f000, 0x0010427d,
+	0x497b5014, 0x4a035012, 0x00000000, 0x80000580,
+	0x0201f000, 0x00104289, 0x4a038805, 0xffffffff,
+	0x59a80012, 0x82000c80, 0x00000004, 0x02021800,
+	0x001005d8, 0x0c01f001, 0x00103ba9, 0x00103bd6,
+	0x00103c4f, 0x4803c856, 0x59c400a3, 0x8400051e,
+	0x480388a3, 0x4a035012, 0x00000001, 0x59c40008,
+	0x8400054e, 0x48038808, 0x0201f800, 0x00104263,
+	0x42007800, 0x0010b54c, 0x4a007806, 0x11010000,
+	0x4200a000, 0x0010b402, 0x4200a800, 0x0010b553,
+	0x4200b000, 0x00000002, 0x0201f800, 0x0010ab17,
+	0x497b8802, 0x42000800, 0x00000003, 0x497b504a,
+	0x0201f800, 0x0010416e, 0x4a03504a, 0x00000001,
+	0x497b5016, 0x0201f800, 0x00104290, 0x42006000,
+	0xffffffff, 0x42006800, 0x00080000, 0x0201f800,
+	0x0010427d, 0x42006000, 0xfff7ffff, 0x41786800,
+	0x0201f000, 0x0010427d, 0x59a80016, 0x497b5016,
+	0x80002540, 0x04000066, 0x59c40004, 0x82000500,
+	0x00000003, 0x04020071, 0x59a80815, 0x8c040d02,
+	0x0400004b, 0x82100580, 0x0000000c, 0x0402004f,
+	0x82100400, 0x00000018, 0x8000b104, 0x41cc1000,
+	0x42001800, 0x0010b54c, 0x50080800, 0x500c0000,
+	0x80040580, 0x0402001a, 0x80081000, 0x800c1800,
+	0x8058b040, 0x040207f9, 0x0201f800, 0x00104290,
+	0x42006000, 0xffffffff, 0x42006800, 0x00500000,
+	0x0201f800, 0x0010427d, 0x4a035012, 0x00000002,
+	0x4a035014, 0x00000002, 0x42000800, 0x000007d0,
+	0x42001000, 0x00104148, 0x0201f800, 0x0010606e,
+	0x0201f800, 0x00104263, 0x0401f048, 0x59cc0806,
+	0x82040d80, 0x11010000, 0x04020028, 0x59cc0800,
+	0x82040500, 0x00ffffff, 0x0400001a, 0x82000580,
+	0x000000ef, 0x04020017, 0x59cc0801, 0x82040500,
+	0x00ffffff, 0x82000580, 0x000000ef, 0x04020011,
+	0x83cca400, 0x00000007, 0x4200a800, 0x0010b402,
+	0x4200b000, 0x00000002, 0x50500800, 0x50540000,
+	0x80040480, 0x04001007, 0x04020010, 0x8050a000,
+	0x8054a800, 0x8058b040, 0x040207f8, 0x0401f00b,
+	0x59a80015, 0x84000502, 0x48035015, 0x41cca000,
+	0x4200a800, 0x0010b54c, 0x4200b000, 0x00000009,
+	0x0201f800, 0x0010ab17, 0x0201f800, 0x00104290,
+	0x42006000, 0xffffffff, 0x42006800, 0x00080000,
+	0x0201f800, 0x0010427d, 0x42006000, 0xfff7ffff,
+	0x41786800, 0x0201f800, 0x0010427d, 0x42006000,
+	0xffffffff, 0x42006800, 0x00004000, 0x0201f800,
+	0x0010427d, 0x59c40004, 0x82000500, 0x00000003,
+	0x04020006, 0x497b5016, 0x42000800, 0x00000003,
+	0x0201f000, 0x0010416e, 0x1c01f000, 0x1c01f000,
+	0x59a80014, 0x82006d80, 0x0000000f, 0x04000005,
+	0x82000580, 0x0000001b, 0x02020800, 0x00104139,
+	0x1c01f000, 0x59a80015, 0x84000506, 0x48035015,
+	0x497b504a, 0x59a80014, 0x82000c80, 0x0000001e,
+	0x02021800, 0x001005d8, 0x0c01f001, 0x00103c97,
+	0x00103cac, 0x00103cd5, 0x00103cf0, 0x00103d14,
+	0x00103d45, 0x00103d68, 0x00103d9b, 0x00103dbe,
+	0x00103de4, 0x00103e21, 0x00103e48, 0x00103e5f,
+	0x00103e71, 0x00103e8a, 0x00103ea0, 0x00103ea5,
+	0x00103ecd, 0x00103ef0, 0x00103f16, 0x00103f39,
+	0x00103f6c, 0x00103fae, 0x00103fd8, 0x00103ff0,
+	0x00104030, 0x00104049, 0x0010405c, 0x0010405d,
+	0x4803c856, 0x4202d800, 0x00000007, 0x0201f800,
+	0x0010513b, 0x04000007, 0x42006000, 0xffffffd7,
+	0x41786800, 0x0201f800, 0x0010427d, 0x0401f00b,
+	0x59c40006, 0x82000500, 0xffffff0f, 0x48038806,
+	0x42001000, 0x000000f0, 0x0201f800, 0x0010193d,
+	0x0201f800, 0x00105098, 0x1c01f000, 0x4803c856,
+	0x42006000, 0xbf7fffff, 0x42006800, 0x00400000,
+	0x0201f800, 0x0010427d, 0x4a035014, 0x00000001,
+	0x42001000, 0x001041f3, 0x0201f800, 0x00105fa4,
+	0x0201f800, 0x001041f8, 0x42000800, 0x000007d0,
+	0x42001000, 0x00104148, 0x0201f000, 0x0010606e,
+	0x59a80016, 0x82000580, 0x00000014, 0x04020025,
+	0x4803c857, 0x42006000, 0xffbfffff, 0x41786800,
+	0x0201f800, 0x0010427d, 0x59c40004, 0x82000500,
+	0x00000003, 0x0402001b, 0x59cc1006, 0x82081580,
+	0x11020000, 0x04020016, 0x59cc1007, 0x8c08153e,
+	0x0400000b, 0x59a80015, 0x8c000504, 0x04020008,
+	0x42000000, 0x0010b83f, 0x0201f800, 0x0010aa47,
+	0x59a80015, 0x84000544, 0x48035015, 0x42001000,
+	0x00104148, 0x0201f800, 0x00105f90, 0x4a035014,
+	0x00000010, 0x0401f9d4, 0x0401f002, 0x497b5016,
+	0x1c01f000, 0x4803c856, 0x4a035014, 0x00000003,
+	0x42006000, 0xbf3fffff, 0x42006800, 0x00100000,
+	0x0201f800, 0x0010427d, 0x42001000, 0x001041f3,
+	0x0201f800, 0x00105fa4, 0x0201f800, 0x001041f8,
+	0x42001000, 0x00104148, 0x0201f800, 0x00105f90,
+	0x42007800, 0x0010b552, 0x46007800, 0x11020000,
+	0x42000800, 0x00000005, 0x0201f000, 0x0010416e,
+	0x59a80016, 0x80000540, 0x04000021, 0x4803c857,
+	0x42001000, 0x00104148, 0x0201f800, 0x00105f90,
+	0x59a80016, 0x82000580, 0x00000014, 0x04020016,
+	0x59cc1006, 0x82081580, 0x11020000, 0x04020012,
+	0x59cc1007, 0x8c08153e, 0x0400000b, 0x59a80015,
+	0x8c000504, 0x04020008, 0x42000000, 0x0010b83f,
+	0x0201f800, 0x0010aa47, 0x59a80015, 0x84000544,
+	0x48035015, 0x4a035014, 0x00000004, 0x0401f805,
+	0x0401f003, 0x0201f800, 0x00104139, 0x1c01f000,
+	0x4803c856, 0x4a035014, 0x00000005, 0x83cca400,
+	0x00000006, 0x4200a800, 0x0010b552, 0x4200b000,
+	0x00000005, 0x0201f800, 0x0010ab17, 0x42007800,
+	0x0010b552, 0x46007800, 0x11030000, 0x0201f800,
+	0x0010413e, 0x04020014, 0x59a80015, 0x8c000500,
+	0x04020011, 0x59a80810, 0x82040580, 0x00ffffff,
+	0x0400000d, 0x82040d00, 0x000000ff, 0x82040400,
+	0x0010210e, 0x50000800, 0x80040910, 0x42001000,
+	0x00000004, 0x0401fb9b, 0x0400000b, 0x0201f800,
+	0x0010420d, 0x4200b000, 0x00000004, 0x83cca400,
+	0x00000007, 0x4200a800, 0x0010b553, 0x0201f800,
+	0x0010ab17, 0x42000800, 0x00000005, 0x0201f000,
+	0x0010416e, 0x59a80016, 0x80000540, 0x04000020,
+	0x4803c857, 0x42001000, 0x00104148, 0x0201f800,
+	0x00105f90, 0x59a80016, 0x82000580, 0x00000014,
+	0x04020016, 0x59cc1006, 0x82081580, 0x11030000,
+	0x04020012, 0x59cc1007, 0x8c08153e, 0x0400000b,
+	0x59a80015, 0x8c000504, 0x04020008, 0x42000000,
+	0x0010b83f, 0x0201f800, 0x0010aa47, 0x59a80015,
+	0x84000544, 0x48035015, 0x4a035014, 0x00000006,
+	0x0401f804, 0x0401f002, 0x0401fbd3, 0x1c01f000,
+	0x4803c856, 0x4a035014, 0x00000007, 0x83cca400,
+	0x00000006, 0x4200a800, 0x0010b552, 0x4200b000,
+	0x00000005, 0x0201f800, 0x0010ab17, 0x42007800,
+	0x0010b552, 0x46007800, 0x11040000, 0x0401fbc7,
+	0x04020020, 0x59a80015, 0x8c000500, 0x0402001d,
+	0x599c0017, 0x8c000500, 0x0400001a, 0x599c1402,
+	0x82080480, 0x0000007f, 0x02021800, 0x001005d8,
+	0x4c080000, 0x82081400, 0x0010210e, 0x50081000,
+	0x82081500, 0x000000ff, 0x480b5010, 0x42000800,
+	0x00000003, 0x0201f800, 0x00106c78, 0x5c000800,
+	0x42001000, 0x00000004, 0x0401fb3e, 0x04000005,
+	0x0401fd2b, 0x04000003, 0x0201f800, 0x001015fe,
+	0x42000800, 0x00000005, 0x0401f3d4, 0x59a80016,
+	0x80000540, 0x04000020, 0x4803c857, 0x42001000,
+	0x00104148, 0x0201f800, 0x00105f90, 0x59a80016,
+	0x82000580, 0x00000014, 0x04020016, 0x59cc1006,
+	0x82081580, 0x11040000, 0x04020012, 0x59cc1007,
+	0x8c08153e, 0x0400000b, 0x59a80015, 0x8c000504,
+	0x04020008, 0x42000000, 0x0010b83f, 0x0201f800,
+	0x0010aa47, 0x59a80015, 0x84000544, 0x48035015,
+	0x4a035014, 0x00000008, 0x0401f804, 0x0401f002,
+	0x0401fb7d, 0x1c01f000, 0x4803c856, 0x4a035014,
+	0x00000009, 0x83cca400, 0x00000006, 0x4200a800,
+	0x0010b552, 0x4200b000, 0x00000005, 0x0201f800,
+	0x0010ab17, 0x42007800, 0x0010b552, 0x46007800,
+	0x11050100, 0x0401fb71, 0x0402000a, 0x59a80015,
+	0x8c000500, 0x04020007, 0x0401fa8c, 0x04020005,
+	0x82000540, 0x00000001, 0x0201f800, 0x001015fe,
+	0x42000800, 0x00000005, 0x0401fb94, 0x0401fb63,
+	0x04020ea4, 0x4d3c0000, 0x42027800, 0x00000001,
+	0x0201f800, 0x00109874, 0x5c027800, 0x1c01f000,
+	0x59a80016, 0x80000540, 0x0400003a, 0x4803c857,
+	0x42001000, 0x00104148, 0x0201f800, 0x00105f90,
+	0x59a80016, 0x82000580, 0x00000014, 0x04020030,
+	0x59cc1006, 0x82080500, 0x11050000, 0x82000580,
+	0x11050000, 0x0402002a, 0x8c081510, 0x04000014,
+	0x59cc1007, 0x8c08153e, 0x0400000b, 0x59a80015,
+	0x8c000504, 0x04020008, 0x42000000, 0x0010b83f,
+	0x0201f800, 0x0010aa47, 0x59a80015, 0x84000544,
+	0x48035015, 0x4a035013, 0x00000001, 0x4a035014,
+	0x0000000a, 0x0401f818, 0x0401f016, 0x80000540,
+	0x04020013, 0x59cc1007, 0x8c08153e, 0x0400000b,
+	0x59a80015, 0x8c000504, 0x04020008, 0x42000000,
+	0x0010b83f, 0x0201f800, 0x0010aa47, 0x59a80015,
+	0x84000544, 0x48035015, 0x497b5013, 0x4a035014,
+	0x0000000e, 0x0401f86d, 0x0401f002, 0x0401fb1a,
+	0x1c01f000, 0x4803c856, 0x4a035014, 0x0000000b,
+	0x42001000, 0x0010b553, 0x4008a800, 0x4200b000,
+	0x00000020, 0x4600a800, 0xffffffff, 0x8054a800,
+	0x8058b040, 0x040207fc, 0x42007800, 0x0010b552,
+	0x46007800, 0x11060000, 0x42001000, 0x0010b553,
+	0x0401fb0a, 0x04000005, 0x50080000, 0x46001000,
+	0x00ffffff, 0x0401f00c, 0x50080800, 0x82040d00,
+	0x0000ffff, 0x59a80010, 0x82000500, 0x000000ff,
+	0x82000540, 0x00000100, 0x800000e0, 0x80040d40,
+	0x44041000, 0x42000800, 0x00000021, 0x0401f327,
+	0x59a80016, 0x80000540, 0x04000014, 0x4803c857,
+	0x59a80016, 0x42001000, 0x00104148, 0x0201f800,
+	0x00105f90, 0x59a80016, 0x82000580, 0x00000084,
+	0x04020009, 0x59cc1006, 0x82081580, 0x11060000,
+	0x04020005, 0x4a035014, 0x0000000c, 0x0401f804,
+	0x0401f002, 0x0401fadc, 0x1c01f000, 0x4803c856,
+	0x4a035014, 0x0000000d, 0x83cca400, 0x00000006,
+	0x4200a800, 0x0010b552, 0x4200b000, 0x00000021,
+	0x0201f800, 0x0010ab17, 0x42007800, 0x0010b552,
+	0x46007800, 0x11070000, 0x42000800, 0x00000021,
+	0x0401f2fe, 0x59a80016, 0x80000540, 0x04000016,
+	0x4803c857, 0x59a80016, 0x42001000, 0x00104148,
+	0x0201f800, 0x00105f90, 0x82000580, 0x00000084,
+	0x0402000c, 0x59cc1006, 0x82081580, 0x11070000,
+	0x04020008, 0x4a035013, 0x00000001, 0x0401fa91,
+	0x4a035014, 0x0000000e, 0x0401f804, 0x0401f002,
+	0x0401fab1, 0x1c01f000, 0x4803c856, 0x82040d40,
+	0x00000001, 0x0401fbfc, 0x4a035014, 0x0000000f,
+	0x497b5016, 0x42006000, 0xffffffff, 0x42006800,
+	0x00300000, 0x0401fbe8, 0x42006000, 0xffdfffff,
+	0x41786800, 0x0401fbe4, 0x42000800, 0x000007d0,
+	0x42001000, 0x00104148, 0x0201f000, 0x00105f69,
+	0x4803c856, 0x59a80016, 0x80000540, 0x04020296,
+	0x1c01f000, 0x4803c856, 0x4a035014, 0x00000011,
+	0x83cca400, 0x00000006, 0x4200a800, 0x0010b552,
+	0x4200b000, 0x00000005, 0x0201f800, 0x0010ab17,
+	0x4200a800, 0x0010b552, 0x4600a800, 0x11020000,
+	0x0401fa8a, 0x04020015, 0x59a80010, 0x82000d00,
+	0xffff0000, 0x04000011, 0x82000500, 0x000000ff,
+	0x0400000e, 0x82000c00, 0x0010210e, 0x50040800,
+	0x80040910, 0x82040580, 0x0000007e, 0x04000007,
+	0x82040580, 0x00000080, 0x04000004, 0x42001000,
+	0x00000004, 0x0401fa07, 0x42000800, 0x00000005,
+	0x0401f2a2, 0x59a80016, 0x80000540, 0x04000020,
+	0x4803c857, 0x42001000, 0x00104148, 0x0201f800,
+	0x00105f90, 0x59a80016, 0x82000580, 0x00000014,
+	0x04020016, 0x59cc1006, 0x82081580, 0x11030000,
+	0x04020012, 0x59cc1007, 0x8c08153e, 0x0400000b,
+	0x59a80015, 0x8c000504, 0x04020008, 0x42000000,
+	0x0010b83f, 0x0201f800, 0x0010aa47, 0x59a80015,
+	0x84000544, 0x48035015, 0x4a035014, 0x00000012,
+	0x0401f804, 0x0401f002, 0x0401fa4b, 0x1c01f000,
+	0x4803c856, 0x4a035014, 0x00000013, 0x83cca400,
+	0x00000006, 0x4200a800, 0x0010b552, 0x4200b000,
+	0x00000005, 0x0201f800, 0x0010ab17, 0x4200a800,
+	0x0010b552, 0x4600a800, 0x11030000, 0x0401fa3f,
+	0x04020013, 0x59a80015, 0x8c000500, 0x04020010,
+	0x59a80810, 0x82040580, 0x00ffffff, 0x0400000c,
+	0x82040d00, 0x000000ff, 0x82040400, 0x0010210e,
+	0x50000800, 0x80040910, 0x42001000, 0x00000004,
+	0x0401f9c0, 0x04000002, 0x0401fafb, 0x42000800,
+	0x00000005, 0x0401f259, 0x59a80016, 0x80000540,
+	0x04000020, 0x4803c857, 0x42001000, 0x00104148,
+	0x0201f800, 0x00105f90, 0x59a80016, 0x82000580,
+	0x00000014, 0x04020016, 0x59cc1006, 0x82081580,
+	0x11040000, 0x04020012, 0x59cc1007, 0x8c08153e,
+	0x0400000b, 0x59a80015, 0x8c000504, 0x04020008,
+	0x42000000, 0x0010b83f, 0x0201f800, 0x0010aa47,
+	0x59a80015, 0x84000544, 0x48035015, 0x4a035014,
+	0x00000014, 0x0401f804, 0x0401f002, 0x0401fa02,
+	0x1c01f000, 0x4803c856, 0x4a035014, 0x00000015,
+	0x83cca400, 0x00000006, 0x4200a800, 0x0010b552,
+	0x4200b000, 0x00000005, 0x0201f800, 0x0010ab17,
+	0x4200a800, 0x0010b552, 0x4600a800, 0x11040000,
+	0x0401f9f6, 0x04020020, 0x59a80015, 0x8c000500,
+	0x0402001d, 0x599c0017, 0x8c000500, 0x0400001a,
+	0x599c1402, 0x82080480, 0x0000007f, 0x02021800,
+	0x001005d8, 0x4c080000, 0x82081400, 0x0010210e,
+	0x50081000, 0x82081500, 0x000000ff, 0x480b5010,
+	0x42000800, 0x00000003, 0x0201f800, 0x00106c78,
+	0x5c000800, 0x42001000, 0x00000004, 0x0401f96d,
+	0x04000005, 0x0201f800, 0x00103abf, 0x02020800,
+	0x001015fe, 0x42000800, 0x00000005, 0x0401f203,
+	0x59a80016, 0x80000540, 0x0400003f, 0x4803c857,
+	0x42001000, 0x00104148, 0x0201f800, 0x00105f90,
+	0x59a80016, 0x82000580, 0x00000014, 0x04020035,
+	0x59cc1006, 0x82080500, 0x11050000, 0x82000580,
+	0x11050000, 0x0402002f, 0x8c081510, 0x04000010,
+	0x0401fb09, 0x59cc1007, 0x8c08153e, 0x0400000b,
+	0x59a80015, 0x8c000504, 0x04020008, 0x42000000,
+	0x0010b83f, 0x0201f800, 0x0010aa47, 0x59a80015,
+	0x84000544, 0x48035015, 0x0401f013, 0x59cc1007,
+	0x8c08153e, 0x0400000b, 0x59a80015, 0x8c000504,
+	0x04020008, 0x42000000, 0x0010b83f, 0x0201f800,
+	0x0010aa47, 0x59a80015, 0x84000544, 0x48035015,
+	0x82000540, 0x00000001, 0x0401faeb, 0x497b5013,
+	0x0401f003, 0x4a035013, 0x00000001, 0x59cc1007,
+	0x8c08153c, 0x04000003, 0x4a035026, 0x00000008,
+	0x4a035014, 0x00000016, 0x0401f804, 0x0401f002,
+	0x0401f98d, 0x1c01f000, 0x4803c856, 0x83cca400,
+	0x00000006, 0x4200a800, 0x0010b552, 0x4200b000,
+	0x00000005, 0x0201f800, 0x0010ab17, 0x4a035014,
+	0x00000017, 0x59a80013, 0x8c000500, 0x04000006,
+	0x42001000, 0x0010b552, 0x46001000, 0x11050100,
+	0x0401f003, 0x4a035014, 0x0000001b, 0x0401f97b,
+	0x0402000a, 0x59a80015, 0x8c000500, 0x04020007,
+	0x0401f896, 0x04020005, 0x82000540, 0x00000001,
+	0x0201f800, 0x001015fe, 0x42000800, 0x00000005,
+	0x0401f99e, 0x4d3c0000, 0x42027800, 0x00000001,
+	0x0201f800, 0x00109874, 0x5c027800, 0x1c01f000,
+	0x59a80016, 0x80000540, 0x04000015, 0x4803c857,
+	0x42001000, 0x00104148, 0x0201f800, 0x00105f90,
+	0x59a80016, 0x82000580, 0x00000084, 0x0402000b,
+	0x59cc1006, 0x82081580, 0x11060000, 0x04020007,
+	0x80000580, 0x0401faa0, 0x4a035014, 0x00000018,
+	0x0401f804, 0x0401f002, 0x0401f94b, 0x1c01f000,
+	0x4803c856, 0x4a035014, 0x00000019, 0x83cca400,
+	0x00000006, 0x4200a800, 0x0010b552, 0x4200b000,
+	0x00000021, 0x0201f800, 0x0010ab17, 0x42003800,
+	0x0010b553, 0x0401f941, 0x04020018, 0x401c2800,
+	0x50141000, 0x80080130, 0x80000000, 0x40001800,
+	0x82081500, 0x00ffffff, 0x800000f0, 0x80080540,
+	0x44002800, 0x59a80810, 0x82040d00, 0x000000ff,
+	0x400c1000, 0x80081104, 0x82082400, 0x0010b553,
+	0x50101000, 0x820c0500, 0x00000003, 0x0c01f806,
+	0x80081540, 0x44082000, 0x42000800, 0x00000021,
+	0x0401f156, 0x0010401d, 0x00104022, 0x00104027,
+	0x0010402c, 0x800408f0, 0x40040000, 0x82081500,
+	0x00ffffff, 0x1c01f000, 0x800408e0, 0x40040000,
+	0x82081500, 0xff00ffff, 0x1c01f000, 0x800408d0,
+	0x40040000, 0x82081500, 0xffff00ff, 0x1c01f000,
+	0x40040000, 0x82081500, 0xffffff00, 0x1c01f000,
+	0x59a80016, 0x80000540, 0x04000016, 0x4803c857,
+	0x42001000, 0x00104148, 0x0201f800, 0x00105f90,
+	0x59a80016, 0x82000580, 0x00000084, 0x0402000c,
+	0x59cc1006, 0x82081580, 0x11070000, 0x04020008,
+	0x4a035013, 0x00000001, 0x0401f8d2, 0x4a035014,
+	0x0000001a, 0x0401f804, 0x0401f002, 0x0401f8f2,
+	0x1c01f000, 0x82000540, 0x00000001, 0x0401fa3e,
+	0x4a035014, 0x0000001b, 0x83cca400, 0x00000006,
+	0x4200a800, 0x0010b552, 0x59a82016, 0x40100000,
+	0x8000b104, 0x40580800, 0x5450a800, 0x8050a000,
+	0x8054a800, 0x8058b040, 0x040207fc, 0x0401f113,
+	0x1c01f000, 0x1c01f000, 0x4803c856, 0x42003000,
+	0x00000004, 0x42004000, 0x0010b553, 0x599c2817,
+	0x8c142d14, 0x0402001f, 0x42001000, 0x00000003,
+	0x40200000, 0x80080400, 0x50000800, 0x82042580,
+	0xffffffff, 0x04020005, 0x80081040, 0x80183040,
+	0x040207f8, 0x0401f05e, 0x800811c0, 0x04020006,
+	0x82042580, 0x3fffffff, 0x04000058, 0x82040d40,
+	0xc0000000, 0x4200b000, 0x00000020, 0x42001800,
+	0x00000001, 0x40042000, 0x80102102, 0x04021021,
+	0x800c18c2, 0x8058b040, 0x040207fc, 0x0401f04b,
+	0x41781000, 0x40200000, 0x80080400, 0x50000800,
+	0x82042580, 0xffffffff, 0x04020005, 0x80081000,
+	0x80183040, 0x040207f8, 0x0401f040, 0x800811c0,
+	0x04020003, 0x82040d40, 0xc0000000, 0x4200b000,
+	0x00000001, 0x42001800, 0x80000000, 0x40042000,
+	0x801020c2, 0x04021007, 0x800c1902, 0x8058b000,
+	0x82580480, 0x00000021, 0x040017fa, 0x0401f02f,
+	0x40200000, 0x80082400, 0x50100000, 0x800c0540,
+	0x44002000, 0x59a80015, 0x84000540, 0x48035015,
+	0x40580000, 0x42002800, 0x00000020, 0x80142c80,
+	0x40080000, 0x42003800, 0x00000003, 0x801c0480,
+	0x800000ca, 0x80142d40, 0x82144c00, 0x0010210e,
+	0x50242800, 0x82142d00, 0x000000ff, 0x48175010,
+	0x4c040000, 0x40140800, 0x0201f800, 0x001015eb,
+	0x5c000800, 0x40001800, 0x500c0000, 0x80100540,
+	0x44001800, 0x59a80015, 0x84000540, 0x48035015,
+	0x4200a800, 0x0010b553, 0x4020a000, 0x4200b000,
+	0x00000004, 0x0201f800, 0x0010ab17, 0x82000540,
+	0x00000001, 0x0401f002, 0x80000580, 0x1c01f000,
+	0x4807c857, 0x480bc857, 0x4008b000, 0x83cca400,
+	0x00000007, 0x4200a800, 0x0010b553, 0x40541000,
+	0x0201f800, 0x0010ab17, 0x40041800, 0x41782000,
+	0x42000000, 0x00000003, 0x820c1c80, 0x00000020,
+	0x04001004, 0x80102000, 0x80000040, 0x0401f7fb,
+	0x40041800, 0x801021c0, 0x04000005, 0x820c1c80,
+	0x00000020, 0x80102040, 0x040207fd, 0x42002000,
+	0x00000001, 0x800c19c0, 0x04000004, 0x801020c2,
+	0x800c1840, 0x040207fe, 0x80083c00, 0x83cc2c00,
+	0x00000007, 0x80142c00, 0x50140000, 0x80102d00,
+	0x04020012, 0x80100540, 0x44003800, 0x82042400,
+	0x0010210e, 0x50102800, 0x82142d00, 0x000000ff,
+	0x48175010, 0x4c040000, 0x40140800, 0x0201f800,
+	0x001015eb, 0x5c000800, 0x59a80015, 0x84000540,
+	0x48035015, 0x80000580, 0x1c01f000, 0x4807c856,
+	0x42001000, 0x00008017, 0x59a8184e, 0x0201f800,
+	0x0010aa4f, 0x0201f800, 0x00103a3e, 0x1c01f000,
+	0x4807c856, 0x4200b000, 0x00000020, 0x83cca400,
+	0x00000007, 0x4200a800, 0x0010be21, 0x0201f000,
+	0x0010ab28, 0x4807c856, 0x0201f800, 0x00106ede,
+	0x42000800, 0x000000f7, 0x0401f8de, 0x497b2804,
+	0x497b2805, 0x497b281c, 0x497b281d, 0x4202d800,
+	0x00000001, 0x42006000, 0xbf7fffff, 0x42006800,
+	0x00018000, 0x0401f950, 0x42006000, 0xfffeffff,
+	0x41786800, 0x0401f94c, 0x497b504e, 0x42000800,
+	0x0000002d, 0x42001000, 0x001041bc, 0x0201f000,
+	0x00105f69, 0x4807c856, 0x0401ffe3, 0x497b5014,
+	0x497b5016, 0x1c01f000, 0x4807c856, 0x59a80005,
+	0x8c000506, 0x1c01f000, 0x4807c856, 0x42006000,
+	0xffffffff, 0x42006800, 0x00000028, 0x0401f136,
+	0x4807c856, 0x0401ffc2, 0x0201f800, 0x00106c55,
+	0x4df00000, 0x0201f800, 0x00106e21, 0x5c03e000,
+	0x02000800, 0x00106c4b, 0x59c400a4, 0x82000500,
+	0x0000000f, 0x82000580, 0x00000002, 0x0402000a,
+	0x42006000, 0xffffffff, 0x42006800, 0x00200000,
+	0x0401f921, 0x42006000, 0xffdfffff, 0x41786800,
+	0x0401f91d, 0x497b5014, 0x42000800, 0x000000f7,
+	0x0401f89c, 0x59c400a3, 0x82000500, 0xbf20bfff,
+	0x82000540, 0x0001c000, 0x480388a3, 0x84000520,
+	0x480388a3, 0x1c01f000, 0x497b5016, 0x59b400f5,
+	0x8c000500, 0x04020004, 0x82000540, 0x00000001,
+	0x480368f5, 0x800400c4, 0x82000400, 0x00002000,
+	0x4803910a, 0x59b400f6, 0x82000500, 0x00000018,
+	0x040207fd, 0x4a0368f0, 0x0010b54b, 0x42000000,
+	0x0010b552, 0x480368f1, 0x82040400, 0x0000dc00,
+	0x480368f3, 0x59c400a4, 0x82000500, 0x0000000f,
+	0x82000580, 0x00000008, 0x04020017, 0x4c5c0000,
+	0x4c600000, 0x59c4b805, 0x8c5cbd3a, 0x04020005,
+	0x42000000, 0x0010b818, 0x0201f800, 0x0010aa47,
+	0x4a038805, 0x02000000, 0x0201f800, 0x001019fe,
+	0x4000c000, 0x0201f800, 0x00101963, 0x4202d800,
+	0x00000001, 0x497b5014, 0x5c00c000, 0x5c00b800,
+	0x1c01f000, 0x59c8010b, 0x8c000502, 0x040007e2,
+	0x59c408a4, 0x82040d00, 0x0000000f, 0x82040d80,
+	0x0000000b, 0x04020005, 0x59a80814, 0x82040d40,
+	0x00002000, 0x0401f004, 0x59a80812, 0x82040d40,
+	0x00001000, 0x4807504e, 0x59a8084a, 0x800409c0,
+	0x04020007, 0x42000800, 0x000007d0, 0x42001000,
+	0x00104148, 0x0201f800, 0x0010606e, 0x1c01f000,
+	0x4807c856, 0x0401ff4e, 0x0201f800, 0x00106c55,
+	0x4df00000, 0x0201f800, 0x00106e21, 0x5c03e000,
+	0x02000800, 0x00106c4b, 0x59c400a4, 0x82000500,
+	0x0000000f, 0x82000580, 0x00000002, 0x0402000a,
+	0x42006000, 0xffffffff, 0x42006800, 0x00200000,
+	0x0401f8ad, 0x42006000, 0xffdfffff, 0x41786800,
+	0x0401f8a9, 0x0201f800, 0x00105141, 0x04000014,
+	0x0201f800, 0x00105151, 0x04020011, 0x4a035032,
+	0x0000aaaa, 0x4c040000, 0x0201f800, 0x0010162a,
+	0x59a8002a, 0x82000500, 0xffff0000, 0x80040540,
+	0x4803502a, 0x5c000800, 0x4a035033, 0x00000000,
+	0x0201f800, 0x001050a2, 0x0401f008, 0x4a03504c,
+	0x00000005, 0x42000000, 0x00000001, 0x0201f800,
+	0x00101590, 0x0401ff2c, 0x1c01f000, 0x0401f805,
+	0x42006000, 0xbf7f7fff, 0x41786800, 0x0401f086,
+	0x0201f800, 0x00105151, 0x04020005, 0x59c40006,
+	0x82000540, 0x000000f0, 0x48038806, 0x1c01f000,
+	0x800408d0, 0x59a80015, 0x8c000506, 0x04000006,
+	0x59a80010, 0x82000500, 0x000000ff, 0x80040540,
+	0x0401f003, 0x82040540, 0x000000f7, 0x480388a7,
+	0x1c01f000, 0x4807c856, 0x42000000, 0x0010b83b,
+	0x0201f800, 0x0010aa47, 0x42003000, 0x00000005,
+	0x4d3c0000, 0x4c180000, 0x42003000, 0x0000000d,
+	0x42027800, 0x00000002, 0x0401f038, 0x4807c856,
+	0x42000000, 0x0010b86b, 0x0201f800, 0x0010aa47,
+	0x42003000, 0x00000000, 0x4d3c0000, 0x4c180000,
+	0x42003000, 0x0000000f, 0x42027800, 0x00000002,
+	0x0401f02a, 0x4807c856, 0x42000000, 0x0010b86a,
+	0x0201f800, 0x0010aa47, 0x42003000, 0x00000003,
+	0x4d3c0000, 0x4c180000, 0x42003000, 0x0000000e,
+	0x42027800, 0x00000202, 0x0401f01c, 0x4807c856,
+	0x42000000, 0x0010b869, 0x0201f800, 0x0010aa47,
+	0x42003000, 0x00000004, 0x4d3c0000, 0x4c180000,
+	0x42003000, 0x00000010, 0x42027800, 0x00000202,
+	0x0401f00e, 0x4807c856, 0x42000000, 0x0010b83e,
+	0x0201f800, 0x0010aa47, 0x42003000, 0x00000001,
+	0x4d3c0000, 0x4c180000, 0x42003000, 0x0000000c,
+	0x42027800, 0x00000202, 0x42001800, 0x0000ffff,
+	0x42002000, 0x00000007, 0x0201f800, 0x00103aae,
+	0x5c003000, 0x4d400000, 0x0201f800, 0x0010a95d,
+	0x42028000, 0x0000002a, 0x0201f800, 0x00101fe5,
+	0x5c028000, 0x5c027800, 0x1c01f000, 0x4807c856,
+	0x04011000, 0x4a03c840, 0x0010b54b, 0x4a03c842,
+	0x00000040, 0x40000000, 0x040117ff, 0x42007800,
+	0x0010b54b, 0x46007800, 0x00000011, 0x803c7800,
+	0x4a007800, 0x220000ef, 0x4a007801, 0x000000ef,
+	0x4a007802, 0x01380000, 0x4a007803, 0x00000000,
+	0x4a007804, 0xffffffff, 0x4a007805, 0x00000000,
+	0x1c01f000, 0x59c400a3, 0x80300500, 0x80340540,
+	0x480388a3, 0x1c01f000, 0x4833c857, 0x59c400a3,
+	0x80300540, 0x480388a3, 0x80300580, 0x480388a3,
+	0x1c01f000, 0x4803c856, 0x04000004, 0x4a03504b,
+	0x00000001, 0x0401f002, 0x497b504b, 0x1c01f000,
+	0x4803c856, 0x59c80002, 0x80000540, 0x0400000a,
+	0x80000040, 0x04000008, 0x4a039005, 0x00000140,
+	0x42000000, 0x00000006, 0x80000040, 0x040207ff,
+	0x0401f7f4, 0x1c01f000, 0x4c5c0000, 0x4c600000,
+	0x59c4b805, 0x485fc856, 0x8c5cbd3a, 0x04020005,
+	0x42000000, 0x0010b818, 0x0201f800, 0x0010aa47,
+	0x4a038805, 0x02000000, 0x0201f800, 0x001019fe,
+	0x4000c000, 0x0201f800, 0x00101963, 0x4a038805,
+	0x04000000, 0x5c00c000, 0x5c00b800, 0x1c01f000,
+	0x497a6a00, 0x4937c857, 0x4a026c00, 0x00000707,
+	0x497a6801, 0x497a6808, 0x497a6809, 0x497a6806,
+	0x497a6807, 0x497a6c0b, 0x497a680c, 0x0201f800,
+	0x00103b25, 0x04020006, 0x5934080f, 0x59340010,
+	0x80040540, 0x02020800, 0x001005d8, 0x4a026a04,
+	0x00000100, 0x497a6a03, 0x59340402, 0x82000500,
+	0x000000ff, 0x48026c02, 0x497a6c04, 0x497a6a05,
+	0x497a6c05, 0x497a6811, 0x4d2c0000, 0x5934000d,
+	0x49466c03, 0x80025d40, 0x04000004, 0x0201f800,
+	0x001007fd, 0x497a680d, 0x5c025800, 0x599c0401,
+	0x48026a0b, 0x599c0208, 0x48026c12, 0x497a680a,
+	0x0201f000, 0x00104c62, 0x42000000, 0x00000005,
+	0x80000d80, 0x0401f02d, 0x0201f800, 0x00104a09,
+	0x04020017, 0x59a80026, 0x8c00050a, 0x04020010,
+	0x59340212, 0x82000500, 0x0000ff00, 0x4803c857,
+	0x0400000b, 0x59340a00, 0x8c040d1e, 0x02000000,
+	0x000201c4, 0x42000000, 0x00000029, 0x42000800,
+	0x00001000, 0x492fc857, 0x0401f018, 0x492fc857,
+	0x42000000, 0x00000028, 0x0401f012, 0x59a80805,
+	0x8c040d02, 0x04020003, 0x8c040d00, 0x04000004,
+	0x42000000, 0x00000004, 0x0401f00a, 0x42000000,
+	0x00000029, 0x59340a00, 0x8c040d1e, 0x04000005,
+	0x492fc857, 0x42000800, 0x00001000, 0x0401f003,
+	0x492fc857, 0x80000d80, 0x4803c857, 0x80028540,
+	0x1c01f000, 0x4803c857, 0x59a80005, 0x8c000500,
+	0x040207ec, 0x0201f800, 0x001049e7, 0x040207e4,
+	0x59340200, 0x8c00050e, 0x040007e1, 0x0201f000,
+	0x000201c4, 0x0201f800, 0x001047eb, 0x040007bf,
+	0x0201f000, 0x000201c8, 0x592c0206, 0x492fc857,
+	0x82000d80, 0x000007ff, 0x04020006, 0x4a025c0a,
+	0x00000030, 0x42026800, 0x0010b524, 0x0401f021,
+	0x82000c80, 0x000007f0, 0x04021046, 0x81ac0400,
+	0x50000000, 0x80026d40, 0x04000038, 0x0201f800,
+	0x001048e3, 0x04020038, 0x592c040a, 0x8c00050a,
+	0x04020014, 0x592e6009, 0x83300480, 0x0010d1c0,
+	0x0400103b, 0x41580000, 0x81300480, 0x04021038,
+	0x59300c06, 0x82040580, 0x00000009, 0x04020037,
+	0x4a025a06, 0x00000000, 0x497a5800, 0x59300008,
+	0x80000540, 0x04020018, 0x492e6008, 0x0401f010,
+	0x0201f800, 0x0002075a, 0x04000019, 0x592c0206,
+	0x49366009, 0x492e6008, 0x4a026406, 0x00000009,
+	0x497a6015, 0x49325809, 0x82000d80, 0x000007ff,
+	0x04020003, 0x4a026015, 0x00008000, 0x42027000,
+	0x00000043, 0x0201f800, 0x000207a1, 0x80000580,
+	0x0401f020, 0x40000800, 0x58040000, 0x80000d40,
+	0x040207fd, 0x492c0800, 0x0401f01a, 0x42000000,
+	0x0000002c, 0x0401f016, 0x42000000, 0x00000028,
+	0x0401f013, 0x59a80805, 0x82040500, 0x00000003,
+	0x04000004, 0x42000000, 0x00000004, 0x0401f00c,
+	0x42000000, 0x00000029, 0x0401f009, 0x42000000,
+	0x00000008, 0x0401f006, 0x82040580, 0x00000007,
+	0x040207fb, 0x42000000, 0x00000005, 0x80000540,
+	0x1c01f000, 0x492fc857, 0x592e8c06, 0x83440d80,
+	0x000007fc, 0x04000004, 0x83440480, 0x000007f0,
+	0x04021014, 0x0201f800, 0x00020245, 0x04020011,
+	0x0201f800, 0x001049f3, 0x04020011, 0x0201f800,
+	0x0002075a, 0x0400001c, 0x49366009, 0x492e6008,
+	0x4a026406, 0x0000000a, 0x42027000, 0x00000040,
+	0x0201f800, 0x000207a1, 0x80000580, 0x0401f011,
+	0x42000000, 0x00000028, 0x0401f00d, 0x0201f800,
+	0x00104a09, 0x040007fb, 0x59a80805, 0x82040d00,
+	0x00000003, 0x04000004, 0x42000000, 0x00000004,
+	0x0401f003, 0x42000000, 0x00000029, 0x80000540,
+	0x1c01f000, 0x42000000, 0x0000002c, 0x0401f7fc,
+	0x492fc857, 0x592e8c06, 0x4947c857, 0x83440c80,
+	0x00000800, 0x42000000, 0x0000000a, 0x04021176,
+	0x592c4207, 0x4823c857, 0x82200500, 0x0000000f,
+	0x0c01f001, 0x001043d5, 0x0010445d, 0x001044a9,
+	0x001044b4, 0x001044bf, 0x001043d1, 0x001043d1,
+	0x001043d1, 0x001044cf, 0x00104513, 0x00104530,
+	0x001043d1, 0x001043d1, 0x001043d1, 0x001043d1,
+	0x001043d1, 0x4803c857, 0x42000000, 0x0000000c,
+	0x0401f15d, 0x592c1008, 0x82081500, 0x00ffffff,
+	0x59a80010, 0x80084d80, 0x42000000, 0x00000010,
+	0x04000155, 0x0201f800, 0x00104919, 0x04000036,
+	0x4803c857, 0x82004d80, 0x0000001d, 0x0402001a,
+	0x0201f800, 0x00105755, 0x59340405, 0x4c000000,
+	0x0201f800, 0x001049e7, 0x5c000000, 0x04000004,
+	0x8c20450a, 0x04000028, 0x80000580, 0x44002800,
+	0x59340008, 0x48002802, 0x59340009, 0x48002801,
+	0x59340006, 0x48002804, 0x59340007, 0x48002803,
+	0x4200b000, 0x00000005, 0x0201f800, 0x0010955f,
+	0x0401f166, 0x4803c857, 0x82004d80, 0x0000001a,
+	0x04020003, 0x40101000, 0x0401f136, 0x4803c857,
+	0x82004d80, 0x0000001b, 0x04020003, 0x40181000,
+	0x0401f130, 0x4803c857, 0x82004d80, 0x0000001c,
+	0x04000131, 0x82004d80, 0x00000019, 0x42000000,
+	0x0000000a, 0x04000120, 0x42000000, 0x0000000a,
+	0x04020137, 0x59a80005, 0x8c000514, 0x0400001b,
+	0x0201f800, 0x001049e7, 0x04000018, 0x59340212,
+	0x82000500, 0x0000ff00, 0x42001000, 0x00000010,
+	0x0402000c, 0x42001000, 0x00000008, 0x59a80026,
+	0x8c000506, 0x04020009, 0x59340002, 0x82000500,
+	0x00ff0000, 0x82000580, 0x00ff0000, 0x04000007,
+	0x0201f800, 0x00104c6d, 0x42000000, 0x0000001c,
+	0x40181000, 0x04020107, 0x0201f800, 0x0002075a,
+	0x04000111, 0x49366009, 0x492e6008, 0x4a026406,
+	0x00000001, 0x8c20450a, 0x04000004, 0x592c0404,
+	0x8400055c, 0x48025c04, 0x4c200000, 0x4d3c0000,
+	0x42027800, 0x00001000, 0x0201f800, 0x0010203c,
+	0x5c027800, 0x5c004000, 0x8c204512, 0x0400000b,
+	0x599c0018, 0x8c000518, 0x04000008, 0x592c0009,
+	0x82000500, 0x00000380, 0x5934080a, 0x80040d40,
+	0x84040d54, 0x4806680a, 0x417a7800, 0x0401f914,
+	0x42000800, 0x00000003, 0x0401f91b, 0x42027000,
+	0x00000002, 0x0201f800, 0x000207a1, 0x80000580,
+	0x0401f10a, 0x0201f800, 0x00020245, 0x040200ec,
+	0x0201f800, 0x001049ed, 0x04000008, 0x0201f800,
+	0x001049e7, 0x040200ec, 0x417a7800, 0x417a6000,
+	0x0201f800, 0x001020a1, 0x59a80005, 0x8c000514,
+	0x0400001b, 0x0201f800, 0x001049e7, 0x04000018,
+	0x59340212, 0x82000500, 0x0000ff00, 0x42001000,
+	0x00000010, 0x0402000c, 0x42001000, 0x00000008,
+	0x59a80026, 0x8c000506, 0x04020009, 0x59340002,
+	0x82000500, 0x00ff0000, 0x82000580, 0x00ff0000,
+	0x04000007, 0x0201f800, 0x00104c6d, 0x42000000,
+	0x0000001c, 0x40181000, 0x040200b2, 0x0201f800,
+	0x0002075a, 0x040000bc, 0x5934080a, 0x8c204512,
+	0x0400000c, 0x599c0018, 0x8c000518, 0x04000009,
+	0x592c0009, 0x82000500, 0x00000380, 0x82041500,
+	0xfffffc7f, 0x80080d40, 0x84040d54, 0x0401f002,
+	0x84040d14, 0x4806680a, 0x49366009, 0x492e6008,
+	0x4a026406, 0x00000001, 0x417a7800, 0x0401f8c8,
+	0x42000800, 0x00000005, 0x0401f8cf, 0x42027000,
+	0x00000003, 0x0201f800, 0x000207a1, 0x80000580,
+	0x0401f0be, 0x0201f800, 0x00020245, 0x040200a0,
+	0x0201f800, 0x001049fc, 0x040200a3, 0x0201f800,
+	0x00109517, 0x04000094, 0x80000580, 0x0401f0b3,
+	0x0201f800, 0x00020245, 0x04020095, 0x0201f800,
+	0x001049fc, 0x04020098, 0x0201f800, 0x001090e6,
+	0x04000089, 0x80000580, 0x0401f0a8, 0x0201f800,
+	0x00020245, 0x0402008a, 0x83444d80, 0x000007fe,
+	0x42000000, 0x0000000a, 0x0402006b, 0x0201f800,
+	0x001049e7, 0x04020088, 0x0201f800, 0x0010952f,
+	0x04000079, 0x80000580, 0x0401f098, 0x82200500,
+	0x00000070, 0x04020005, 0x8c20450e, 0x42000000,
+	0x0000000c, 0x0402005c, 0x8c20450a, 0x0400000d,
+	0x4d3c0000, 0x42027800, 0x00001000, 0x8c20450e,
+	0x04020002, 0x853e7d56, 0x82200500, 0x000000a0,
+	0x0201f800, 0x001049d3, 0x5c027800, 0x0401f07f,
+	0x0201f800, 0x00020245, 0x04020065, 0x8c204508,
+	0x04000010, 0x4d3c0000, 0x42027800, 0x00001000,
+	0x8c20450e, 0x04020002, 0x853e7d56, 0x82200500,
+	0x00000090, 0x0201f800, 0x001049bb, 0x5c027800,
+	0x42000000, 0x0000000a, 0x0402003b, 0x0401f06b,
+	0x836c0580, 0x00000003, 0x42000800, 0x00000007,
+	0x0402000f, 0x0201f800, 0x001049f3, 0x04000007,
+	0x4c000000, 0x0201f800, 0x00104a1f, 0x5c000000,
+	0x0400004d, 0x0401f05d, 0x0201f800, 0x001094c5,
+	0x04000007, 0x80000580, 0x0401f05c, 0x0201f800,
+	0x00104a1f, 0x04000051, 0x0401f054, 0x0201f800,
+	0x00104a1f, 0x04000034, 0x0401f050, 0x0201f800,
+	0x00020245, 0x04020036, 0x836c0580, 0x00000003,
+	0x04020040, 0x8c204508, 0x04000006, 0x417a7800,
+	0x417a6000, 0x0201f800, 0x001020a1, 0x0401f043,
+	0x0201f800, 0x001049ed, 0x04000008, 0x0201f800,
+	0x001049e7, 0x0402002c, 0x417a7800, 0x417a6000,
+	0x0201f800, 0x001020a1, 0x480bc856, 0x0201f800,
+	0x00109332, 0x04000018, 0x80000580, 0x0401f037,
+	0x0401f7e3, 0x480bc857, 0x42000800, 0x00000019,
+	0x40001000, 0x4200b000, 0x00000002, 0x0401f00a,
+	0x480bc857, 0x40000800, 0x4200b000, 0x00000002,
+	0x0401f005, 0x480bc857, 0x40000800, 0x4200b000,
+	0x00000001, 0x480bc857, 0x42028000, 0x00000031,
+	0x0401f020, 0x480bc857, 0x42000800, 0x00000003,
+	0x4200b000, 0x00000001, 0x0401f7f7, 0x480bc857,
+	0x42000800, 0x0000000a, 0x4200b000, 0x00000001,
+	0x0401f7f1, 0x480bc857, 0x42000800, 0x00000009,
+	0x40001000, 0x4200b000, 0x00000002, 0x0401f7ea,
+	0x480bc857, 0x42000800, 0x00000007, 0x4200b000,
+	0x00000001, 0x0401f7e4, 0x480bc857, 0x4200b000,
+	0x00000001, 0x0401f7e0, 0x80028580, 0x4178b000,
+	0x82000540, 0x00000001, 0x1c01f000, 0x4937c857,
+	0x59326809, 0x59341200, 0x813e79c0, 0x04000003,
+	0x84081540, 0x0401f002, 0x84081500, 0x480a6a00,
+	0x1c01f000, 0x59326809, 0x5c000000, 0x4c000000,
+	0x4803c857, 0x4937c857, 0x82040580, 0x00000006,
+	0x04020004, 0x42000000, 0x00000606, 0x0401f021,
+	0x82040580, 0x00000004, 0x04020004, 0x42000000,
+	0x00000404, 0x0401f01b, 0x82040580, 0x00000007,
+	0x42000000, 0x00000707, 0x04000016, 0x82040580,
+	0x00000003, 0x42000000, 0x00000703, 0x04000011,
+	0x82040580, 0x00000005, 0x42000000, 0x00000405,
+	0x0400000c, 0x82040580, 0x00000009, 0x42000000,
+	0x00000409, 0x04000007, 0x82040580, 0x0000000b,
+	0x42000000, 0x0000070b, 0x02020800, 0x001005d8,
+	0x4803c857, 0x48026c00, 0x82040d80, 0x00000006,
+	0x04020005, 0x59341404, 0x800811c0, 0x02000800,
+	0x001005d8, 0x1c01f000, 0x5c000000, 0x4c000000,
+	0x4803c857, 0x4947c857, 0x481bc857, 0x83440480,
+	0x00000800, 0x04021034, 0x83441400, 0x0010ac00,
+	0x50080000, 0x80026d40, 0x04020011, 0x4c180000,
+	0x4d2c0000, 0x0201f800, 0x001007d3, 0x412e6800,
+	0x5c025800, 0x5c003000, 0x04000027, 0x45341000,
+	0x497a680d, 0x497a6810, 0x497a680f, 0x497a680e,
+	0x4c180000, 0x0401fcf3, 0x5c003000, 0x59340a12,
+	0x4c040000, 0x0201f800, 0x0010513b, 0x5c000800,
+	0x04000009, 0x82180500, 0x00ffff00, 0x04000008,
+	0x59a81010, 0x82081500, 0x00ffff00, 0x80080580,
+	0x04000003, 0x80000580, 0x0401f004, 0x82180500,
+	0x000000ff, 0x800000d0, 0x80040d80, 0x04000003,
+	0x4803c857, 0x48026a12, 0x59340002, 0x80180580,
+	0x04000003, 0x481bc857, 0x481a6802, 0x80000580,
+	0x1c01f000, 0x4803c856, 0x82000540, 0x00000001,
+	0x0401f7fc, 0x4947c857, 0x83440480, 0x00000800,
+	0x04021011, 0x83441400, 0x0010ac00, 0x50080000,
+	0x80026d40, 0x0400000b, 0x0401fbf9, 0x0402000a,
+	0x59a80005, 0x8c000502, 0x04000004, 0x59340200,
+	0x8c00050e, 0x04000004, 0x82000540, 0x00000001,
+	0x1c01f000, 0x80000580, 0x0401f7fe, 0x5c000000,
+	0x4c000000, 0x4803c857, 0x4947c857, 0x4d2c0000,
+	0x4d300000, 0x83440480, 0x00000800, 0x04021024,
+	0x83441400, 0x0010ac00, 0x50080000, 0x80026d40,
+	0x0400001b, 0x45781000, 0x5934000d, 0x80025d40,
+	0x02020800, 0x001007fd, 0x59366011, 0x813261c0,
+	0x0400000e, 0x4c640000, 0x5930c800, 0x59325808,
+	0x0201f800, 0x00109037, 0x02020800, 0x001007fd,
+	0x0201f800, 0x0002077d, 0x82666540, 0x00000000,
+	0x040207f6, 0x5c00c800, 0x0201f800, 0x00104c62,
+	0x41365800, 0x0201f800, 0x001007f5, 0x80000580,
+	0x5c026000, 0x5c025800, 0x1c01f000, 0x82000540,
+	0x00000001, 0x0401f7fb, 0x4937c857, 0x4c580000,
+	0x59cc0001, 0x82000500, 0x00ffffff, 0x48026802,
+	0x497a6c01, 0x497a6a01, 0x59340200, 0x84000502,
+	0x48026a00, 0x0201f800, 0x0010513b, 0x04020017,
+	0x59340403, 0x82000580, 0x000007fe, 0x04000005,
+	0x59a80026, 0x8c00050a, 0x04020010, 0x0401f008,
+	0x59cc0408, 0x8c000518, 0x0400000c, 0x59cc0009,
+	0x48035035, 0x59cc000a, 0x48035036, 0x59cc0207,
+	0x80000540, 0x04020003, 0x42000000, 0x00000001,
+	0x48038893, 0x4803501e, 0x59cc0a09, 0x82040d00,
+	0x00000010, 0x59cc0408, 0x82000500, 0x00000020,
+	0x04000002, 0x84040d40, 0x5934000a, 0x82000500,
+	0xffffffee, 0x80040540, 0x4802680a, 0x83cca400,
+	0x0000000b, 0x8334ac00, 0x00000006, 0x4200b000,
+	0x00000002, 0x0201f800, 0x0010ab17, 0x83cca400,
+	0x0000000d, 0x8334ac00, 0x00000008, 0x4200b000,
+	0x00000002, 0x0201f800, 0x0010ab17, 0x59cc0a18,
+	0x82040480, 0x00000800, 0x0402100c, 0x82040480,
+	0x00000400, 0x04001004, 0x42000800, 0x00000400,
+	0x0401f006, 0x82040480, 0x00000200, 0x04001003,
+	0x42000800, 0x00000200, 0x48066a04, 0x59340403,
+	0x82000580, 0x000007fe, 0x04020003, 0x59cc0a08,
+	0x48066a04, 0x42000800, 0x00000004, 0x59cc1207,
+	0x800811c0, 0x04000005, 0x82080480, 0x00000004,
+	0x04021002, 0x40080800, 0x48066c04, 0x5c00b000,
+	0x1c01f000, 0x4937c857, 0x59a80026, 0x8c000508,
+	0x04000004, 0x84000556, 0x4803c857, 0x48035026,
+	0x59cc0207, 0x4803c857, 0x48026a05, 0x59cc020a,
+	0x4803c857, 0x48026c05, 0x59341200, 0x599c0818,
+	0x5934180a, 0x4807c857, 0x480bc857, 0x480fc857,
+	0x59cc2006, 0x82102500, 0xff000000, 0x82102580,
+	0x02000000, 0x04000007, 0x8c00050e, 0x04000009,
+	0x8c0c1d14, 0x04000003, 0x8c0c1d0e, 0x04000005,
+	0x8c040d18, 0x04000003, 0x8408154a, 0x0401f002,
+	0x8408150a, 0x8c000510, 0x04000009, 0x8c0c1d14,
+	0x04000003, 0x8c0c1d10, 0x04000005, 0x8c040d18,
+	0x04000003, 0x8408154e, 0x0401f002, 0x8408150e,
+	0x8c000512, 0x04000009, 0x8c0c1d14, 0x04000003,
+	0x8c0c1d12, 0x04000005, 0x8c040d18, 0x04000003,
+	0x8408155c, 0x0401f002, 0x8408151c, 0x480a6a00,
+	0x1c01f000, 0x4803c856, 0x4c5c0000, 0x4d2c0000,
+	0x4c580000, 0x5934000d, 0x80025d40, 0x04000029,
+	0x592c0003, 0x82000480, 0x00000008, 0x0400100b,
+	0x412cb800, 0x592c0001, 0x80025d40, 0x040207f9,
+	0x0201f800, 0x001007e4, 0x04000037, 0x492fc857,
+	0x492cb801, 0x0401f020, 0x832c0c00, 0x00000004,
+	0x4200b000, 0x00000008, 0x50040000, 0x82000580,
+	0xffffffff, 0x04020006, 0x80041000, 0x50080000,
+	0x82000580, 0xffffffff, 0x04000007, 0x82040c00,
+	0x00000002, 0x8058b040, 0x040207f4, 0x0201f800,
+	0x001005d8, 0x45480800, 0x454c1000, 0x592c1803,
+	0x800c1800, 0x480e5803, 0x480fc857, 0x0401f014,
+	0x0201f800, 0x001007e4, 0x04000017, 0x492fc857,
+	0x492e680d, 0x497a5802, 0x4a025803, 0x00000001,
+	0x494a5804, 0x494e5805, 0x832c0c00, 0x00000006,
+	0x4200b000, 0x0000000e, 0x46000800, 0xffffffff,
+	0x80040800, 0x8058b040, 0x040207fc, 0x82000540,
+	0x00000001, 0x5c00b000, 0x5c025800, 0x5c00b800,
+	0x1c01f000, 0x80000580, 0x0401f7fb, 0x4803c856,
+	0x4d3c0000, 0x4d2c0000, 0x5934000d, 0x80025d40,
+	0x0400001f, 0x592c0002, 0x80000540, 0x0402001f,
+	0x412e7800, 0x0401f8ce, 0x0402001c, 0x46000800,
+	0xffffffff, 0x46001000, 0xffffffff, 0x4813c857,
+	0x480fc857, 0x580c0003, 0x82000c80, 0x00000002,
+	0x04021014, 0x480fc857, 0x400c0000, 0x812c0580,
+	0x04020004, 0x580c0001, 0x4802680d, 0x0401f003,
+	0x580c0001, 0x48002001, 0x400e5800, 0x0201f800,
+	0x001007f4, 0x82000540, 0x00000001, 0x5c025800,
+	0x5c027800, 0x1c01f000, 0x80000580, 0x0401f7fc,
+	0x80000040, 0x48001803, 0x4803c857, 0x0401f7f6,
+	0x0201f800, 0x00020086, 0x59300007, 0x8400054e,
+	0x48026007, 0x592c1a04, 0x820c1d00, 0x000000ff,
+	0x820c0580, 0x00000048, 0x04000013, 0x0201f000,
+	0x0002028e, 0x8c000500, 0x02020800, 0x000200e5,
+	0x4a026203, 0x00000002, 0x592c1a04, 0x820c1d00,
+	0x000000ff, 0x820c0580, 0x00000018, 0x02000000,
+	0x0002028e, 0x820c0580, 0x00000048, 0x02020000,
+	0x0002028e, 0x42000800, 0x80000804, 0x0201f800,
+	0x00106721, 0x0201f000, 0x00020297, 0x4a025a06,
+	0x00000008, 0x0201f000, 0x000202da, 0x4a025a06,
+	0x00000029, 0x0201f000, 0x000202da, 0x4a025a06,
+	0x0000002a, 0x0201f000, 0x000202da, 0x4a025a06,
+	0x00000028, 0x0201f000, 0x000202da, 0x4943c857,
+	0x4d440000, 0x4d340000, 0x4d2c0000, 0x4c580000,
+	0x4200b000, 0x000007f0, 0x417a8800, 0x0201f800,
+	0x00020245, 0x0402000d, 0x8d3e7d14, 0x04000005,
+	0x59340212, 0x82000500, 0x0000ff00, 0x04000007,
+	0x8d3e7d06, 0x04000004, 0x59340200, 0x8c00050e,
+	0x04020002, 0x0401f813, 0x81468800, 0x8058b040,
+	0x040207ef, 0x83440480, 0x00000800, 0x04021008,
+	0x8d3e7d02, 0x04000006, 0x42028800, 0x000007f0,
+	0x4200b000, 0x00000010, 0x0401f7e5, 0x5c00b000,
+	0x5c025800, 0x5c026800, 0x5c028800, 0x1c01f000,
+	0x4d2c0000, 0x41783000, 0x5936580f, 0x812e59c0,
+	0x04000029, 0x592c0204, 0x82000500, 0x000000ff,
+	0x82000580, 0x00000012, 0x04000020, 0x8d3e7d00,
+	0x04000003, 0x0401f83c, 0x0402001c, 0x592c2000,
+	0x497a5800, 0x801831c0, 0x04020009, 0x59340010,
+	0x812c0580, 0x04020004, 0x497a680f, 0x497a6810,
+	0x0401f008, 0x4812680f, 0x0401f006, 0x48103000,
+	0x59340010, 0x812c0580, 0x04020002, 0x481a6810,
+	0x4a025a04, 0x00000103, 0x49425a06, 0x497a5c09,
+	0x0201f800, 0x001091c6, 0x0201f800, 0x000202da,
+	0x40125800, 0x0401f7da, 0x412c3000, 0x592e5800,
+	0x0401f7d7, 0x5c025800, 0x1c01f000, 0x4803c856,
+	0x41781800, 0x5934000f, 0x80025d40, 0x04000010,
+	0x592c0005, 0x80200580, 0x592c0000, 0x04000003,
+	0x412c1800, 0x0401f7f9, 0x497a5800, 0x800c19c0,
+	0x04000008, 0x48001800, 0x80000540, 0x04020004,
+	0x480e6810, 0x82000540, 0x00000001, 0x1c01f000,
+	0x4802680f, 0x80000540, 0x040207fd, 0x497a6810,
+	0x0401f7f9, 0x592c0008, 0x81480580, 0x04020003,
+	0x592c0009, 0x814c0580, 0x1c01f000, 0x4803c856,
+	0x4c580000, 0x413c1800, 0x400c2000, 0x593c0002,
+	0x80000540, 0x04020018, 0x4200b000, 0x00000008,
+	0x820c0c00, 0x00000004, 0x50040000, 0x81480580,
+	0x04020005, 0x80041000, 0x50080000, 0x814c0580,
+	0x0400000d, 0x82040c00, 0x00000002, 0x8058b040,
+	0x040207f6, 0x400c2000, 0x580c0001, 0x80001d40,
+	0x040207ee, 0x82000540, 0x00000001, 0x5c00b000,
+	0x1c01f000, 0x80000580, 0x0401f7fd, 0x4937c857,
+	0x4c580000, 0x4d2c0000, 0x5934000d, 0x80025d40,
+	0x04020016, 0x0201f800, 0x001007e4, 0x04000010,
+	0x492e680d, 0x4a025802, 0x00000001, 0x497a5803,
+	0x832c0c00, 0x00000004, 0x4200b000, 0x00000010,
+	0x46000800, 0xffffffff, 0x80040800, 0x8058b040,
+	0x040207fc, 0x82000540, 0x00000001, 0x5c025800,
+	0x5c00b000, 0x1c01f000, 0x4d2c0000, 0x592e5801,
+	0x0201f800, 0x001007fd, 0x5c025800, 0x0401f7ea,
+	0x4d2c0000, 0x5936580d, 0x812e59c0, 0x04000007,
+	0x4937c857, 0x497a680d, 0x0201f800, 0x001007fd,
+	0x82000540, 0x00000001, 0x5c025800, 0x1c01f000,
+	0x59340405, 0x4937c857, 0x4803c857, 0x8c000508,
+	0x1c01f000, 0x4803c856, 0x0201f800, 0x0010513b,
+	0x04000011, 0x59a80815, 0x8c040d04, 0x0402000e,
+	0x59a80826, 0x8c040d06, 0x0400000b, 0x83ac0400,
+	0x000007fe, 0x50000000, 0x80026d40, 0x04000006,
+	0x0401f9a7, 0x04020004, 0x59340200, 0x8400055a,
+	0x48026a00, 0x599c0017, 0x8c000508, 0x04000015,
+	0x4200b000, 0x000007f0, 0x417a8800, 0x0201f800,
+	0x00020245, 0x0402000c, 0x0401f999, 0x0402000a,
+	0x59a80010, 0x59340802, 0x80040580, 0x82000500,
+	0x00ffff00, 0x04020004, 0x59340200, 0x8400055a,
+	0x48026a00, 0x81468800, 0x8058b040, 0x040207f0,
+	0x0401f884, 0x04000003, 0x59a80836, 0x0401f006,
+	0x599c0017, 0x8c000508, 0x04000007, 0x42000800,
+	0x000007d0, 0x42001000, 0x00104876, 0x0201f800,
+	0x0010606e, 0x1c01f000, 0x4803c856, 0x4d340000,
+	0x4d440000, 0x4d3c0000, 0x4c580000, 0x42001000,
+	0x00104876, 0x0201f800, 0x00105f90, 0x59a80826,
+	0x8c040d06, 0x04000015, 0x0401f86a, 0x04000013,
+	0x83ae6c00, 0x000007fe, 0x51366800, 0x59340200,
+	0x8400051a, 0x48026a00, 0x599c0017, 0x8c000508,
+	0x04000007, 0x42000800, 0x000007d0, 0x42001000,
+	0x00104876, 0x0201f800, 0x0010606e, 0x0201f800,
+	0x00101e45, 0x0401f027, 0x4200b000, 0x000007f0,
+	0x80028d80, 0x0201f800, 0x00020245, 0x0402001e,
+	0x59340200, 0x8c00051a, 0x0400001b, 0x59368c03,
+	0x417a7800, 0x42028000, 0x00000029, 0x41783000,
+	0x0201f800, 0x0010a446, 0x59340200, 0x84000558,
+	0x8400051a, 0x48026a00, 0x4937c857, 0x4a026c00,
+	0x00000707, 0x42028000, 0x00000029, 0x0201f800,
+	0x00106ab4, 0x417a7800, 0x0201f800, 0x001067fd,
+	0x80000d80, 0x0201f800, 0x0010a2ff, 0x0201f800,
+	0x00106c4b, 0x81468800, 0x8058b040, 0x040207de,
+	0x5c00b000, 0x5c027800, 0x5c028800, 0x5c026800,
+	0x1c01f000, 0x4933c857, 0x59303809, 0x581c0200,
+	0x8400051a, 0x48003a00, 0x1c01f000, 0x4803c856,
+	0x42026800, 0x0010b524, 0x497a680e, 0x42028800,
+	0x000007ff, 0x0201f800, 0x001042b4, 0x4937c857,
+	0x4a026c00, 0x00000606, 0x4a026802, 0x00ffffff,
+	0x4a026a04, 0x00000200, 0x4a026c04, 0x00000002,
+	0x1c01f000, 0x59300009, 0x50000000, 0x4933c857,
+	0x4803c857, 0x8c00050e, 0x1c01f000, 0x59300009,
+	0x50000000, 0x8c00050a, 0x1c01f000, 0x4933c856,
+	0x0401f90f, 0x04000006, 0x59340400, 0x82000d00,
+	0x000000ff, 0x82041580, 0x00000005, 0x1c01f000,
+	0x4d340000, 0x83ac0400, 0x000007fe, 0x50000000,
+	0x80026d40, 0x04000003, 0x59340200, 0x8c00051a,
+	0x5c026800, 0x1c01f000, 0x4937c857, 0x493fc857,
+	0x59340403, 0x81ac0400, 0x50000000, 0x81340580,
+	0x02020800, 0x001005d8, 0x59341200, 0x813e79c0,
+	0x04000003, 0x8408155e, 0x0401f002, 0x8408151e,
+	0x480a6a00, 0x1c01f000, 0x4937c857, 0x0201f800,
+	0x0010210a, 0x04000006, 0x59a80835, 0x42001000,
+	0x00104910, 0x0201f800, 0x0010606e, 0x1c01f000,
+	0x4937c857, 0x42001000, 0x00104910, 0x0201f800,
+	0x00105f90, 0x59a81026, 0x84081512, 0x480b5026,
+	0x1c01f000, 0x4c380000, 0x4c340000, 0x4c240000,
+	0x4c600000, 0x4008c000, 0x83440480, 0x00000800,
+	0x04021045, 0x80002d80, 0x41442000, 0x83447400,
+	0x0010ac00, 0x4200b000, 0x000007f0, 0x83444c80,
+	0x000007f0, 0x04001003, 0x4200b000, 0x00000010,
+	0x50380000, 0x80000540, 0x0402001e, 0x41440000,
+	0x80100580, 0x04020043, 0x40102800, 0x82104c80,
+	0x000007f0, 0x04001015, 0x82104d80, 0x000007fc,
+	0x04020005, 0x82604d80, 0x00fffffc, 0x0402002a,
+	0x0401f00e, 0x82104d80, 0x000007fd, 0x04020005,
+	0x82604d80, 0x00fffffd, 0x04020023, 0x0401f007,
+	0x82104d80, 0x000007ff, 0x0402001f, 0x82604d80,
+	0x00ffffff, 0x0402001c, 0x84142d5e, 0x0401f029,
+	0x40006800, 0x58343002, 0x82183500, 0x00ffffff,
+	0x40180000, 0x80600580, 0x04020019, 0x40100000,
+	0x81440580, 0x0402000a, 0x40366800, 0x8c204508,
+	0x04000053, 0x0401ff8a, 0x04020051, 0x4947c857,
+	0x42000000, 0x0000001d, 0x0401f04e, 0x4947c857,
+	0x480bc857, 0x4823c857, 0x42000000, 0x0000001a,
+	0x0401f048, 0x4947c857, 0x4863c857, 0x4813c857,
+	0x42000000, 0x00000019, 0x0401f042, 0x40100000,
+	0x81440580, 0x04020007, 0x58343002, 0x4947c857,
+	0x481bc857, 0x42000000, 0x0000001b, 0x0401f039,
+	0x80102000, 0x80387000, 0x83444c80, 0x000007f0,
+	0x04001009, 0x82104d80, 0x00000800, 0x0402000c,
+	0x42002000, 0x000007f0, 0x42007000, 0x0010b3f0,
+	0x0401f007, 0x82104d80, 0x000007f0, 0x04020004,
+	0x41782000, 0x42007000, 0x0010ac00, 0x8058b040,
+	0x040207a4, 0x801429c0, 0x04020007, 0x0201f800,
+	0x001005d8, 0x4947c857, 0x42000000, 0x0000000a,
+	0x0401f01c, 0x4d2c0000, 0x4c180000, 0x40603000,
+	0x0401fc12, 0x4947c857, 0x4937c857, 0x5c003000,
+	0x5c025800, 0x040207f4, 0x497a6a12, 0x59a80026,
+	0x8c00050a, 0x0402000d, 0x82600500, 0x00ffff00,
+	0x04000006, 0x59a84810, 0x82244d00, 0x00ffff00,
+	0x80240580, 0x04020005, 0x82600500, 0x000000ff,
+	0x800000d0, 0x48026a12, 0x48626802, 0x80000580,
+	0x80000540, 0x5c00c000, 0x5c004800, 0x5c006800,
+	0x5c007000, 0x1c01f000, 0x5934000f, 0x5934140b,
+	0x80081040, 0x04001002, 0x480a6c0b, 0x80000540,
+	0x02020800, 0x00020253, 0x1c01f000, 0x4803c857,
+	0x4947c857, 0x4c300000, 0x82006500, 0x00000030,
+	0x04000006, 0x4c000000, 0x0201f800, 0x0010942a,
+	0x5c000000, 0x0402000b, 0x8c00050e, 0x04000006,
+	0x0201f800, 0x00020245, 0x04020006, 0x4937c857,
+	0x0401fc2f, 0x80000580, 0x5c006000, 0x1c01f000,
+	0x82000540, 0x00000001, 0x0401f7fc, 0x4803c857,
+	0x4c580000, 0x4d440000, 0x40001000, 0x80000d80,
+	0x4200b000, 0x000007f0, 0x4c040000, 0x40068800,
+	0x4c080000, 0x40080000, 0x0401ffdd, 0x5c001000,
+	0x5c000800, 0x80040800, 0x8058b040, 0x040207f7,
+	0x5c028800, 0x5c00b000, 0x1c01f000, 0x4c5c0000,
+	0x59340400, 0x8200bd80, 0x00000606, 0x5c00b800,
+	0x1c01f000, 0x4c5c0000, 0x59340400, 0x8200bd80,
+	0x00000404, 0x5c00b800, 0x1c01f000, 0x4c5c0000,
+	0x59340400, 0x8200bd80, 0x00000404, 0x04000003,
+	0x8200bd80, 0x00000606, 0x5c00b800, 0x1c01f000,
+	0x4c5c0000, 0x4c600000, 0x59340400, 0x8200bd00,
+	0x0000ff00, 0x825cc580, 0x00000400, 0x04000003,
+	0x825cc580, 0x00000600, 0x5c00c000, 0x5c00b800,
+	0x1c01f000, 0x4c5c0000, 0x59340400, 0x82000500,
+	0x000000ff, 0x8200bd80, 0x00000003, 0x04000003,
+	0x8200bd80, 0x00000005, 0x5c00b800, 0x1c01f000,
+	0x4c5c0000, 0x59340400, 0x82000500, 0x0000ff00,
+	0x8400b9c0, 0x805c0580, 0x4937c857, 0x4803c857,
+	0x48026c00, 0x5c00b800, 0x1c01f000, 0x4c040000,
+	0x4c080000, 0x592c0207, 0x8c00050c, 0x0400000f,
+	0x592e8c06, 0x82000500, 0x00000080, 0x84000548,
+	0x4d3c0000, 0x42027800, 0x00001000, 0x0401ff90,
+	0x5c027800, 0x82000540, 0x00000001, 0x5c001000,
+	0x5c000800, 0x1c01f000, 0x80000580, 0x0401f7fc,
+	0x592c040b, 0x82000500, 0x0000e000, 0x82000580,
+	0x00006000, 0x04000019, 0x836c0580, 0x00000003,
+	0x04000016, 0x836c0580, 0x00000002, 0x040200ff,
+	0x59a80026, 0x82000d00, 0x00000038, 0x04020005,
+	0x59a80832, 0x800409c0, 0x0400000c, 0x0401f0f7,
+	0x82000d00, 0x00000003, 0x82040d80, 0x00000003,
+	0x040200f2, 0x82000d00, 0x00000028, 0x04020003,
+	0x8c00050c, 0x040000ed, 0x592c100a, 0x82080500,
+	0xff000000, 0x040200ce, 0x59a80010, 0x80080580,
+	0x040000c8, 0x592c0c0b, 0x82040d00, 0x0000e000,
+	0x82040480, 0x00008000, 0x040210c8, 0x592e8c06,
+	0x83440480, 0x00000800, 0x04001007, 0x83440580,
+	0x0000ffff, 0x040200af, 0x800409c0, 0x040200f7,
+	0x0401f0ac, 0x800409c0, 0x040200f4, 0x41784000,
+	0x0401fead, 0x040200db, 0x42027000, 0x00000053,
+	0x592c2409, 0x82100500, 0xffffff00, 0x040200aa,
+	0x4813c857, 0x592c000c, 0x800001c0, 0x04000083,
+	0x82100580, 0x00000004, 0x040000a0, 0x82100580,
+	0x00000051, 0x0400009d, 0x82100580, 0x00000003,
+	0x04000016, 0x82100580, 0x00000020, 0x0400004b,
+	0x82100580, 0x00000024, 0x04000042, 0x82100580,
+	0x00000021, 0x04000042, 0x82100580, 0x00000050,
+	0x04000037, 0x82100580, 0x00000052, 0x04000031,
+	0x82100580, 0x00000005, 0x0402006b, 0x42027000,
+	0x00000001, 0x0401f01b, 0x42027000, 0x00000002,
+	0x59a80005, 0x8c000514, 0x04000016, 0x0401ff4c,
+	0x04000014, 0x59340212, 0x82000500, 0x0000ff00,
+	0x42001000, 0x00000010, 0x0402000c, 0x59a80026,
+	0x8c000506, 0x0402006f, 0x42001000, 0x00000008,
+	0x59340002, 0x82000500, 0x00ff0000, 0x82000580,
+	0x00ff0000, 0x04000003, 0x0401f9bf, 0x04020065,
+	0x0201f800, 0x0002075a, 0x0400007e, 0x4a026406,
+	0x00000010, 0x49366009, 0x42000800, 0x00000003,
+	0x83380580, 0x00000002, 0x04000003, 0x42000800,
+	0x0000000b, 0x0201f800, 0x00104571, 0x0401f044,
+	0x42027000, 0x00000000, 0x0401f003, 0x42027000,
+	0x00000004, 0x0401ff37, 0x04020071, 0x0401f036,
+	0x42027000, 0x00000033, 0x0401f006, 0x42027000,
+	0x00000005, 0x0401f003, 0x42027000, 0x00000003,
+	0x0401ff23, 0x04020066, 0x59a80005, 0x8c000514,
+	0x04000016, 0x0401ff12, 0x04000014, 0x59340212,
+	0x82000500, 0x0000ff00, 0x42001000, 0x00000010,
+	0x0402000c, 0x59a80026, 0x8c000506, 0x04020035,
+	0x42001000, 0x00000008, 0x59340002, 0x82000500,
+	0x00ff0000, 0x82000580, 0x00ff0000, 0x04000003,
+	0x0401f985, 0x0402002b, 0x0201f800, 0x0002075a,
+	0x04000044, 0x4a026406, 0x00000010, 0x49366009,
+	0x42000800, 0x00000005, 0x83380580, 0x00000003,
+	0x04000003, 0x42000800, 0x00000009, 0x0201f800,
+	0x00104571, 0x0401f00a, 0x82102580, 0x00000011,
+	0x0402002d, 0x0201f800, 0x0002075a, 0x04000031,
+	0x4a026406, 0x00000010, 0x49366009, 0x492e6008,
+	0x49325808, 0x813669c0, 0x04000007, 0x592c0c0b,
+	0x8c040d18, 0x04000004, 0x59340200, 0x84000514,
+	0x48026a00, 0x0201f800, 0x000207a1, 0x80000580,
+	0x1c01f000, 0x82000540, 0x00000001, 0x0401f7fd,
+	0x42001000, 0x0000000a, 0x0401f015, 0x42001000,
+	0x00000010, 0x0401f012, 0x42001000, 0x00000016,
+	0x0401f00f, 0x42001000, 0x00000017, 0x0401f00c,
+	0x42001000, 0x00000018, 0x0401f009, 0x42001000,
+	0x0000001b, 0x0401f006, 0x42001000, 0x0000001e,
+	0x0401f003, 0x42001000, 0x00000020, 0x42000800,
+	0x00000019, 0x42028000, 0x00000031, 0x0401f7e2,
+	0x42000800, 0x00000003, 0x0401f003, 0x42000800,
+	0x0000000a, 0x41781000, 0x0401f7f7, 0x42000800,
+	0x00000009, 0x59341400, 0x0401f7f3, 0x42028000,
+	0x00000008, 0x0401f005, 0x42000800, 0x00000007,
+	0x416c1000, 0x0401f7ec, 0x41780800, 0x41781000,
+	0x0401f7cd, 0x42028000, 0x00000000, 0x0401f7fb,
+	0x82004d80, 0x0000001d, 0x02000800, 0x001005d8,
+	0x82004d80, 0x0000001a, 0x04020004, 0x40101000,
+	0x40000800, 0x0401f7dc, 0x82004d80, 0x0000001b,
+	0x04020003, 0x40181000, 0x0401f7fa, 0x82004d80,
+	0x0000001c, 0x040007f7, 0x82004d80, 0x00000019,
+	0x040007b8, 0x0401f7d6, 0x592e6008, 0x0201f800,
+	0x0010941a, 0x040007b6, 0x59300c06, 0x82040580,
+	0x00000011, 0x040207d6, 0x83440580, 0x0000ffff,
+	0x04020005, 0x59326809, 0x813669c0, 0x0400000e,
+	0x0401f7cf, 0x592c100a, 0x82081500, 0x00ffffff,
+	0x41784000, 0x0401fda8, 0x040207d6, 0x59300009,
+	0x800001c0, 0x04000003, 0x81340580, 0x040207c4,
+	0x49366009, 0x592c0c0b, 0x82041500, 0x0000e000,
+	0x82080580, 0x00006000, 0x04000009, 0x59300a03,
+	0x82040580, 0x00000007, 0x040207b9, 0x492e6008,
+	0x42027000, 0x00000054, 0x0401f77f, 0x0201f800,
+	0x0010a8d4, 0x040007bc, 0x0401f7b1, 0x492fc857,
+	0x59a80021, 0x800001c0, 0x04020073, 0x592e6008,
+	0x4933c857, 0x0201f800, 0x0010941a, 0x04000041,
+	0x59301406, 0x82080580, 0x00000005, 0x0402005b,
+	0x59301203, 0x82080580, 0x00000007, 0x04020057,
+	0x592e8c06, 0x83440480, 0x00000800, 0x04021032,
+	0x41784000, 0x592c1009, 0x82081500, 0x00ffffff,
+	0x0401fd75, 0x0402005f, 0x59300009, 0x800001c0,
+	0x04000003, 0x81340580, 0x04020048, 0x4d300000,
+	0x592e6013, 0x4933c857, 0x83300580, 0xffffffff,
+	0x0400000d, 0x0201f800, 0x0010941a, 0x5c026000,
+	0x04000029, 0x591c1406, 0x82080580, 0x00000006,
+	0x04000046, 0x82080580, 0x00000011, 0x04000043,
+	0x0401f002, 0x5c026000, 0x59a80010, 0x592c100a,
+	0x82081500, 0x00ffffff, 0x80081580, 0x04020017,
+	0x592c1009, 0x82081500, 0x00ffffff, 0x80081580,
+	0x0400000f, 0x49366009, 0x492e6008, 0x42027000,
+	0x00000092, 0x0201f800, 0x000207a1, 0x80000580,
+	0x1c01f000, 0x42001000, 0x0000000a, 0x0401f00c,
+	0x42001000, 0x00000010, 0x0401f009, 0x42001000,
+	0x00000014, 0x0401f006, 0x42001000, 0x00000018,
+	0x0401f003, 0x42001000, 0x0000003c, 0x492fc857,
+	0x480bc857, 0x42000800, 0x00000019, 0x42028000,
+	0x00000031, 0x82000540, 0x00000001, 0x0401f7e9,
+	0x492fc857, 0x4803c857, 0x480bc857, 0x40000800,
+	0x0401f7f7, 0x492fc857, 0x42000800, 0x0000000a,
+	0x41781000, 0x0401f7f2, 0x4933c857, 0x59300406,
+	0x4803c857, 0x59300203, 0x4803c857, 0x59300009,
+	0x4803c857, 0x42028000, 0x00000008, 0x41780800,
+	0x41781000, 0x0401f7e8, 0x42000800, 0x0000001e,
+	0x0401f7f0, 0x42000800, 0x00000001, 0x0401f7ed,
+	0x82004d80, 0x0000001d, 0x02000800, 0x001005d8,
+	0x82004d80, 0x0000001a, 0x04020003, 0x40101000,
+	0x0401f7dc, 0x82004d80, 0x0000001b, 0x04020003,
+	0x40181000, 0x0401f7d7, 0x82004d80, 0x0000001c,
+	0x040007d4, 0x82004d80, 0x00000019, 0x040007d1,
+	0x0401f7d5, 0x59302009, 0x801021c0, 0x04000035,
+	0x58101400, 0x82081d00, 0x000000ff, 0x59300c03,
+	0x82040580, 0x00000008, 0x04000022, 0x82040580,
+	0x0000000a, 0x04000017, 0x82040580, 0x0000000c,
+	0x04000010, 0x82040580, 0x00000002, 0x04000019,
+	0x82040580, 0x00000001, 0x04000012, 0x82040580,
+	0x00000003, 0x0400000b, 0x82040580, 0x00000005,
+	0x04000004, 0x82040580, 0x00000033, 0x04020019,
+	0x820c0580, 0x00000009, 0x0400000d, 0x0401f015,
+	0x820c0580, 0x00000005, 0x04000009, 0x0401f011,
+	0x820c0580, 0x0000000b, 0x04000005, 0x0401f00d,
+	0x820c0580, 0x00000003, 0x0402000a, 0x82081d00,
+	0xffffff00, 0x840c01c0, 0x800c0540, 0x4813c857,
+	0x480bc857, 0x4807c857, 0x4803c857, 0x48002400,
+	0x1c01f000, 0x599c0017, 0x8c00050a, 0x04000003,
+	0x80000580, 0x1c01f000, 0x59a80026, 0x82000500,
+	0x00000028, 0x04000008, 0x42028800, 0x000007fd,
+	0x0201f800, 0x00020245, 0x04020003, 0x5934000a,
+	0x8c000504, 0x1c01f000, 0x4d300000, 0x5934000e,
+	0x80026540, 0x04000006, 0x0201f800, 0x001062d5,
+	0x02000800, 0x001064ad, 0x497a680e, 0x5c026000,
+	0x1c01f000, 0x4d440000, 0x4d340000, 0x80000580,
+	0x40001800, 0x40028800, 0x82080580, 0x00000008,
+	0x04020003, 0x42001800, 0x00000001, 0x0201f800,
+	0x00020245, 0x0402000a, 0x0401fd6d, 0x04020008,
+	0x800c19c0, 0x04000004, 0x59340405, 0x8c000508,
+	0x04000003, 0x80081040, 0x04000009, 0x81468800,
+	0x83440480, 0x00000800, 0x040017f1, 0x80000580,
+	0x5c026800, 0x5c028800, 0x1c01f000, 0x82000540,
+	0x00000001, 0x5c026800, 0x5c028800, 0x1c01f000,
+	0x4a033020, 0x00000000, 0x497b3026, 0x497b3027,
+	0x497b3028, 0x497b3029, 0x497b302b, 0x497b3021,
+	0x4a03b104, 0x60000001, 0x1c01f000, 0x4803c856,
+	0x599c0018, 0x497b3024, 0x497b3025, 0x82000500,
+	0x0000000f, 0x82000d80, 0x00000005, 0x04000006,
+	0x82000580, 0x00000006, 0x0400000d, 0x497b3022,
+	0x1c01f000, 0x4a033022, 0x00000005, 0x599c0216,
+	0x82000500, 0x0000ffff, 0x04020003, 0x42000000,
+	0x00000002, 0x48033023, 0x1c01f000, 0x4a033022,
+	0x00000006, 0x0401f7f6, 0x0401ffe5, 0x4a03c826,
+	0x00000004, 0x599c0209, 0x80000540, 0x0400001f,
+	0x599c0207, 0x80000540, 0x04000007, 0x800000cc,
+	0x599c080d, 0x80040400, 0x4803b100, 0x497bb102,
+	0x59d80101, 0x599c000d, 0x4803b100, 0x599c000e,
+	0x4803b101, 0x599c0207, 0x80000540, 0x04020002,
+	0x497bb102, 0x599c0a09, 0x82040540, 0x00400000,
+	0x59980822, 0x4803b103, 0x4a03b109, 0x00000004,
+	0x4a03b104, 0x10000001, 0x800409c0, 0x04020004,
+	0x4a033020, 0x00000001, 0x1c01f000, 0x4a033020,
+	0x00000002, 0x0401f7fd, 0x59980022, 0x4803c856,
+	0x80000540, 0x02000000, 0x000202de, 0x0401f017,
+	0x42034000, 0x0010b4a4, 0x59a1d81e, 0x80edd9c0,
+	0x02000800, 0x001005d8, 0x58ec0009, 0x48efc857,
+	0x49a3c857, 0x492fc857, 0x4803c857, 0x800001c0,
+	0x08020000, 0x0201f800, 0x001005d8, 0x5931d821,
+	0x58ef400b, 0x58ec0009, 0x800001c0, 0x08020000,
+	0x0201f800, 0x001005d8, 0x497a5800, 0x59980026,
+	0x80000540, 0x0402008c, 0x59d80105, 0x82000d00,
+	0x00018780, 0x040201da, 0x80000106, 0x82000500,
+	0x00000003, 0x0c01f001, 0x00104d0a, 0x00104d89,
+	0x00104d22, 0x00104d50, 0x592c0001, 0x492fc857,
+	0x492fb107, 0x80000d40, 0x04020007, 0x59940019,
+	0x80000540, 0x04022003, 0x59980023, 0x48032819,
+	0x1c01f000, 0x497a5801, 0x40065800, 0x592c0001,
+	0x496a5800, 0x815eb800, 0x412ed000, 0x80000d40,
+	0x040207f9, 0x59c80000, 0x82000540, 0x00001200,
+	0x48039000, 0x0401f7ee, 0x492fc857, 0x492fb107,
+	0x592c0001, 0x80000d40, 0x04020012, 0x59da5908,
+	0x835c0480, 0x00000020, 0x0400101c, 0x0402b01a,
+	0x492fb007, 0x0400e7fa, 0x59d80105, 0x82000500,
+	0x00018780, 0x040201aa, 0x59940019, 0x80000540,
+	0x04022003, 0x59980023, 0x48032819, 0x1c01f000,
+	0x497a5801, 0x40065800, 0x592c0001, 0x496a5800,
+	0x815eb800, 0x412ed000, 0x80000d40, 0x040207f9,
+	0x59c80000, 0x82000540, 0x00001200, 0x48039000,
+	0x0401f7e3, 0x0400f009, 0x496a5800, 0x412ed000,
+	0x815eb800, 0x59c80000, 0x82000540, 0x00001200,
+	0x48039000, 0x0401f7e0, 0x492fa807, 0x0401f7de,
+	0x492fc857, 0x59d81108, 0x45681000, 0x400ad000,
+	0x815eb800, 0x0400e7fc, 0x59c80000, 0x82000540,
+	0x00001200, 0x48039000, 0x0402d00c, 0x592c0001,
+	0x492fc857, 0x492fb107, 0x80000d40, 0x0402001d,
+	0x59940019, 0x80000540, 0x04022003, 0x59980023,
+	0x48032819, 0x1c01f000, 0x59d80105, 0x82000500,
+	0x00018780, 0x04020172, 0x42000000, 0x0010b855,
+	0x0201f800, 0x0010aa47, 0x59980026, 0x59980828,
+	0x80000000, 0x48033026, 0x492fc857, 0x800409c0,
+	0x492f3028, 0x04000003, 0x492c0800, 0x0401f002,
+	0x492f3029, 0x592c0001, 0x80000d40, 0x040007e5,
+	0x497a5801, 0x40065800, 0x592c0001, 0x496a5800,
+	0x815eb800, 0x412ed000, 0x80000d40, 0x040207f9,
+	0x59c80000, 0x82000540, 0x00001200, 0x48039000,
+	0x0401f7d8, 0x59980026, 0x59980828, 0x80000000,
+	0x48033026, 0x492fc857, 0x800409c0, 0x492f3028,
+	0x04000003, 0x492c0800, 0x0401f002, 0x492f3029,
+	0x592c0001, 0x80000d40, 0x04020027, 0x0402d00e,
+	0x59980029, 0x80025d40, 0x0400000f, 0x59980026,
+	0x80000040, 0x48033026, 0x04020002, 0x48033028,
+	0x592c0000, 0x48033029, 0x492fc857, 0x492fb107,
+	0x0400d7f4, 0x42000000, 0x0010b855, 0x0201f800,
+	0x0010aa47, 0x0402e00a, 0x59da5908, 0x496a5800,
+	0x412ed000, 0x815eb800, 0x0400e7fc, 0x59c80000,
+	0x82000540, 0x00001200, 0x48039000, 0x59d80105,
+	0x82000500, 0x00018780, 0x04020125, 0x59940019,
+	0x80000540, 0x04022003, 0x59980023, 0x48032819,
+	0x1c01f000, 0x497a5801, 0x40065800, 0x592c0001,
+	0x496a5800, 0x815eb800, 0x412ed000, 0x80000d40,
+	0x040207f9, 0x59c80000, 0x82000540, 0x00001200,
+	0x48039000, 0x0401f7ce, 0x592c0204, 0x4803c856,
+	0x04000008, 0x42034000, 0x0010b4a4, 0x59a1d81e,
+	0x80edd9c0, 0x02000800, 0x001005d8, 0x0401f003,
+	0x5931d821, 0x58ef400b, 0x58ec0009, 0x800001c0,
+	0x08020000, 0x0201f800, 0x001005d8, 0x497a5801,
+	0x40065800, 0x592c0001, 0x496a5800, 0x412ed000,
+	0x815eb800, 0x80000d40, 0x040207f9, 0x59c80000,
+	0x82000540, 0x00001200, 0x48039000, 0x1c01f000,
+	0x497a5801, 0x40065800, 0x592c0001, 0x496a5800,
+	0x412ed000, 0x815eb800, 0x80000d40, 0x040207f9,
+	0x59c80000, 0x82000540, 0x00001200, 0x48039000,
+	0x0200e000, 0x000202fb, 0x0201f000, 0x00020302,
+	0x5998002b, 0x84000540, 0x4803302b, 0x0201f000,
+	0x0002035e, 0x42000000, 0x0010b855, 0x0201f800,
+	0x0010aa47, 0x492fc857, 0x59980026, 0x59980828,
+	0x80000000, 0x48033026, 0x800409c0, 0x492f3028,
+	0x04000003, 0x492c0800, 0x0401f002, 0x492f3029,
+	0x592c0001, 0x80000d40, 0x04020002, 0x1c01f000,
+	0x497a5801, 0x40065800, 0x592c0001, 0x496a5800,
+	0x412ed000, 0x815eb800, 0x80000d40, 0x040207f9,
+	0x59c80000, 0x82000540, 0x00001200, 0x48039000,
+	0x1c01f000, 0x59980026, 0x59980828, 0x80000000,
+	0x48033026, 0x492fc857, 0x800409c0, 0x492f3028,
+	0x04000003, 0x492c0800, 0x0401f002, 0x492f3029,
+	0x592c0001, 0x80000d40, 0x04020039, 0x0402d00e,
+	0x59980029, 0x80025d40, 0x0400000f, 0x59980026,
+	0x80000040, 0x48033026, 0x04020002, 0x48033028,
+	0x592c0000, 0x48033029, 0x492fc857, 0x492fb107,
+	0x0400d7f4, 0x42000000, 0x0010b855, 0x0201f800,
+	0x0010aa47, 0x0402e01d, 0x59da5908, 0x496a5800,
+	0x412ed000, 0x815eb800, 0x0400e7fc, 0x59c80000,
+	0x82000540, 0x00001200, 0x48039000, 0x04006018,
+	0x59d8010a, 0x59d8090a, 0x80040d80, 0x040207fd,
+	0x900001c0, 0x82000540, 0x00000013, 0x4803c011,
+	0x5998002b, 0x84000500, 0x4803302b, 0x59e00017,
+	0x8c000508, 0x04000003, 0x4a03c017, 0x00000003,
+	0x4203e000, 0x30000001, 0x59d80105, 0x82000500,
+	0x00018780, 0x0402007e, 0x1c01f000, 0x5998002b,
+	0x84000540, 0x4803302b, 0x0401f7f8, 0x497a5801,
+	0x40065800, 0x592c0001, 0x496a5800, 0x412ed000,
+	0x815eb800, 0x80000d40, 0x040207f9, 0x59c80000,
+	0x82000540, 0x00001200, 0x48039000, 0x0401f7bc,
+	0x5c000000, 0x4c000000, 0x4803c857, 0x492fc857,
+	0x4943c857, 0x4807c857, 0x4a025a04, 0x00000103,
+	0x49425a06, 0x48065a08, 0x4a025c06, 0x0000ffff,
+	0x813261c0, 0x04000003, 0x59300402, 0x48025c06,
+	0x832c0400, 0x00000009, 0x04011000, 0x4803c840,
+	0x4a03c842, 0x0000000b, 0x04011000, 0x1c01f000,
+	0x4df00000, 0x4203e000, 0x50000000, 0x599cb817,
+	0x59940019, 0x80000540, 0x04002023, 0x0400000e,
+	0x59980022, 0x82000580, 0x00000005, 0x0400001e,
+	0x59a80069, 0x81640580, 0x0402001b, 0x8c5cbd08,
+	0x04000005, 0x59a8006a, 0x59a80866, 0x80040580,
+	0x04020015, 0x8c5cbd08, 0x04020030, 0x59d8090b,
+	0x59d8010a, 0x80040580, 0x0400000d, 0x0400600e,
+	0x4a03c011, 0x80400012, 0x4a03c020, 0x00008040,
+	0x59e00017, 0x8c000508, 0x04000003, 0x4a03c017,
+	0x00000002, 0x4203e000, 0x30000001, 0x4a032819,
+	0xffff0000, 0x04026835, 0x04006003, 0x8c5cbd08,
+	0x04020860, 0x59980029, 0x80025d40, 0x04000010,
+	0x59d80105, 0x82000500, 0x00018780, 0x04020020,
+	0x0402d00d, 0x59980026, 0x492fc857, 0x80000040,
+	0x48033026, 0x592c0000, 0x492fb107, 0x48033029,
+	0x04020003, 0x4803c856, 0x48033028, 0x5c03e000,
+	0x1c01f000, 0x42000000, 0x0010b855, 0x0201f800,
+	0x0010aa47, 0x0401f7fa, 0x59e0000f, 0x59e0080f,
+	0x80040580, 0x040207fd, 0x59e00010, 0x59e01010,
+	0x80081580, 0x040207fd, 0x40065000, 0x80041580,
+	0x040007c7, 0x040067dc, 0x0401f7ca, 0x4803c857,
+	0x485fc857, 0x8c00050e, 0x02020800, 0x001005d0,
+	0x4203e000, 0x50000000, 0x4200b800, 0x00008004,
+	0x0201f000, 0x001005dd, 0x5998002b, 0x8c000500,
+	0x04000013, 0x84000500, 0x4803302b, 0x59d8010a,
+	0x59d8090a, 0x80040580, 0x040207fd, 0x800408e0,
+	0x82040d40, 0x00000013, 0x4807c011, 0x59e00017,
+	0x8c000508, 0x04000003, 0x4a03c017, 0x00000003,
+	0x4203e000, 0x30000001, 0x1c01f000, 0x0402e014,
+	0x59da5908, 0x496a5800, 0x412ed000, 0x815eb800,
+	0x0400e7fc, 0x59c80000, 0x82000540, 0x00001200,
+	0x48039000, 0x59d8090b, 0x59980024, 0x48073024,
+	0x80040480, 0x04020004, 0x59940019, 0x80000540,
+	0x04022003, 0x59980823, 0x48072819, 0x59d80105,
+	0x82000500, 0x00018780, 0x040207c9, 0x1c01f000,
+	0x59981025, 0x59e00010, 0x59e00810, 0x80041d80,
+	0x040207fd, 0x80080580, 0x04000013, 0x48073025,
+	0x59e0000f, 0x59e0100f, 0x80081d80, 0x040207fd,
+	0x81280580, 0x04000008, 0x400a5000, 0x40080000,
+	0x80040580, 0x04000003, 0x59980823, 0x48072819,
+	0x1c01f000, 0x59940019, 0x80000540, 0x040227f8,
+	0x0401f7fc, 0x59e0000f, 0x59e0100f, 0x80081d80,
+	0x040207fd, 0x81280580, 0x040007f6, 0x400a5000,
+	0x59940019, 0x80000540, 0x040027ed, 0x0401f7f1,
+	0x59a80017, 0x82000c80, 0x0000000a, 0x02021800,
+	0x001005d8, 0x0c01f809, 0x4a038805, 0x000000f0,
+	0x59c400a3, 0x82000500, 0x02870000, 0x02020800,
+	0x001005d8, 0x1c01f000, 0x00104fc5, 0x00104f51,
+	0x00104f6c, 0x00104f95, 0x00104fb8, 0x00104ff2,
+	0x00105004, 0x00104f6c, 0x00104fd6, 0x00104f50,
+	0x1c01f000, 0x4a038808, 0x00000004, 0x0401f8f9,
+	0x0201f800, 0x001053ab, 0x59c40805, 0x8c040d0e,
+	0x04020013, 0x8c040d0a, 0x0402000b, 0x8c040d0c,
+	0x04020006, 0x8c040d08, 0x0400000d, 0x4a035017,
+	0x00000003, 0x0401f00a, 0x4a035017, 0x00000000,
+	0x0401f007, 0x42000000, 0x0010b844, 0x0201f800,
+	0x0010aa47, 0x4a035017, 0x00000002, 0x1c01f000,
+	0x4a038808, 0x00000002, 0x0401f8de, 0x59c40805,
+	0x8c040d08, 0x04020021, 0x8c040d0c, 0x0402001c,
+	0x8c040d0e, 0x04020017, 0x82040500, 0x000000f0,
+	0x0402001c, 0x0201f800, 0x001053ab, 0x4a038808,
+	0x00000080, 0x59c40002, 0x8400050c, 0x48038802,
+	0x0401f9d9, 0x4d3c0000, 0x42027800, 0x00000001,
+	0x0201f800, 0x00109874, 0x5c027800, 0x4a038808,
+	0x00000080, 0x4a035017, 0x00000009, 0x0401f009,
+	0x4a035017, 0x00000001, 0x0401f006, 0x4a035017,
+	0x00000000, 0x0401f003, 0x4a035017, 0x00000003,
+	0x1c01f000, 0x0401f8b7, 0x4a038808, 0x00000080,
+	0x59c40805, 0x8c040d0a, 0x0402001b, 0x8c040d0c,
+	0x04020016, 0x8c040d0e, 0x04020011, 0x82040500,
+	0x000000f0, 0x04020016, 0x59c40002, 0x8400050c,
+	0x48038802, 0x0401f9b4, 0x4d3c0000, 0x42027800,
+	0x00000001, 0x0201f800, 0x00109874, 0x5c027800,
+	0x4a035017, 0x00000009, 0x0401f009, 0x4a035017,
+	0x00000001, 0x0401f006, 0x4a035017, 0x00000000,
+	0x0401f003, 0x4a035017, 0x00000002, 0x1c01f000,
+	0x4a038808, 0x00000008, 0x59c40805, 0x8c040d0c,
+	0x04020006, 0x8c040d0e, 0x04000006, 0x4a035017,
+	0x00000001, 0x0401f003, 0x4a035017, 0x00000000,
+	0x1c01f000, 0x0401f8d3, 0x59c40805, 0x8c040d0c,
+	0x0402000d, 0x4c040000, 0x0401f882, 0x5c000800,
+	0x8c040d0a, 0x04020006, 0x8c040d0e, 0x04000006,
+	0x4a035017, 0x00000001, 0x0401f003, 0x4a035017,
+	0x00000002, 0x1c01f000, 0x4a038808, 0x00000008,
+	0x42001000, 0x00105058, 0x0201f800, 0x00106084,
+	0x59c40805, 0x8c040d0a, 0x0402000d, 0x8c040d08,
+	0x0402000b, 0x8c040d0c, 0x04020006, 0x8c040d0e,
+	0x0400000d, 0x4a035017, 0x00000001, 0x0401f00a,
+	0x4a035017, 0x00000000, 0x0401f007, 0x42000000,
+	0x0010b844, 0x0201f800, 0x0010aa47, 0x4a035017,
+	0x00000004, 0x1c01f000, 0x0401f8a6, 0x0401f859,
+	0x59c40805, 0x8c040d0a, 0x0402000b, 0x8c040d0c,
+	0x04020006, 0x8c040d0e, 0x04000009, 0x4a035017,
+	0x00000001, 0x0401f006, 0x4a035017, 0x00000000,
+	0x0401f003, 0x4a035017, 0x00000002, 0x1c01f000,
+	0x4a038808, 0x00000004, 0x0401f846, 0x59c40805,
+	0x8c040d0a, 0x04020010, 0x8c040d08, 0x0402000b,
+	0x8c040d0c, 0x04020006, 0x8c040d0e, 0x0400000c,
+	0x4a035017, 0x00000001, 0x0401f009, 0x4a035017,
+	0x00000000, 0x0401f006, 0x4a035017, 0x00000003,
+	0x0401f003, 0x4a035017, 0x00000002, 0x1c01f000,
+	0x0401f91f, 0x02020800, 0x001005d8, 0x59a80805,
+	0x8c040d0c, 0x04000015, 0x84040d0c, 0x48075005,
+	0x4a038805, 0x00000010, 0x0201f800, 0x00101937,
+	0x59c40005, 0x8c000508, 0x04000008, 0x4a038808,
+	0x00000008, 0x4a035033, 0x00000001, 0x4202d800,
+	0x00000001, 0x0401f01a, 0x59c40006, 0x84000548,
+	0x48038806, 0x0401f016, 0x59a80017, 0x82000580,
+	0x00000001, 0x0400000c, 0x59a80017, 0x82000580,
+	0x00000005, 0x0402000c, 0x42000000, 0x0010b844,
+	0x0201f800, 0x0010aa47, 0x4a035017, 0x00000008,
+	0x0401f007, 0x42000000, 0x0010b844, 0x0201f800,
+	0x0010aa47, 0x4a035017, 0x00000004, 0x1c01f000,
+	0x4803c856, 0x4c040000, 0x4c080000, 0x42000800,
+	0x00000064, 0x42001000, 0x00105058, 0x0201f800,
+	0x00106079, 0x5c001000, 0x5c000800, 0x1c01f000,
+	0x4803c856, 0x4c040000, 0x0201f800, 0x00106c55,
+	0x4df00000, 0x0201f800, 0x00106e21, 0x5c03e000,
+	0x02000800, 0x00106c4b, 0x0401ffba, 0x5c000800,
+	0x1c01f000, 0x4803c856, 0x4c040000, 0x4c080000,
+	0x0201f800, 0x00106c55, 0x4df00000, 0x0201f800,
+	0x00106e21, 0x5c03e000, 0x02000800, 0x00106c4b,
+	0x59c40006, 0x84000500, 0x48038806, 0x0201f800,
+	0x00106ede, 0x497b8880, 0x0201f800, 0x0010a9c0,
+	0x0201f800, 0x0010a9ce, 0x0201f800, 0x00101815,
+	0x4a03504c, 0x00000004, 0x4202d800, 0x00000004,
+	0x4a038805, 0x00000001, 0x42001000, 0x00105058,
+	0x0201f800, 0x00106084, 0x0201f800, 0x001006d4,
+	0x0401f8c1, 0x04000006, 0x42006000, 0xfeffffff,
+	0x41786800, 0x0201f800, 0x0010427d, 0x0201f800,
+	0x00100452, 0x42000000, 0x00000001, 0x0201f800,
+	0x00101590, 0x5c001000, 0x5c000800, 0x1c01f000,
+	0x59c40008, 0x8c000508, 0x04020007, 0x4a038808,
+	0x00000010, 0x4201d000, 0x00001388, 0x0201f800,
+	0x0010608e, 0x1c01f000, 0x4c040000, 0x59a80833,
+	0x82040580, 0x00000000, 0x0400000b, 0x82040580,
+	0x00000001, 0x0400000b, 0x82040580, 0x00000002,
+	0x0400000b, 0x82040580, 0x00000003, 0x0400000b,
+	0x0401f057, 0x4a035017, 0x00000000, 0x0401f009,
+	0x4a035017, 0x00000004, 0x0401f006, 0x4a035017,
+	0x00000001, 0x0401f003, 0x4a035017, 0x00000007,
+	0x497b8880, 0x4a038893, 0x00000001, 0x41780000,
+	0x0201f800, 0x00101606, 0x0201f800, 0x00106ede,
+	0x836c0d80, 0x00000004, 0x04000008, 0x59c40006,
+	0x82000500, 0xffffff0f, 0x82000540, 0x04000001,
+	0x48038806, 0x0401f007, 0x59c40006, 0x82000500,
+	0xffffff0f, 0x82000540, 0x04000000, 0x48038806,
+	0x0401f875, 0x04020005, 0x59c40806, 0x82040d00,
+	0xfbffff0f, 0x48078806, 0x4200b000, 0x00000005,
+	0x59c40005, 0x8c000534, 0x04020033, 0x42006000,
+	0xfc18ffff, 0x42006800, 0x01000000, 0x0201f800,
+	0x0010427d, 0x0201f800, 0x00101937, 0x59c408a4,
+	0x82040d00, 0x0000000f, 0x82040d80, 0x0000000c,
+	0x0400000a, 0x42006000, 0xfeffffff, 0x42006800,
+	0x02000000, 0x0201f800, 0x0010427d, 0x8058b040,
+	0x040207e8, 0x0401f8a1, 0x0401f853, 0x04000006,
+	0x42006000, 0xfeffffff, 0x41786800, 0x0201f800,
+	0x0010427d, 0x836c0d80, 0x00000004, 0x04000006,
+	0x59a8084d, 0x42001000, 0x00105065, 0x0201f800,
+	0x0010606e, 0x4a035033, 0x00000004, 0x0401fe31,
+	0x0401f841, 0x04020008, 0x59c408a4, 0x82040d00,
+	0x0000000f, 0x82040580, 0x0000000c, 0x02020800,
+	0x001005d8, 0x5c000800, 0x1c01f000, 0x4803c856,
+	0x4c000000, 0x0201f800, 0x0010609e, 0x4a035010,
+	0x00ffffff, 0x497b5032, 0x59a8002a, 0x82000500,
+	0xffff0000, 0x4803502a, 0x497b8880, 0x497b8893,
+	0x41780000, 0x0201f800, 0x00101606, 0x59c40001,
+	0x82000500, 0xfffffcff, 0x48038801, 0x42006000,
+	0xfc18ffff, 0x41786800, 0x0201f800, 0x0010427d,
+	0x4a038808, 0x00000000, 0x5c000000, 0x800001c0,
+	0x02020800, 0x0010411d, 0x4a038805, 0x040000f0,
+	0x59c40006, 0x82000500, 0xffffffcf, 0x82000540,
+	0x440000c1, 0x48038806, 0x1c01f000, 0x4c5c0000,
+	0x59a8b832, 0x825cbd80, 0x0000aaaa, 0x5c00b800,
+	0x1c01f000, 0x4c5c0000, 0x599cb818, 0x825cbd00,
+	0x00000030, 0x825cbd80, 0x00000000, 0x5c00b800,
+	0x1c01f000, 0x4c5c0000, 0x599cb818, 0x825cbd00,
+	0x00000030, 0x825cbd80, 0x00000010, 0x5c00b800,
+	0x1c01f000, 0x4c5c0000, 0x599cb818, 0x825cbd00,
+	0x00000030, 0x825cbd80, 0x00000020, 0x5c00b800,
+	0x1c01f000, 0x59a80005, 0x4803c857, 0x82000d00,
+	0x00000013, 0x04000025, 0x599c1017, 0x4d3c0000,
+	0x82000500, 0x00000011, 0x04000007, 0x42027800,
+	0x00000400, 0x0201f800, 0x00103b25, 0x0402000a,
+	0x0401f012, 0x42027800, 0x00000408, 0x0201f800,
+	0x00103b25, 0x0400000d, 0x42003000, 0x00000003,
+	0x0401f003, 0x42003000, 0x00000004, 0x42028000,
+	0x0000000e, 0x0201f800, 0x0010a449, 0x599c1017,
+	0x8c08150a, 0x04020007, 0x42028000, 0x00000004,
+	0x0201f800, 0x00101fe5, 0x80000580, 0x0401f80d,
+	0x5c027800, 0x0401f00a, 0x0201f800, 0x00103b25,
+	0x04000007, 0x42028000, 0x0000000f, 0x42003000,
+	0x00000001, 0x0201f800, 0x0010a449, 0x1c01f000,
+	0x59a80005, 0x04000004, 0x82000540, 0x00000010,
+	0x0401f003, 0x82000500, 0xffffffef, 0x48035005,
+	0x4803c857, 0x1c01f000, 0x4803c856, 0x4c580000,
+	0x42000000, 0x0010b8cb, 0x0201f800, 0x0010aa47,
+	0x42000800, 0x0010c0f1, 0x59c40003, 0x44000800,
+	0x59c40004, 0x48000801, 0x59c4000b, 0x48000802,
+	0x59c4008e, 0x48000803, 0x59c4008f, 0x48000804,
+	0x59c40090, 0x48000805, 0x59c40091, 0x48000806,
+	0x59c40092, 0x48000807, 0x59c40093, 0x48000808,
+	0x59c40099, 0x48000809, 0x59c4009e, 0x4800080a,
+	0x59c400aa, 0x4800080b, 0x59c400af, 0x4800080c,
+	0x59c400b2, 0x4800080d, 0x59c400b1, 0x4800080e,
+	0x82040c00, 0x0000000f, 0x41c41800, 0x4200b000,
+	0x00000030, 0x580c0050, 0x44000800, 0x80040800,
+	0x800c1800, 0x8058b040, 0x040207fb, 0x41c41800,
+	0x4200b000, 0x00000020, 0x580c0010, 0x44000800,
+	0x80040800, 0x800c1800, 0x8058b040, 0x040207fb,
+	0x497b8830, 0x4200b000, 0x00000040, 0x59c40031,
+	0x44000800, 0x80040800, 0x8058b040, 0x040207fc,
+	0x497b88ac, 0x4200b000, 0x00000010, 0x59c400ad,
+	0x44000800, 0x80040800, 0x8058b040, 0x040207fc,
+	0x59c41001, 0x4c080000, 0x8408150c, 0x480b8801,
+	0x4a0370e4, 0x00000300, 0x4a0370e5, 0xb0000000,
+	0x42000800, 0x00000800, 0x80040840, 0x02000800,
+	0x001005d8, 0x59b800e5, 0x8c000538, 0x040207fb,
+	0x4a0370e4, 0x00000200, 0x42006000, 0xffffffff,
+	0x42006800, 0x80000000, 0x0201f800, 0x0010427d,
+	0x4a038807, 0x00000001, 0x497b8807, 0x4a038808,
+	0x00000010, 0x42006000, 0xfcf8ffff, 0x42006800,
+	0x01000000, 0x0201f800, 0x0010427d, 0x5c001000,
+	0x480b8801, 0x42000800, 0x0010c0f1, 0x50040000,
+	0x48038803, 0x58040001, 0x48038804, 0x58040002,
+	0x4803880b, 0x58040003, 0x4803888e, 0x58040004,
+	0x4803888f, 0x58040005, 0x48038890, 0x58040006,
+	0x48038891, 0x58040007, 0x48038892, 0x58040008,
+	0x48038893, 0x58040009, 0x48038899, 0x5804000a,
+	0x4803889e, 0x5804000b, 0x480388aa, 0x5804000c,
+	0x480388af, 0x5804000d, 0x480388b2, 0x5804000e,
+	0x480388b1, 0x82040c00, 0x0000000f, 0x41c41800,
+	0x4200b000, 0x00000030, 0x50040000, 0x48001850,
+	0x80040800, 0x800c1800, 0x8058b040, 0x040207fb,
+	0x41c41800, 0x4200b000, 0x00000020, 0x50040000,
+	0x48001810, 0x80040800, 0x800c1800, 0x8058b040,
+	0x040207fb, 0x497b8830, 0x4200b000, 0x00000040,
+	0x50040000, 0x48038831, 0x80040800, 0x8058b040,
+	0x040207fc, 0x497b88ac, 0x4200b000, 0x00000010,
+	0x50040000, 0x480388ad, 0x80040800, 0x8058b040,
+	0x040207fc, 0x497b8880, 0x41780000, 0x0201f800,
+	0x00101606, 0x59c408a4, 0x82040d00, 0x0000000f,
+	0x82040580, 0x0000000c, 0x02020800, 0x001005d8,
+	0x4a038805, 0x04000000, 0x5c00b000, 0x1c01f000,
+	0x4803c856, 0x4c580000, 0x4ce80000, 0x42000000,
+	0x0010b845, 0x0201f800, 0x0010aa47, 0x59c41008,
+	0x4c080000, 0x82080500, 0xffffff7f, 0x48038808,
+	0x59c40004, 0x82000500, 0x00003e02, 0x04000005,
+	0x4201d000, 0x00000014, 0x0201f800, 0x0010608e,
+	0x59c40006, 0x82000500, 0xffffff0f, 0x48038806,
+	0x4a038805, 0x00000010, 0x4a038808, 0x00000004,
+	0x4200b000, 0x00000065, 0x59c40005, 0x8c000508,
+	0x04020012, 0x4201d000, 0x000003e8, 0x0201f800,
+	0x0010608e, 0x8058b040, 0x040207f8, 0x0201f800,
+	0x00106ede, 0x4a038808, 0x00000008, 0x4a035033,
+	0x00000001, 0x4202d800, 0x00000001, 0x82000540,
+	0x00000001, 0x0401f030, 0x0201f800, 0x00100ae0,
+	0x42000000, 0x0010b8a8, 0x0201f800, 0x0010aa47,
+	0x0201f800, 0x00100ef4, 0x497b8880, 0x59a8002a,
+	0x82000500, 0x0000ffff, 0x4c000000, 0x0201f800,
+	0x00101606, 0x5c000000, 0x48038880, 0x4a038808,
+	0x00000000, 0x4200b000, 0x00000065, 0x4a038805,
+	0x000000f0, 0x0201f800, 0x00101937, 0x42000800,
+	0x000000f0, 0x59c40005, 0x80040d00, 0x04000008,
+	0x4201d000, 0x000003e8, 0x0201f800, 0x0010608e,
+	0x8058b040, 0x040207f2, 0x0401f7d1, 0x59c40006,
+	0x82000540, 0x000000f0, 0x48038806, 0x59a8001e,
+	0x80000540, 0x04020002, 0x80000000, 0x48038893,
+	0x80000580, 0x5c001000, 0x4df00000, 0x0201f800,
+	0x0010195d, 0x5c03e000, 0x480b8808, 0x5c01d000,
+	0x5c00b000, 0x1c01f000, 0x4803c856, 0x4c580000,
+	0x4ce80000, 0x59c41008, 0x82080500, 0xffffff7f,
+	0x48038808, 0x4c080000, 0x59c40004, 0x82000500,
+	0x00003e02, 0x04000005, 0x4201d000, 0x00000014,
+	0x0201f800, 0x0010608e, 0x0201f800, 0x00100ae0,
+	0x42000000, 0x0010b8a9, 0x0201f800, 0x0010aa47,
+	0x0201f800, 0x00100ef4, 0x4a038808, 0x00000002,
+	0x80000580, 0x48038880, 0x48038893, 0x0201f800,
+	0x00101606, 0x4200b000, 0x00000384, 0x4a038805,
+	0x000000f0, 0x0201f800, 0x00101937, 0x42000800,
+	0x000000f0, 0x59c40005, 0x80040d00, 0x04000015,
+	0x82000500, 0x000000d0, 0x04020012, 0x4201d000,
+	0x00000067, 0x0201f800, 0x0010608e, 0x8058b040,
+	0x040207ef, 0x0201f800, 0x00106ede, 0x4a038808,
+	0x00000008, 0x4a035033, 0x00000001, 0x4202d800,
+	0x00000001, 0x82000540, 0x00000001, 0x0401f010,
+	0x497b8880, 0x59a8001e, 0x80000540, 0x04020002,
+	0x80000000, 0x48038893, 0x59a8002a, 0x82000500,
+	0x0000ffff, 0x4c000000, 0x0201f800, 0x00101606,
+	0x5c000000, 0x48038880, 0x80000580, 0x5c001000,
+	0x4df00000, 0x0201f800, 0x0010195d, 0x5c03e000,
+	0x480b8808, 0x5c01d000, 0x5c00b000, 0x1c01f000,
+	0x4803c856, 0x59c40004, 0x82000500, 0x00003e02,
+	0x0400000a, 0x0201f800, 0x00106ede, 0x4a038808,
+	0x00000008, 0x4a035033, 0x00000001, 0x4202d800,
+	0x00000001, 0x0401f052, 0x0201f800, 0x00100ae0,
+	0x42000000, 0x0010b8aa, 0x0201f800, 0x0010aa47,
+	0x0201f800, 0x00100ef4, 0x59c40006, 0x84000508,
+	0x48038806, 0x4a038805, 0x00000010, 0x59a80805,
+	0x84040d4c, 0x48075005, 0x42000800, 0x00000064,
+	0x42001000, 0x00105058, 0x0201f800, 0x0010606e,
+	0x4a038808, 0x00000000, 0x497b8880, 0x4a038805,
+	0x000000f0, 0x0201f800, 0x00101937, 0x42000800,
+	0x000000f0, 0x59c40005, 0x80040d00, 0x0400000e,
+	0x82000500, 0x000000e0, 0x0402000b, 0x4201d000,
+	0x000003e8, 0x0201f800, 0x0010608e, 0x0201f800,
+	0x00105f48, 0x59940004, 0x80000540, 0x040207ec,
+	0x0401f023, 0x4c080000, 0x42001000, 0x00105065,
+	0x0201f800, 0x00105f90, 0x42001000, 0x00105058,
+	0x0201f800, 0x00106084, 0x5c001000, 0x497b8880,
+	0x59a8001e, 0x80000540, 0x04020002, 0x80000000,
+	0x48038893, 0x59a8002a, 0x82000500, 0x0000ffff,
+	0x4c000000, 0x0201f800, 0x00101606, 0x5c000000,
+	0x48038880, 0x59a80805, 0x84040d0c, 0x48075005,
+	0x59c40006, 0x84000548, 0x48038806, 0x0201f800,
+	0x0010195d, 0x4a038808, 0x00000080, 0x1c01f000,
+	0x4803c856, 0x4d400000, 0x4d3c0000, 0x0201f800,
+	0x00106ede, 0x0201f800, 0x0010ab33, 0x04020025,
+	0x599c1017, 0x59a80805, 0x8c040d00, 0x0402000c,
+	0x8c08151a, 0x0400001f, 0x84040d42, 0x48075005,
+	0x42028000, 0x00000004, 0x42027800, 0x0000000c,
+	0x8c081508, 0x04020008, 0x0401f012, 0x42028000,
+	0x00000004, 0x42027800, 0x00000004, 0x8c081508,
+	0x0400000c, 0x4d400000, 0x42028000, 0x0000000e,
+	0x42028800, 0x0000ffff, 0x0201f800, 0x0010a446,
+	0x5c028000, 0x599c0817, 0x8c040d0a, 0x04020005,
+	0x4943c857, 0x493fc857, 0x0201f800, 0x00101fe5,
+	0x497b8880, 0x4202d800, 0x00000001, 0x0401fcfb,
+	0x5c027800, 0x5c028000, 0x1c01f000, 0x0201f800,
+	0x00100ae0, 0x42000000, 0x0010b8ab, 0x0201f800,
+	0x0010aa47, 0x0201f800, 0x00100ef4, 0x42000000,
+	0x00000001, 0x0201f800, 0x00101606, 0x4a038880,
+	0x00000001, 0x0201f000, 0x0010195d, 0x4202e000,
+	0x00000000, 0x4a033015, 0x00000001, 0x497b301d,
+	0x497b3006, 0x4a03b004, 0x60000001, 0x59d80005,
+	0x4a03b004, 0x90000001, 0x4a03a804, 0x60000001,
+	0x59d40005, 0x4a03a804, 0x90000001, 0x0201f000,
+	0x00105983, 0x4a03c825, 0x00000004, 0x4a03c827,
+	0x00000004, 0x599c0409, 0x80000d40, 0x04000020,
+	0x599c0407, 0x80000540, 0x04000007, 0x800000cc,
+	0x599c100b, 0x80080400, 0x4803b000, 0x497bb002,
+	0x59d80001, 0x599c000b, 0x4803b000, 0x599c000c,
+	0x4803b001, 0x599c0407, 0x80000540, 0x04020002,
+	0x497bb002, 0x599c0c09, 0x82040540, 0x00400000,
+	0x4803b003, 0x4a03b009, 0x00000004, 0x4a03b004,
+	0x10000001, 0x59e00803, 0x82040d00, 0xfffffeff,
+	0x82040d40, 0x00008000, 0x4807c003, 0x599c040a,
+	0x80000540, 0x04000020, 0x599c0408, 0x80000540,
+	0x04000007, 0x800000cc, 0x599c100f, 0x80080400,
+	0x4803a800, 0x497ba802, 0x59d40001, 0x599c000f,
+	0x4803a800, 0x599c0010, 0x4803a801, 0x599c0408,
+	0x80000540, 0x04020002, 0x497ba802, 0x599c0c0a,
+	0x82040540, 0x00400000, 0x4803a803, 0x4a03a809,
+	0x00000004, 0x4a03a804, 0x10000001, 0x59e00803,
+	0x82040d00, 0xfffffbff, 0x82040d40, 0x00008000,
+	0x4807c003, 0x800409c0, 0x04000007, 0x4202e000,
+	0x00000001, 0x0200b800, 0x00020551, 0x0200f000,
+	0x00020566, 0x1c01f000, 0x0201f800, 0x001005d8,
+	0x1c01f000, 0x4df00000, 0x4203e000, 0x50000000,
+	0x59981005, 0x800811c0, 0x0400001e, 0x58080005,
+	0x82000d00, 0x43018780, 0x02020000, 0x00105846,
+	0x8c000508, 0x04000015, 0x580a5808, 0x592c0204,
+	0x497a5800, 0x497a5801, 0x82000500, 0x000000ff,
+	0x82000c80, 0x0000004b, 0x0402100b, 0x0c01f80f,
+	0x5c03e000, 0x83700580, 0x00000003, 0x040007e6,
+	0x0200f800, 0x00020566, 0x0200b000, 0x00020551,
+	0x1c01f000, 0x0401f850, 0x5c03e000, 0x0401f7f9,
+	0x0401f8de, 0x0401f7fd, 0x00105491, 0x00105491,
+	0x00105491, 0x00105491, 0x001054a1, 0x00105491,
+	0x00105491, 0x00105491, 0x00105491, 0x00105491,
+	0x00105519, 0x00105491, 0x00105491, 0x001054a1,
+	0x001054a1, 0x00105491, 0x00105491, 0x00105491,
+	0x00105491, 0x00105491, 0x00105491, 0x00105491,
+	0x00105491, 0x00105491, 0x00105491, 0x00105491,
+	0x00105491, 0x00105491, 0x00105491, 0x00105491,
+	0x00105491, 0x00105491, 0x00105491, 0x00105491,
+	0x00105491, 0x00105491, 0x00105491, 0x00105491,
+	0x00105491, 0x00105491, 0x00105491, 0x00105491,
+	0x00105491, 0x00105491, 0x00105491, 0x00105491,
+	0x00105491, 0x00105491, 0x00105491, 0x00105491,
+	0x00105491, 0x00105491, 0x00105491, 0x00105491,
+	0x00105491, 0x00105491, 0x00105491, 0x00105491,
+	0x00105491, 0x00105491, 0x00105491, 0x00105491,
+	0x00105491, 0x00105491, 0x00105491, 0x00105491,
+	0x00105491, 0x00105491, 0x00105491, 0x00105491,
+	0x00105491, 0x00105491, 0x00105491, 0x00105491,
+	0x00105491, 0x492fc857, 0x42000000, 0x0010b85e,
+	0x0201f800, 0x0010aa47, 0x42000000, 0x00000400,
+	0x0401f019, 0x492fc857, 0x42000000, 0x0010b85d,
+	0x0201f800, 0x0010aa47, 0x42000000, 0x00001000,
+	0x0401f011, 0x492fc857, 0x42000000, 0x0010b85c,
+	0x0201f800, 0x0010aa47, 0x42000000, 0x00002000,
+	0x0401f009, 0x492fc857, 0x42000000, 0x0010b85f,
+	0x0201f800, 0x0010aa47, 0x42000000, 0x00000800,
+	0x0401f001, 0x4803c857, 0x4202e000, 0x00000001,
+	0x592c0c04, 0x82040d00, 0xffff80ff, 0x80040540,
+	0x48025c04, 0x0201f000, 0x000202da, 0x592c0204,
+	0x492fc857, 0x80000110, 0x040007db, 0x80000040,
+	0x04000025, 0x48033002, 0x492f3003, 0x492f3004,
+	0x4a033008, 0x001054e5, 0x4202e000, 0x00000003,
+	0x1c01f000, 0x592c0204, 0x492fc857, 0x80000110,
+	0x040007cd, 0x80000040, 0x04000033, 0x48033002,
+	0x492f3003, 0x492f3004, 0x4a033008, 0x00105501,
+	0x4202e000, 0x00000003, 0x1c01f000, 0x0201f800,
+	0x0010ab33, 0x02020000, 0x000204d9, 0x42028000,
+	0x00000028, 0x41780800, 0x417a6000, 0x0201f800,
+	0x00104e70, 0x0201f800, 0x001091c6, 0x0201f000,
+	0x000202da, 0x592c0a0a, 0x8c040d02, 0x04020016,
+	0x59a80021, 0x492fc857, 0x80000540, 0x0402000f,
+	0x592c0207, 0x80000540, 0x04000005, 0x0201f800,
+	0x00104326, 0x04020004, 0x1c01f000, 0x42000000,
+	0x00000000, 0x592c0a06, 0x48065c06, 0x48025a06,
+	0x0201f000, 0x000202da, 0x42000000, 0x00000028,
+	0x0401f7f9, 0x42000800, 0x00000009, 0x0201f000,
+	0x0010665b, 0x592c0208, 0x492fc857, 0x82000c80,
+	0x0000199a, 0x040217a4, 0x592c0408, 0x80000540,
+	0x040207a1, 0x59a80821, 0x800409c0, 0x04020009,
+	0x592c0207, 0x80000540, 0x0400079b, 0x497a5a06,
+	0x0201f800, 0x00104385, 0x04020004, 0x1c01f000,
+	0x42000000, 0x00000028, 0x48025a06, 0x0201f000,
+	0x000202da, 0x59980804, 0x59980002, 0x48065800,
+	0x492c0801, 0x492f3004, 0x80000040, 0x48033002,
+	0x04000002, 0x1c01f000, 0x599a5803, 0x59980008,
+	0x4202e000, 0x00000001, 0x0801f000, 0x592e8a06,
+	0x592c0406, 0x4803c856, 0x82000500, 0x000000ff,
+	0x4200b800, 0x00000001, 0x82000d80, 0x00000001,
+	0x04000015, 0x417a8800, 0x4200b800, 0x000007f0,
+	0x82000d80, 0x00000002, 0x0400000f, 0x80000540,
+	0x02020000, 0x000202da, 0x592e8a06, 0x0201f800,
+	0x00020245, 0x02020000, 0x000202da, 0x592e9008,
+	0x592e9809, 0x0201f800, 0x00104713, 0x0201f000,
+	0x000202da, 0x59a80805, 0x84040d00, 0x48075005,
+	0x0201f800, 0x00020245, 0x02000800, 0x0010482c,
+	0x81468800, 0x805cb840, 0x040207fa, 0x0201f000,
+	0x000202da, 0x592c0a08, 0x4807c857, 0x82040580,
+	0x0000000e, 0x04000045, 0x82040580, 0x00000046,
+	0x04000046, 0x82040580, 0x00000045, 0x04000020,
+	0x82040580, 0x00000029, 0x04000010, 0x82040580,
+	0x0000002a, 0x04000009, 0x82040580, 0x0000000f,
+	0x040001fc, 0x82040580, 0x0000002e, 0x040001f9,
+	0x4807c856, 0x0401f1f2, 0x59a80805, 0x84040d04,
+	0x48075005, 0x0401f1f3, 0x592e8a06, 0x0201f800,
+	0x00020245, 0x040201ef, 0x59340200, 0x84000518,
+	0x48026a00, 0x592e6009, 0x4933c857, 0x83300580,
+	0xffffffff, 0x0402002a, 0x0401f1e6, 0x592c1407,
+	0x480bc857, 0x0201f800, 0x00109410, 0x411e6000,
+	0x04020003, 0x4803c856, 0x0401f1d9, 0x592e3809,
+	0x591c1414, 0x84081516, 0x84081554, 0x480a3c14,
+	0x4a026403, 0x0000003a, 0x592c040b, 0x80000540,
+	0x04000007, 0x4a026403, 0x0000003b, 0x592c020c,
+	0x4802641a, 0x592c040c, 0x4802621a, 0x4a026203,
+	0x00000001, 0x42000800, 0x80000040, 0x0201f800,
+	0x00020721, 0x0401f1c7, 0x59a80068, 0x84000510,
+	0x48035068, 0x0401f1c3, 0x592c1207, 0x8c081500,
+	0x040201c0, 0x592e8a06, 0x592e6009, 0x0201f800,
+	0x0010941a, 0x04020003, 0x4803c856, 0x0401f1b4,
+	0x59300c06, 0x82040580, 0x00000004, 0x04000003,
+	0x4803c856, 0x0401f1ae, 0x59300a03, 0x82040580,
+	0x00000007, 0x04000003, 0x4803c856, 0x0401f1a8,
+	0x59300c03, 0x82040580, 0x00000001, 0x04000021,
+	0x82040580, 0x00000003, 0x04000016, 0x82040580,
+	0x00000006, 0x04000020, 0x82040580, 0x00000008,
+	0x04000015, 0x82040580, 0x0000000a, 0x0400000a,
+	0x82040580, 0x0000000c, 0x04000004, 0x82040580,
+	0x0000002e, 0x04020018, 0x42000800, 0x00000009,
+	0x0401f013, 0x42000800, 0x00000005, 0x0401f010,
+	0x417a7800, 0x0201f800, 0x0010203c, 0x4a026406,
+	0x00000001, 0x42000800, 0x00000003, 0x0401f008,
+	0x417a7800, 0x0201f800, 0x0010203c, 0x4a026406,
+	0x00000001, 0x42000800, 0x0000000b, 0x0201f800,
+	0x00104571, 0x4a026203, 0x00000001, 0x0201f800,
+	0x0010672b, 0x0401f17b, 0x40000800, 0x58040000,
+	0x80000540, 0x040207fd, 0x492c0800, 0x1c01f000,
+	0x492fc857, 0x59300c06, 0x82040580, 0x00000006,
+	0x04020094, 0x0201f800, 0x001049e7, 0x04020005,
+	0x59340200, 0x8c00051a, 0x02000000, 0x00020533,
+	0x59340200, 0x8c00050e, 0x0400008a, 0x59300203,
+	0x42027800, 0x00000001, 0x82000580, 0x00000007,
+	0x02020000, 0x00020533, 0x4a026203, 0x00000002,
+	0x0201f000, 0x00020533, 0x42028000, 0x00000002,
+	0x4a026206, 0x00000014, 0x4d2c0000, 0x0201f800,
+	0x0010a1d1, 0x5c025800, 0x59300c06, 0x4807c857,
+	0x82040580, 0x00000007, 0x04020063, 0x492fc857,
+	0x4a025a06, 0x00000001, 0x0201f000, 0x000202da,
+	0x592c240a, 0x492fc857, 0x4813c857, 0x8c10251c,
+	0x04020016, 0x8c10251a, 0x04000003, 0x8c10250a,
+	0x04000069, 0x59340a00, 0x8c040d0e, 0x04000003,
+	0x8c10251e, 0x04000064, 0x0201f800, 0x0002075a,
+	0x0400006b, 0x592c240a, 0x49366009, 0x49325809,
+	0x4a026406, 0x00000006, 0x4a026203, 0x00000007,
+	0x0201f000, 0x0002052f, 0x592c0a0c, 0x5934000f,
+	0x41784000, 0x80001540, 0x0400006d, 0x58080204,
+	0x82000500, 0x000000ff, 0x82000580, 0x00000012,
+	0x04020004, 0x5808020c, 0x80040580, 0x04000004,
+	0x58080000, 0x40084000, 0x0401f7f3, 0x58080000,
+	0x49781000, 0x802041c0, 0x04000006, 0x48004000,
+	0x80000540, 0x04020007, 0x48226810, 0x0401f005,
+	0x4802680f, 0x80000540, 0x04020002, 0x497a6810,
+	0x4d2c0000, 0x400a5800, 0x4a025a06, 0x00000002,
+	0x0201f800, 0x000202da, 0x5c025800, 0x0401f7bc,
+	0x592c040a, 0x8c00051c, 0x04000016, 0x592c0206,
+	0x82000580, 0x0000ffff, 0x04020012, 0x592e6009,
+	0x83300580, 0xffffffff, 0x040007b1, 0x83300480,
+	0x0010d1c0, 0x04001010, 0x59a8000b, 0x81300480,
+	0x0402100d, 0x59300008, 0x800001c0, 0x04020005,
+	0x59300203, 0x82000580, 0x00000007, 0x04000797,
+	0x492fc857, 0x4a025a06, 0x00000029, 0x0201f000,
+	0x000202da, 0x492fc857, 0x4a025a06, 0x00000008,
+	0x0201f000, 0x000202da, 0x492fc857, 0x4a025a06,
+	0x00000045, 0x0201f000, 0x000202da, 0x492fc857,
+	0x4a025a06, 0x0000002a, 0x0201f000, 0x000202da,
+	0x492fc857, 0x4a025a06, 0x00000028, 0x0201f000,
+	0x000202da, 0x492fc857, 0x4a025a06, 0x00000006,
+	0x0201f000, 0x000202da, 0x492fc857, 0x4a025a06,
+	0x0000000e, 0x0201f000, 0x000202da, 0x59340010,
+	0x492e6810, 0x492fc857, 0x80000d40, 0x04000003,
+	0x492c0800, 0x1c01f000, 0x5934040b, 0x492e680f,
+	0x492fc857, 0x4803c857, 0x80000540, 0x04020003,
+	0x4a026a03, 0x00000001, 0x1c01f000, 0x59a8000e,
+	0x81640480, 0x0402176e, 0x42026000, 0x0010d1c0,
+	0x59300009, 0x81340580, 0x04020004, 0x59300202,
+	0x80040580, 0x04000759, 0x83326400, 0x00000024,
+	0x41580000, 0x81300480, 0x040017f6, 0x0401f760,
+	0x492fc857, 0x592c0407, 0x82000c80, 0x0000199a,
+	0x040215f1, 0x592c0204, 0x80000112, 0x040205de,
+	0x592e8a06, 0x0201f800, 0x00020245, 0x04020059,
+	0x0201f800, 0x001049e7, 0x04020059, 0x592e780a,
+	0x493fc857, 0x8d3e7d3e, 0x04020007, 0x59a80021,
+	0x80000540, 0x0402004f, 0x0201f800, 0x00104838,
+	0x040005dd, 0x833c1d00, 0x0000001f, 0x040005da,
+	0x592c0207, 0x82000c80, 0x00001000, 0x040215d6,
+	0x800000c2, 0x800008c4, 0x8005d400, 0x592e9008,
+	0x592e9809, 0x5934080d, 0x800409c0, 0x0402002e,
+	0x833c1d00, 0x0000001f, 0x81780040, 0x80000000,
+	0x800c1902, 0x040217fe, 0x040205c7, 0x0c01f001,
+	0x001056e9, 0x001056ec, 0x001056f9, 0x001056fc,
+	0x001056ff, 0x0201f800, 0x0010903e, 0x0401f01a,
+	0x0201f800, 0x0010480b, 0x04000027, 0x80e9d1c0,
+	0x02020800, 0x00105fae, 0x42028000, 0x00000005,
+	0x417a9000, 0x417a9800, 0x0201f800, 0x0010904e,
+	0x0401f00d, 0x42027000, 0x0000004d, 0x0401f006,
+	0x42027000, 0x0000004e, 0x0401f003, 0x42027000,
+	0x00000052, 0x0201f800, 0x001046c9, 0x02020800,
+	0x0010907e, 0x04000010, 0x8d3e7d3e, 0x04020017,
+	0x1c01f000, 0x58040002, 0x80000540, 0x04020007,
+	0x4d3c0000, 0x40067800, 0x0201f800, 0x001047eb,
+	0x5c027800, 0x040207cb, 0x4a025a06, 0x00000030,
+	0x0401f00d, 0x4a025a06, 0x0000002c, 0x0401f00a,
+	0x4a025a06, 0x00000028, 0x0401f007, 0x4a025a06,
+	0x00000029, 0x0401f004, 0x497a5c09, 0x4a025a06,
+	0x00000000, 0x4a025a04, 0x00000103, 0x0201f000,
+	0x000202da, 0x492fc857, 0x592c0204, 0x80000110,
+	0x80000040, 0x04000002, 0x0401f56f, 0x592c0207,
+	0x82000500, 0x000003ff, 0x48025a07, 0x8c000506,
+	0x04000004, 0x82000500, 0x00000070, 0x04020004,
+	0x59a80821, 0x800409c0, 0x04020018, 0x4a025a06,
+	0x0000dead, 0x592c0408, 0x82000500, 0x0000f0ff,
+	0x48025c08, 0x0201f800, 0x001043b4, 0x04020002,
+	0x1c01f000, 0x49425a06, 0x8058b1c0, 0x04000009,
+	0x0201f800, 0x0010955f, 0x0401f80f, 0x44042800,
+	0x82580580, 0x00000002, 0x04020002, 0x48082801,
+	0x0201f000, 0x000202da, 0x42028000, 0x00000031,
+	0x42000800, 0x00000001, 0x4200b000, 0x00000001,
+	0x0401f7ed, 0x592c0408, 0x80000118, 0x832c2c00,
+	0x00000009, 0x80142c00, 0x1c01f000, 0x492fc857,
+	0x4a025a08, 0x00000006, 0x0201f000, 0x000202da,
+	0x492fc857, 0x4a025a08, 0x00000001, 0x0201f000,
+	0x000202da, 0x492fc857, 0x592c040a, 0x82000500,
+	0x00000003, 0x04000020, 0x0201f800, 0x0002075a,
+	0x04000021, 0x592c0204, 0x492e6008, 0x82000500,
+	0x000000ff, 0x82000580, 0x00000045, 0x0400000e,
+	0x592c000b, 0x0201f800, 0x00105c9a, 0x02000800,
+	0x00020245, 0x04020018, 0x42027000, 0x00000041,
+	0x49366009, 0x4a026406, 0x00000001, 0x0201f000,
+	0x000207a1, 0x59300015, 0x8400055e, 0x48026015,
+	0x42026800, 0x0010b524, 0x42027000, 0x00000040,
+	0x0401f7f4, 0x4a025a06, 0x00000101, 0x0201f000,
+	0x000202da, 0x4a025a06, 0x0000002c, 0x0201f000,
+	0x000202da, 0x4a025a06, 0x00000028, 0x0201f800,
+	0x000202da, 0x0201f000, 0x0002077d, 0x492fc857,
+	0x0201f800, 0x001062e1, 0x0400000b, 0x592c0204,
+	0x80000110, 0x80000040, 0x040204fb, 0x592c0c06,
+	0x800409c0, 0x04000009, 0x42000000, 0x00000102,
+	0x0401f003, 0x42000000, 0x00000104, 0x48025a06,
+	0x0201f000, 0x000202da, 0x592c0c07, 0x800409c0,
+	0x04000024, 0x82040480, 0x00000005, 0x04021021,
+	0x4c040000, 0x80040800, 0x0201f800, 0x00106306,
+	0x5c001000, 0x04020018, 0x832c0400, 0x00000008,
+	0x4000a000, 0x0201f800, 0x0010632f, 0x04020012,
+	0x592c1207, 0x82cc0580, 0x0010b50e, 0x04020009,
+	0x58c80c0b, 0x84040d00, 0x84040d02, 0x8c081500,
+	0x04000002, 0x84040d5e, 0x4805940b, 0x0401f001,
+	0x42000000, 0x00000000, 0x48025a06, 0x0201f000,
+	0x000202da, 0x42000000, 0x00000103, 0x0401f7fb,
+	0x42000000, 0x00000102, 0x0401f7f8, 0x492fc857,
+	0x592e7c06, 0x833c0500, 0xfffffffe, 0x04020043,
+	0x592c4007, 0x42026000, 0x0010d1c0, 0x41581800,
+	0x400c0000, 0x81300480, 0x04021023, 0x59300203,
+	0x82000580, 0x00000000, 0x04000007, 0x59300008,
+	0x80000d40, 0x04000004, 0x58040005, 0x80200580,
+	0x04000004, 0x83326400, 0x00000024, 0x0401f7f1,
+	0x58040204, 0x82000500, 0x000000ff, 0x82000d80,
+	0x00000053, 0x04000007, 0x82000d80, 0x00000048,
+	0x04000004, 0x82000580, 0x00000018, 0x04020023,
+	0x4d2c0000, 0x0201f800, 0x00108be3, 0x5c025800,
+	0x0400001e, 0x4a025a06, 0x00000000, 0x0201f000,
+	0x000202da, 0x592e8a06, 0x83440480, 0x000007f0,
+	0x04021016, 0x83440400, 0x0010ac00, 0x50000000,
+	0x80026d40, 0x04000011, 0x4d2c0000, 0x0201f800,
+	0x001047cb, 0x0400000c, 0x42028000, 0x00000005,
+	0x592c0a08, 0x0201f800, 0x00104e70, 0x0201f800,
+	0x001091cc, 0x0201f800, 0x000202da, 0x5c025800,
+	0x0401f7e5, 0x5c025800, 0x4a025a06, 0x00000031,
+	0x0201f000, 0x000202da, 0x492fc857, 0x4d2c0000,
+	0x0201f800, 0x001007e4, 0x04000016, 0x492fc857,
+	0x412f4000, 0x0201f800, 0x001007e4, 0x0400000e,
+	0x492fc857, 0x412dd800, 0x0201f800, 0x00103b28,
+	0x0201f800, 0x00103b32, 0x49a1d80b, 0x5c025800,
+	0x492dd80a, 0x0201f800, 0x00102214, 0x0201f000,
+	0x00102233, 0x41a25800, 0x0201f800, 0x001007f4,
+	0x5c025800, 0x4a025a06, 0x00004005, 0x4a025c06,
+	0x00000002, 0x0201f000, 0x000202da, 0x4807c857,
+	0x485fc857, 0x4200b800, 0x00000001, 0x5c000800,
+	0x4c5c0000, 0x0401f005, 0x4807c857, 0x485fc857,
+	0x5c000800, 0x4d780000, 0x4803c857, 0x492fc857,
+	0x8c00050e, 0x02020800, 0x001005d0, 0x4203e000,
+	0x50000000, 0x4200b800, 0x00008003, 0x0201f000,
+	0x001005dd, 0x592c0204, 0x80000110, 0x80000040,
+	0x04020441, 0x0201f800, 0x00104a34, 0x04020002,
+	0x1c01f000, 0x49425a06, 0x4806580d, 0x480a580e,
+	0x4943c857, 0x4807c857, 0x480bc857, 0x0201f000,
+	0x000202da, 0x592c0204, 0x80000110, 0x80000040,
+	0x04020431, 0x0201f800, 0x00104b8b, 0x04020002,
+	0x1c01f000, 0x49425a06, 0x48065811, 0x480a5812,
+	0x0201f000, 0x000202da, 0x592c0204, 0x80000110,
+	0x04000425, 0x80000040, 0x0402000c, 0x4202e000,
+	0x00000001, 0x592c020a, 0x8c000504, 0x02000000,
+	0x000204d0, 0x592c0207, 0x82000c80, 0x00001001,
+	0x04021429, 0x0401f009, 0x4202e000, 0x00000003,
+	0x48033002, 0x492f3003, 0x492f3004, 0x4a033008,
+	0x000204d0, 0x1c01f000, 0x4202e000, 0x00000002,
+	0x42000000, 0x0010beda, 0x50007000, 0x492c700b,
+	0x4978700e, 0x4978700c, 0x592c0011, 0x592c0812,
+	0x48007007, 0x48047008, 0x592c1013, 0x82080500,
+	0xffff0000, 0x04000003, 0x0201f800, 0x001005d8,
+	0x4978700d, 0x82080480, 0x00000180, 0x4803c857,
+	0x04001007, 0x4800700f, 0x4a007005, 0x00000180,
+	0x4a007004, 0x00000060, 0x0401f005, 0x4978700f,
+	0x48087005, 0x80081104, 0x48087004, 0x5838000a,
+	0x48007003, 0x40381000, 0x0201f000, 0x00100858,
+	0x0201f800, 0x001007d3, 0x04000003, 0x59980007,
+	0x0801f000, 0x1c01f000, 0x40307000, 0x5838000b,
+	0x80025d40, 0x0400001b, 0x58380002, 0x82000580,
+	0x00000100, 0x0400001d, 0x4c380000, 0x592c0204,
+	0x82000500, 0x000000ff, 0x82000580, 0x00000012,
+	0x0400000b, 0x592c0208, 0x8400054e, 0x48025a08,
+	0x4a025a06, 0x00000002, 0x4a025a04, 0x00000103,
+	0x0201f800, 0x000202c1, 0x0401f005, 0x4a025a06,
+	0x00000010, 0x0201f800, 0x000202da, 0x5c007000,
+	0x4202e000, 0x00000001, 0x4a007002, 0x00000100,
+	0x49787010, 0x1c01f000, 0x58380004, 0x82000480,
+	0x00000003, 0x04000087, 0x58380010, 0x8c000500,
+	0x04020019, 0x4200b000, 0x00000003, 0x832cac00,
+	0x00000011, 0x5838000a, 0x5838100d, 0x8008a400,
+	0x4c380000, 0x0201f800, 0x0010ab17, 0x5c007000,
+	0x5838000d, 0x82000400, 0x00000003, 0x4800700d,
+	0x4a007010, 0x00000001, 0x58380004, 0x82000480,
+	0x00000003, 0x48007004, 0x82000580, 0x00000003,
+	0x0400006c, 0x5838000e, 0x80001d40, 0x04020020,
+	0x4c380000, 0x0201f800, 0x001007d3, 0x5c007000,
+	0x04000010, 0x4a025a04, 0x0000010a, 0x42001800,
+	0x00000005, 0x480c700e, 0x5838000c, 0x80000540,
+	0x04020002, 0x5838000b, 0x40000800, 0x492c0801,
+	0x492c700c, 0x42000800, 0x0000000f, 0x0401f011,
+	0x4202e000, 0x00000008, 0x4a033007, 0x00105915,
+	0x1c01f000, 0x4202e000, 0x00000002, 0x42000000,
+	0x0010beda, 0x50007000, 0x0401f7e7, 0x583a580c,
+	0x400c0000, 0x42000800, 0x00000014, 0x80040c80,
+	0x58381004, 0x5838000f, 0x41783000, 0x80000540,
+	0x04020005, 0x84183540, 0x82081480, 0x00000003,
+	0x0400003c, 0x40080000, 0x80040480, 0x04001002,
+	0x40080800, 0x4004b000, 0x412c0000, 0x800c0400,
+	0x4000a800, 0x5838000a, 0x5838100d, 0x8008a400,
+	0x4c080000, 0x4c040000, 0x4c0c0000, 0x4c380000,
+	0x0201f800, 0x0010ab17, 0x5c007000, 0x5c001800,
+	0x5c000800, 0x40040000, 0x58381004, 0x80080480,
+	0x48007004, 0x82000580, 0x00000003, 0x04000002,
+	0x84183500, 0x5c000000, 0x80041400, 0x82080480,
+	0x00000060, 0x04020003, 0x84183542, 0x41781000,
+	0x400c0000, 0x80041c00, 0x820c0480, 0x00000014,
+	0x04020003, 0x84183544, 0x40001800, 0x40080800,
+	0x4804700d, 0x480c700e, 0x40180000, 0x0c01f001,
+	0x00105960, 0x00105964, 0x00105962, 0x00105960,
+	0x001058fc, 0x00105964, 0x00105962, 0x00105960,
+	0x0201f800, 0x001005d8, 0x5838100f, 0x0401f739,
+	0x5838080d, 0x82040400, 0x00000002, 0x5838100a,
+	0x80080400, 0x50001000, 0x800811c0, 0x0402000f,
+	0x4202e000, 0x00000001, 0x583a580b, 0x4978700b,
+	0x49787010, 0x592c0204, 0x82000500, 0x000000ff,
+	0x82000580, 0x00000012, 0x02000000, 0x00020507,
+	0x0201f000, 0x000204d0, 0x5838000a, 0x80040c00,
+	0x82381c00, 0x00000007, 0x54041800, 0x80040800,
+	0x800c1800, 0x54041800, 0x0401f71a, 0x0201f800,
+	0x001007d3, 0x02000800, 0x001005d8, 0x4a02580a,
+	0x0010be79, 0x42000800, 0x0010beda, 0x452c0800,
+	0x497a580b, 0x497a580c, 0x497a580d, 0x497a580e,
+	0x497a580f, 0x4a025809, 0x001058b6, 0x497a5810,
+	0x4a025802, 0x00000100, 0x4a025801, 0x00000001,
+	0x1c01f000, 0x59c80007, 0x8c000502, 0x04000070,
+	0x835c2c80, 0x00000005, 0x02001000, 0x00105f23,
+	0x59c82817, 0x497b9005, 0x82140500, 0x00e00000,
+	0x0402004f, 0x82140500, 0x000003ff, 0x82001c00,
+	0x00000006, 0x41cc2000, 0x42003000, 0x00006080,
+	0x820c0480, 0x00000040, 0x04001006, 0x42001000,
+	0x00000040, 0x820c1c80, 0x00000040, 0x0401f003,
+	0x400c1000, 0x41781800, 0x54182000, 0x80102000,
+	0x80183000, 0x80081040, 0x040207fc, 0x800c19c0,
+	0x04000005, 0x59c80005, 0x80000000, 0x48039005,
+	0x0401f7ea, 0x82140500, 0x01f60000, 0x04020029,
+	0x82140500, 0x0000f000, 0x0400000b, 0x82000c80,
+	0x00002000, 0x0402100f, 0x82140500, 0x0e000000,
+	0x80000132, 0x0c01f840, 0x4a039005, 0x00000140,
+	0x1c01f000, 0x59cc0400, 0x82000500, 0x0000ff00,
+	0x82000580, 0x00008100, 0x040007f4, 0x0401f01c,
+	0x4817c857, 0x82140500, 0x000003ff, 0x04020007,
+	0x59cc0400, 0x82000500, 0x0000ff00, 0x82000580,
+	0x00008100, 0x04020012, 0x42000000, 0x0010b8bd,
+	0x0201f800, 0x0010aa47, 0x0201f800, 0x00105dfa,
+	0x4803c856, 0x4a039005, 0x00000140, 0x0401f020,
+	0x4817c857, 0x82140500, 0x00f60000, 0x04020004,
+	0x0201f800, 0x00105e35, 0x040207d2, 0x0201f800,
+	0x0010513b, 0x04000010, 0x59c400a4, 0x4803c857,
+	0x82000500, 0x0000000f, 0x82000580, 0x0000000a,
+	0x04020009, 0x497b5016, 0x59c400a3, 0x82000540,
+	0x00080000, 0x480388a3, 0x82000500, 0xfff7ffff,
+	0x480388a3, 0x4817c856, 0x0201f800, 0x0010a978,
+	0x4a039005, 0x00000140, 0x0401f842, 0x4803c856,
+	0x1c01f000, 0x00105a1d, 0x00105cf4, 0x00105a15,
+	0x00105a15, 0x00105a15, 0x00105a15, 0x00105a15,
+	0x00105a15, 0x4803c857, 0x42000000, 0x0010b85a,
+	0x0201f800, 0x0010aa47, 0x4a039005, 0x00000140,
+	0x1c01f000, 0x4817c857, 0x59cc0400, 0x4803c857,
+	0x82000d00, 0x0000ff00, 0x82041500, 0x0000f000,
+	0x840409c0, 0x82140500, 0x000003ff, 0x800018c4,
+	0x8c142d14, 0x04000005, 0x59cc0002, 0x82000500,
+	0x00000003, 0x800c1c80, 0x480f5016, 0x82080580,
+	0x00002000, 0x04020011, 0x836c0580, 0x00000001,
+	0x0402000c, 0x59cc0006, 0x82000500, 0xff000000,
+	0x82000580, 0x11000000, 0x04020011, 0x0201f800,
+	0x00103b38, 0x0201f800, 0x00105f48, 0x0401f00c,
+	0x0401f81f, 0x0401f00a, 0x82080580, 0x00003000,
+	0x04020003, 0x0401fa06, 0x0401f005, 0x82080580,
+	0x00008000, 0x04020002, 0x0401fafc, 0x1c01f000,
+	0x4817c857, 0x42000000, 0x0010b859, 0x0201f800,
+	0x0010aa47, 0x836c0580, 0x00000003, 0x0402000b,
+	0x4c080000, 0x4c0c0000, 0x42001000, 0x00008048,
+	0x40141800, 0x80142120, 0x0201f800, 0x00103a3e,
+	0x5c001800, 0x5c001000, 0x1c01f000, 0x4807c857,
+	0x59cc0002, 0x82000500, 0xff000000, 0x82001580,
+	0x01000000, 0x04000004, 0x82001580, 0x23000000,
+	0x04020192, 0x82040580, 0x00000023, 0x0402003f,
+	0x0401fb6a, 0x0400018d, 0x59300c06, 0x82040580,
+	0x00000010, 0x04000013, 0x82040580, 0x00000011,
+	0x04000010, 0x82040580, 0x00000001, 0x0400000d,
+	0x82040580, 0x00000004, 0x0400000a, 0x82040580,
+	0x00000008, 0x04000007, 0x82040580, 0x0000000a,
+	0x04000004, 0x4933c857, 0x4807c857, 0x0401f177,
+	0x59300004, 0x82000500, 0x80010000, 0x04000004,
+	0x0201f800, 0x00106f60, 0x04020170, 0x59cc0a04,
+	0x48066202, 0x59cc0006, 0x82000500, 0xffff0000,
+	0x82000d80, 0x02000000, 0x04020005, 0x42027000,
+	0x00000015, 0x0201f000, 0x000207a1, 0x82000d80,
+	0x02140000, 0x040007fa, 0x82000d80, 0x02100000,
+	0x040007f7, 0x82000d80, 0x02100000, 0x040007f4,
+	0x82000d80, 0x01000000, 0x04020158, 0x59cc0006,
+	0x82000500, 0x0000ffff, 0x04020154, 0x42027000,
+	0x00000016, 0x0401f7ec, 0x82040580, 0x00000022,
+	0x0402014e, 0x59a80806, 0x8c040d14, 0x04000011,
+	0x0401f967, 0x0402000f, 0x0401f97d, 0x0400000d,
+	0x42027000, 0x0000004c, 0x59cc0001, 0x82000500,
+	0x00ffffff, 0x0201f800, 0x00105eec, 0x0400012a,
+	0x42028800, 0x0000ffff, 0x417a6800, 0x0401f126,
+	0x59cc0006, 0x82000500, 0xffff0000, 0x82000d80,
+	0x03000000, 0x04020021, 0x59a80026, 0x8c000508,
+	0x04000017, 0x8400054c, 0x48035026, 0x59cc0800,
+	0x82040d00, 0x00ffffff, 0x48075010, 0x497b8830,
+	0x84040d70, 0x48078832, 0x59c40802, 0x84040d4c,
+	0x48078802, 0x59cc0007, 0x82000500, 0x0000ffff,
+	0x48038893, 0x4803501e, 0x42000800, 0x00000003,
+	0x59a81010, 0x0201f800, 0x00106c78, 0x59cc0006,
+	0x82000500, 0x0000ffff, 0x04020118, 0x42027000,
+	0x00000017, 0x0401f0d9, 0x82000d80, 0x04000000,
+	0x04020011, 0x59cc0006, 0x82000500, 0x0000ffff,
+	0x0402010e, 0x0201f800, 0x0010513b, 0x04000004,
+	0x42027000, 0x0000001d, 0x0401f0cc, 0x59a80026,
+	0x84000548, 0x48035026, 0x42027000, 0x00000030,
+	0x0401f0c6, 0x82000d80, 0x05000000, 0x04020008,
+	0x59cc0006, 0x82000500, 0x0000ffff, 0x040200fb,
+	0x42027000, 0x00000018, 0x0401f0bc, 0x82000d80,
+	0x20100000, 0x04020004, 0x42027000, 0x00000019,
+	0x0401f0b6, 0x82000d80, 0x21100000, 0x04020004,
+	0x42027000, 0x0000001a, 0x0401f0b0, 0x82000d80,
+	0x52000000, 0x04020008, 0x59cc0006, 0x82000500,
+	0x0000ffff, 0x040200e5, 0x42027000, 0x0000001b,
+	0x0401f0a6, 0x82000d80, 0x50000000, 0x04020008,
+	0x59cc0006, 0x82000500, 0x0000ffff, 0x040200db,
+	0x42027000, 0x0000001c, 0x0401f09c, 0x82000d80,
+	0x13000000, 0x04020004, 0x42027000, 0x00000034,
+	0x0401f096, 0x82000d80, 0x12000000, 0x04020008,
+	0x59cc0006, 0x82000500, 0x0000ffff, 0x040200cb,
+	0x42027000, 0x00000024, 0x0401f08c, 0x82000d00,
+	0xff000000, 0x82040d80, 0x24000000, 0x04020004,
+	0x42027000, 0x0000002d, 0x0401f084, 0x82000d00,
+	0xff000000, 0x82040d80, 0x53000000, 0x04020004,
+	0x42027000, 0x0000002a, 0x0401f07c, 0x82000d80,
+	0x0f000000, 0x04020004, 0x42027000, 0x00000020,
+	0x0401f076, 0x82000d80, 0x61040000, 0x04020036,
+	0x83cc1400, 0x00000006, 0x80080800, 0x50080000,
+	0x82000500, 0x0000ffff, 0x82000480, 0x00000004,
+	0x4c580000, 0x8000b104, 0x8058b1c0, 0x04000026,
+	0x4c100000, 0x50041800, 0x820c1500, 0x03000000,
+	0x80081130, 0x42000000, 0x0010b817, 0x82082580,
+	0x00000000, 0x04020004, 0x42000000, 0x0010b814,
+	0x0401f00c, 0x82082580, 0x00000001, 0x04020004,
+	0x42000000, 0x0010b815, 0x0401f006, 0x82082580,
+	0x00000002, 0x04020003, 0x42000000, 0x0010b816,
+	0x0201f800, 0x0010aa47, 0x42001000, 0x00008015,
+	0x820c2500, 0x0000ffff, 0x800c1920, 0x0201f800,
+	0x00103a3e, 0x5c002000, 0x80040800, 0x8058b040,
+	0x040207da, 0x5c00b000, 0x42027000, 0x00000023,
+	0x0401f03e, 0x82000d80, 0x60000000, 0x04020004,
+	0x42027000, 0x0000003f, 0x0401f038, 0x82000d80,
+	0x54000000, 0x04020006, 0x0401fb12, 0x0402006f,
+	0x42027000, 0x00000046, 0x0401f030, 0x82000d80,
+	0x55000000, 0x04020009, 0x0401fb32, 0x04020004,
+	0x42027000, 0x00000041, 0x0401f028, 0x42027000,
+	0x00000042, 0x0401f025, 0x82000d80, 0x78000000,
+	0x04020004, 0x42027000, 0x00000045, 0x0401f01f,
+	0x82000d80, 0x10000000, 0x04020004, 0x42027000,
+	0x0000004e, 0x0401f019, 0x82000d80, 0x63000000,
+	0x04020004, 0x42027000, 0x0000004a, 0x0401f013,
+	0x82000d00, 0xff000000, 0x82040d80, 0x56000000,
+	0x04020004, 0x42027000, 0x0000004f, 0x0401f00b,
+	0x82000d00, 0xff000000, 0x82040d80, 0x57000000,
+	0x04020004, 0x42027000, 0x00000050, 0x0401f003,
+	0x42027000, 0x0000001d, 0x59cc3800, 0x821c3d00,
+	0x00ffffff, 0x821c0580, 0x00fffffe, 0x59cc0001,
+	0x04020005, 0x40003000, 0x42028800, 0x000007fe,
+	0x0401f003, 0x0401f8d1, 0x04020030, 0x0201f800,
+	0x001045a6, 0x0402002d, 0x83380580, 0x00000046,
+	0x04020004, 0x59a80010, 0x80180580, 0x04000027,
+	0x59340200, 0x8c000514, 0x0400000f, 0x83380580,
+	0x00000030, 0x0400000c, 0x83380580, 0x0000003f,
+	0x04000009, 0x83380580, 0x00000034, 0x04000006,
+	0x83380580, 0x00000024, 0x04000003, 0x42027000,
+	0x0000004c, 0x0201f800, 0x0002075a, 0x04000018,
+	0x49366009, 0x4a026406, 0x00000004, 0x59cc0c04,
+	0x48066202, 0x83380580, 0x0000004c, 0x04020009,
+	0x4a026406, 0x00000011, 0x813669c0, 0x04020005,
+	0x59cc0001, 0x82000500, 0x00ffffff, 0x4802601e,
+	0x0201f000, 0x000207a1, 0x59880052, 0x4803c857,
+	0x80000000, 0x48031052, 0x1c01f000, 0x42001000,
+	0x00008049, 0x59cc1806, 0x800c1930, 0x0201f800,
+	0x00103a3e, 0x0201f800, 0x00107942, 0x040007f3,
+	0x49366009, 0x4a026406, 0x00000004, 0x59cc0c04,
+	0x48066202, 0x4a026403, 0x00000009, 0x4a02641a,
+	0x00000009, 0x4a02621a, 0x00002900, 0x4a026203,
+	0x00000001, 0x0201f000, 0x0010672b, 0x59a80026,
+	0x4803c857, 0x8c000508, 0x04000010, 0x59cc0006,
+	0x82000500, 0xff000000, 0x82000d80, 0x03000000,
+	0x0400000c, 0x82000d80, 0x20000000, 0x04000009,
+	0x82000d80, 0x05000000, 0x04000006, 0x82000d80,
+	0x21000000, 0x04000003, 0x80000580, 0x1c01f000,
+	0x82000540, 0x00000001, 0x0401f7fd, 0x59cc2006,
+	0x82102500, 0xff000000, 0x9c1021c0, 0x0401f807,
+	0x820c1c00, 0x0010b4e3, 0x500c1800, 0x800c0500,
+	0x4803c857, 0x1c01f000, 0x40100800, 0x41781800,
+	0x82040480, 0x00000020, 0x04001004, 0x800c1800,
+	0x40000800, 0x0401f7fb, 0x82040500, 0x0000000f,
+	0x82000400, 0x0010ab38, 0x50000000, 0x8c040d08,
+	0x04000002, 0x900001c0, 0x1c01f000, 0x4803c856,
+	0x0401fac3, 0x0402000a, 0x0201f800, 0x0010210a,
+	0x04020007, 0x59cc0002, 0x82000500, 0xff000000,
+	0x82000d80, 0x08000000, 0x04000802, 0x1c01f000,
+	0x4803c856, 0x59cc0400, 0x82000d00, 0x0000ff00,
+	0x840409c0, 0x82040580, 0x00000033, 0x0402001f,
+	0x0401f976, 0x04000038, 0x59cc0a04, 0x48066202,
+	0x59cc0006, 0x4803c857, 0x82000500, 0xffff0000,
+	0x82000d80, 0x02000000, 0x04020009, 0x59cc0006,
+	0x82000500, 0x0000ffff, 0x0402002b, 0x42027000,
+	0x00000015, 0x0201f000, 0x000207a1, 0x82000d80,
+	0x01000000, 0x04020024, 0x59cc0006, 0x82000500,
+	0x0000ffff, 0x04020020, 0x42027000, 0x00000016,
+	0x0201f000, 0x000207a1, 0x82040580, 0x00000032,
+	0x04020019, 0x59cc0006, 0x82000500, 0xffff0000,
+	0x82000d80, 0x14000000, 0x04020013, 0x42027000,
+	0x00000038, 0x59cc0001, 0x0401f810, 0x0402000e,
+	0x0201f800, 0x001045a6, 0x0402000b, 0x0201f800,
+	0x0002075a, 0x04000008, 0x49366009, 0x4a026406,
+	0x00000004, 0x59cc0c04, 0x48066202, 0x0201f000,
+	0x000207a1, 0x1c01f000, 0x4803c857, 0x4c580000,
+	0x4c100000, 0x4c380000, 0x4c340000, 0x82003500,
+	0x00ffffff, 0x82181500, 0x00ff0000, 0x82081580,
+	0x00ff0000, 0x04020016, 0x82181480, 0x00fffffc,
+	0x04001013, 0x82181580, 0x00fffffd, 0x04020004,
+	0x42028800, 0x000007fd, 0x0401f040, 0x82181580,
+	0x00fffffe, 0x04020004, 0x42028800, 0x000007fe,
+	0x0401f03a, 0x82181580, 0x00fffffc, 0x04020004,
+	0x42028800, 0x000007fc, 0x0401f034, 0x41781000,
+	0x42002000, 0x00000000, 0x4200b000, 0x000007f0,
+	0x41ac7000, 0x50380000, 0x80006d40, 0x04020005,
+	0x800811c0, 0x0402001e, 0x8410155e, 0x0401f01c,
+	0x58340212, 0x82000500, 0x0000ff00, 0x04000011,
+	0x59a84010, 0x82204500, 0x00ffff00, 0x82180500,
+	0x00ffff00, 0x04000002, 0x80200580, 0x58340002,
+	0x0402000f, 0x82000500, 0x000000ff, 0x82184500,
+	0x000000ff, 0x80204580, 0x04020009, 0x0401f006,
+	0x58340002, 0x82000500, 0x00ffffff, 0x80184580,
+	0x04020003, 0x40128800, 0x0401f00c, 0x80102000,
+	0x80387000, 0x8058b040, 0x040207db, 0x800811c0,
+	0x04020005, 0x481bc857, 0x82000540, 0x00000001,
+	0x0401f003, 0x840a8d1e, 0x80000580, 0x5c006800,
+	0x5c007000, 0x5c002000, 0x5c00b000, 0x1c01f000,
+	0x59a80026, 0x8c00050e, 0x04000003, 0x8c000502,
+	0x04000006, 0x59cc0c00, 0x80040910, 0x82040500,
+	0x0000000f, 0x0c01f002, 0x1c01f000, 0x00105d0f,
+	0x00105d0f, 0x00105d0f, 0x00105de5, 0x00105d0f,
+	0x00105d11, 0x00105d29, 0x00105d2c, 0x00105d0f,
+	0x00105d0f, 0x00105d0f, 0x00105d0f, 0x00105d0f,
+	0x00105d0f, 0x00105d0f, 0x00105d0f, 0x4803c856,
+	0x1c01f000, 0x0401f8c5, 0x04000014, 0x82140500,
+	0x000003ff, 0x800000c4, 0x82000480, 0x00000008,
+	0x0400100e, 0x59cc0001, 0x59326809, 0x59340802,
+	0x80040580, 0x82000500, 0x00ffffff, 0x04020007,
+	0x59cc0a04, 0x48066202, 0x42027000, 0x00000046,
+	0x0201f000, 0x000207a1, 0x59cc0004, 0x4803c857,
+	0x1c01f000, 0x59cc0004, 0x4803c857, 0x1c01f000,
+	0x0401f8aa, 0x04000016, 0x82140500, 0x000003ff,
+	0x800000c4, 0x82000480, 0x0000000c, 0x04001010,
+	0x59cc0001, 0x82000500, 0x00ffffff, 0x59326809,
+	0x59340802, 0x82040d00, 0x00ffffff, 0x80040580,
+	0x04020007, 0x59cc0a04, 0x48066202, 0x42027000,
+	0x00000045, 0x0201f000, 0x000207a1, 0x59cc0004,
+	0x4803c857, 0x1c01f000, 0x4817c857, 0x0401f9c8,
+	0x04020011, 0x0201f800, 0x0010210a, 0x0402000e,
+	0x59cc0002, 0x82000500, 0xff000000, 0x82000580,
+	0x00000000, 0x04020008, 0x82040500, 0x0000000f,
+	0x82000c80, 0x00000006, 0x04021003, 0x4803c857,
+	0x0c01f002, 0x1c01f000, 0x00105d60, 0x00105d64,
+	0x00105d60, 0x00105d60, 0x00105db2, 0x00105dc3,
+	0x4803c857, 0x59cc0004, 0x4803c857, 0x1c01f000,
+	0x59cc0004, 0x4803c857, 0x59a80016, 0x800001c0,
+	0x040207f8, 0x59cc0802, 0x8c040d2e, 0x0402001d,
+	0x0201f800, 0x00107942, 0x02000800, 0x001005d8,
+	0x59cc0001, 0x4803c857, 0x0401ff28, 0x0402000d,
+	0x0201f800, 0x00020245, 0x0402000a, 0x4a026406,
+	0x00000005, 0x49366009, 0x59cc0c04, 0x48066202,
+	0x42027000, 0x00000088, 0x0201f000, 0x000207a1,
+	0x42028800, 0x0000ffff, 0x417a6800, 0x59cc0001,
+	0x82000500, 0x00ffffff, 0x4802601e, 0x0401f7f0,
+	0x59cc0001, 0x4803c857, 0x0401ff10, 0x040207d5,
+	0x0201f800, 0x001045a6, 0x040207d2, 0x59cc0005,
+	0x8c000500, 0x04020004, 0x59340200, 0x8c00050e,
+	0x040207cc, 0x0201f800, 0x001049f3, 0x0402000f,
+	0x0401f83e, 0x040007c7, 0x0201f800, 0x0002075a,
+	0x040007c4, 0x49366009, 0x4a026406, 0x00000002,
+	0x59cc0c04, 0x48066202, 0x42027000, 0x00000088,
+	0x0201f000, 0x000207a1, 0x0201f800, 0x0002075a,
+	0x040007b8, 0x49366009, 0x4a026406, 0x00000004,
+	0x59cc0c04, 0x48066202, 0x42027000, 0x00000001,
+	0x0201f000, 0x000207a1, 0x59cc0004, 0x4803c857,
+	0x59cc0802, 0x8c040d2e, 0x0400000b, 0x0401f81f,
+	0x04000009, 0x0401f960, 0x04020007, 0x59cc0a04,
+	0x48066202, 0x42027000, 0x00000089, 0x0201f000,
+	0x000207a1, 0x4933c857, 0x1c01f000, 0x59cc0004,
+	0x4803c857, 0x59cc0802, 0x8c040d2e, 0x0400000b,
+	0x0401f80e, 0x04000009, 0x0401f94f, 0x04020007,
+	0x59cc0a04, 0x48066202, 0x42027000, 0x0000008a,
+	0x0201f000, 0x000207a1, 0x4933c857, 0x1c01f000,
+	0x59cc0a04, 0x0401f002, 0x59cc0c04, 0x59a8000e,
+	0x59a81067, 0x80080400, 0x80040480, 0x04021008,
+	0x40040000, 0x800000c4, 0x800408ca, 0x80040c00,
+	0x82066400, 0x0010d1c0, 0x1c01f000, 0x80000580,
+	0x0401f7fe, 0x59cc0802, 0x8c040d2e, 0x04020010,
+	0x0401ffec, 0x0400000e, 0x59cc0001, 0x82000500,
+	0x00ffffff, 0x59326809, 0x59340802, 0x82040d00,
+	0x00ffffff, 0x80040580, 0x04020005, 0x42027000,
+	0x00000051, 0x0201f000, 0x000207a1, 0x59cc0004,
+	0x4803c857, 0x1c01f000, 0x4803c856, 0x42003000,
+	0x00000105, 0x0401f001, 0x4803c856, 0x4c3c0000,
+	0x41cc7800, 0x0401f803, 0x5c007800, 0x1c01f000,
+	0x4803c856, 0x4c580000, 0x583c0400, 0x82000500,
+	0x0000f000, 0x82000580, 0x0000c000, 0x04000024,
+	0x0201f800, 0x0002075a, 0x04000021, 0x4c180000,
+	0x583c0001, 0x0401fe89, 0x0402001f, 0x0201f800,
+	0x001045a6, 0x0402001c, 0x49366009, 0x0201f800,
+	0x001007e4, 0x04000018, 0x492e6017, 0x497a5800,
+	0x497a5a04, 0x48125c04, 0x832cac00, 0x00000005,
+	0x4200b000, 0x00000007, 0x403ca000, 0x0201f800,
+	0x0010ab17, 0x5c003000, 0x481a641a, 0x4a026403,
+	0x0000003e, 0x4a026406, 0x00000001, 0x4a026203,
+	0x00000001, 0x0201f800, 0x0010672b, 0x5c00b000,
+	0x1c01f000, 0x0201f800, 0x0002077d, 0x5c003000,
+	0x0401f7fb, 0x4803c856, 0x59cc0400, 0x82000d00,
+	0x0000ff00, 0x82040500, 0x0000f000, 0x840409c0,
+	0x82000580, 0x00002000, 0x04020049, 0x82040580,
+	0x00000022, 0x0402003a, 0x59c400a4, 0x82000500,
+	0x0000000f, 0x82000c80, 0x00000007, 0x04001004,
+	0x82000480, 0x0000000c, 0x0400103f, 0x59cc0006,
+	0x82000500, 0xffff0000, 0x82000d80, 0x04000000,
+	0x04000039, 0x82000d80, 0x60000000, 0x04000036,
+	0x82000d80, 0x54000000, 0x04000033, 0x82000d80,
+	0x03000000, 0x04020015, 0x59a80826, 0x8c040d02,
+	0x0402002d, 0x8c040d08, 0x0402002b, 0x0201f800,
+	0x001048ec, 0x0400002b, 0x59a8001d, 0x800000d0,
+	0x59a80810, 0x82040d00, 0x000000ff, 0x80040540,
+	0x59cc0800, 0x82040d00, 0x00ffffff, 0x80040580,
+	0x0402001b, 0x0401f01c, 0x59c40802, 0x8c040d0c,
+	0x04020017, 0x82000d80, 0x52000000, 0x040007ec,
+	0x82000d80, 0x05000000, 0x040007e9, 0x82000d80,
+	0x50000000, 0x040007e6, 0x0401f00d, 0x82040580,
+	0x00000023, 0x0402000a, 0x0401ff58, 0x04000008,
+	0x59300c03, 0x82040580, 0x00000002, 0x04000006,
+	0x82040580, 0x00000051, 0x04000003, 0x80000580,
+	0x0401f003, 0x82000540, 0x00000001, 0x1c01f000,
+	0x59cc0006, 0x82000500, 0xffff0000, 0x82000d80,
+	0x03000000, 0x04000004, 0x82000d80, 0x52000000,
+	0x040207f3, 0x59a80026, 0x82000500, 0x00000009,
+	0x82000580, 0x00000008, 0x040007ef, 0x0401f7ec,
+	0x4803c856, 0x4c5c0000, 0x4c580000, 0x59a80016,
+	0x82000580, 0x0000004c, 0x0402001f, 0x59ccb807,
+	0x9c5cb9c0, 0x825cbd00, 0x00000007, 0x8c5cbd00,
+	0x0400000a, 0x4200b000, 0x00000002, 0x83a81c00,
+	0x00000002, 0x83cc1400, 0x0000000d, 0x0201f800,
+	0x0010855a, 0x04020010, 0x8c5cbd02, 0x0400000a,
+	0x4200b000, 0x00000002, 0x83a81c00, 0x00000000,
+	0x83cc1400, 0x0000000f, 0x0201f800, 0x0010855a,
+	0x04020005, 0x8c5cbd04, 0x04000003, 0x82000540,
+	0x00000001, 0x5c00b000, 0x5c00b800, 0x1c01f000,
+	0x4803c856, 0x4c5c0000, 0x4c580000, 0x59a80016,
+	0x82000580, 0x0000004c, 0x0402001f, 0x59ccb807,
+	0x9c5cb9c0, 0x825cbd00, 0x00000007, 0x8c5cbd00,
+	0x0400000a, 0x4200b000, 0x00000002, 0x83a81c00,
+	0x00000002, 0x83cc1400, 0x00000009, 0x0201f800,
+	0x0010855a, 0x04020010, 0x8c5cbd02, 0x0400000a,
+	0x4200b000, 0x00000002, 0x83a81c00, 0x00000000,
+	0x83cc1400, 0x0000000b, 0x0201f800, 0x0010855a,
+	0x04020005, 0x8c5cbd04, 0x04000003, 0x82000540,
+	0x00000001, 0x5c00b000, 0x5c00b800, 0x1c01f000,
+	0x4803c857, 0x4c580000, 0x40003000, 0x42002000,
+	0x000007f0, 0x4200b000, 0x00000010, 0x83ac7400,
+	0x000007f0, 0x50380000, 0x80026d40, 0x04000006,
+	0x59340002, 0x82000500, 0x00ffffff, 0x80180580,
+	0x04000010, 0x80102000, 0x80387000, 0x8058b040,
+	0x040207f5, 0x82100480, 0x00000800, 0x42002000,
+	0x00000000, 0x4200b000, 0x000007f0, 0x41ac7000,
+	0x040217ed, 0x82000540, 0x00000001, 0x0401f002,
+	0x40128800, 0x5c00b000, 0x1c01f000, 0x59a80026,
+	0x8c00050e, 0x04000004, 0x8c000502, 0x04000003,
+	0x80000580, 0x1c01f000, 0x82000540, 0x00000001,
+	0x0401f7fd, 0x59300c06, 0x82040580, 0x00000002,
+	0x04000006, 0x82040580, 0x00000005, 0x04000003,
+	0x82000540, 0x00000001, 0x1c01f000, 0x59c80000,
+	0x84000558, 0x84000512, 0x48039000, 0x1c01f000,
+	0x4a03281a, 0x000003e8, 0x4a032802, 0x0010d1c0,
+	0x4a032800, 0x00000000, 0x4a032808, 0x00107049,
+	0x42000000, 0x00000005, 0x83947c00, 0x00000009,
+	0x49787801, 0x4a007802, 0x00106fff, 0x823c7c00,
+	0x00000003, 0x80000040, 0x040207fa, 0x4a032819,
+	0xffff0000, 0x4201d000, 0x00000064, 0x0401f96e,
+	0x4201d000, 0x000186a0, 0x0401f184, 0x00000000,
+	0x00000003, 0x00000006, 0x00000009, 0x0000000c,
+	0x4d300000, 0x4d2c0000, 0x4d340000, 0x4d400000,
+	0x4cfc0000, 0x4d380000, 0x4d3c0000, 0x4d440000,
+	0x4d4c0000, 0x4d480000, 0x4c5c0000, 0x4c600000,
+	0x4c640000, 0x4cc80000, 0x4ccc0000, 0x0201f800,
+	0x0002057b, 0x5c019800, 0x5c019000, 0x5c00c800,
+	0x5c00c000, 0x5c00b800, 0x5c029000, 0x5c029800,
+	0x5c028800, 0x5c027800, 0x5c027000, 0x5c01f800,
+	0x5c028000, 0x5c026800, 0x5c025800, 0x5c026000,
+	0x1c01f000, 0x59940004, 0x80000540, 0x0402000a,
+	0x59940025, 0x80040400, 0x02001800, 0x001005d8,
+	0x48032804, 0x480b2805, 0x4a032803, 0x0000000a,
+	0x80000580, 0x1c01f000, 0x5994001f, 0x80000540,
+	0x0402000a, 0x59940025, 0x80040400, 0x02001800,
+	0x001005d8, 0x4803281f, 0x480b2820, 0x4a03281e,
+	0x00000001, 0x80000580, 0x1c01f000, 0x59940022,
+	0x80000540, 0x0402000a, 0x59940025, 0x80040400,
+	0x02001800, 0x001005d8, 0x48032822, 0x480b2823,
+	0x4a032821, 0x0000000a, 0x80000580, 0x1c01f000,
+	0x4c000000, 0x59940005, 0x4803c857, 0x480bc857,
+	0x80080580, 0x04020003, 0x497b2804, 0x497b2805,
+	0x5c000000, 0x1c01f000, 0x4c000000, 0x59940020,
+	0x4803c857, 0x480bc857, 0x80080580, 0x04020003,
+	0x497b281f, 0x497b2820, 0x5c000000, 0x1c01f000,
+	0x4c000000, 0x59940023, 0x4803c857, 0x480bc857,
+	0x80080580, 0x04020003, 0x497b2822, 0x497b2823,
+	0x5c000000, 0x1c01f000, 0x4937c857, 0x48ebc857,
+	0x59340203, 0x80e80480, 0x04001002, 0x48ea6a03,
+	0x1c01f000, 0x5c03e000, 0x1c01f000, 0x4d440000,
+	0x42007800, 0x00000010, 0x59968801, 0x0201f800,
+	0x00020245, 0x04020012, 0x59341a03, 0x800c1840,
+	0x0400100f, 0x59940027, 0x800c0480, 0x04000003,
+	0x48026a03, 0x0402100a, 0x5934000f, 0x497a6a03,
+	0x80000540, 0x04000006, 0x4c3c0000, 0x5934140b,
+	0x0201f800, 0x00020253, 0x5c007800, 0x81468800,
+	0x83440480, 0x00000800, 0x04021007, 0x803c7840,
+	0x040207e7, 0x49472801, 0x5c028800, 0x5c03e000,
+	0x1c01f000, 0x4a032800, 0x00000002, 0x497b2801,
+	0x0401f7fa, 0x42007800, 0x00000010, 0x59966002,
+	0x59300205, 0x80000d40, 0x04000006, 0x59940027,
+	0x80040480, 0x48026205, 0x0400102d, 0x0400002c,
+	0x59300206, 0x80000d40, 0x04000014, 0x59b800e4,
+	0x8c000524, 0x04020011, 0x4a0370e4, 0x00030000,
+	0x40000000, 0x59b800e4, 0x8c000524, 0x04000004,
+	0x4a0370e4, 0x00020000, 0x0401f008, 0x59940027,
+	0x80040480, 0x48026206, 0x4a0370e4, 0x00020000,
+	0x0400101c, 0x0400001b, 0x83326400, 0x00000024,
+	0x49332802, 0x41540000, 0x81300480, 0x04021005,
+	0x803c7840, 0x040207db, 0x5c03e000, 0x1c01f000,
+	0x59940026, 0x48032827, 0x4a032802, 0x0010d1c0,
+	0x497b2826, 0x80000540, 0x0400000f, 0x4a032800,
+	0x00000001, 0x5c03e000, 0x1c01f000, 0x4c3c0000,
+	0x0201f800, 0x001091db, 0x5c007800, 0x0401f7d1,
+	0x4c3c0000, 0x0201f800, 0x00108d5d, 0x5c007800,
+	0x0401f7e2, 0x4a032800, 0x00000000, 0x5c03e000,
+	0x1c01f000, 0x59a8086b, 0x8c040d30, 0x04020029,
+	0x8c040d32, 0x0400000f, 0x59a80069, 0x81640480,
+	0x04001019, 0x59a8000b, 0x81500580, 0x04000005,
+	0x59a8006a, 0x59a81066, 0x80080580, 0x04020012,
+	0x900411c0, 0x82081500, 0x00007000, 0x0401f012,
+	0x82040500, 0x0000001f, 0x04000016, 0x80040840,
+	0x82040500, 0x0000001f, 0x04000003, 0x4807506b,
+	0x0401f010, 0x900401c0, 0x82000500, 0x0000001f,
+	0x80040d40, 0x900401c0, 0x80040580, 0x82001500,
+	0x00007000, 0x82040500, 0xffff8fff, 0x80080540,
+	0x4803506b, 0x80081114, 0x0201f800, 0x001006e2,
+	0x1c01f000, 0x4a032807, 0x000007d0, 0x4a032806,
+	0x0000000a, 0x1c01f000, 0x42000800, 0x000007d0,
+	0x83180480, 0x00000005, 0x02021800, 0x001005d8,
+	0x83947c00, 0x00000009, 0x83180400, 0x00105f43,
+	0x50000000, 0x803c7c00, 0x48047801, 0x4a007800,
+	0x0000000a, 0x1c01f000, 0x83180480, 0x00000005,
+	0x02021800, 0x001005d8, 0x83947c00, 0x00000009,
+	0x83180400, 0x00105f43, 0x50000000, 0x803c7c00,
+	0x49787801, 0x1c01f000, 0x4807c857, 0x480bc857,
+	0x59940025, 0x80040400, 0x02001800, 0x001005d8,
+	0x48032804, 0x480b2805, 0x4a032803, 0x0000000a,
+	0x1c01f000, 0x4807c857, 0x480bc857, 0x59940025,
+	0x80040400, 0x02001800, 0x001005d8, 0x4803281c,
+	0x480b281d, 0x4a03281b, 0x0000000a, 0x1c01f000,
+	0x4c000000, 0x5994001d, 0x4803c857, 0x480bc857,
+	0x80080580, 0x04020003, 0x4803281c, 0x4803281d,
+	0x5c000000, 0x1c01f000, 0x80e9d1c0, 0x0400000e,
+	0x0401f836, 0x04025000, 0x4203e000, 0x80000000,
+	0x40e81000, 0x41780800, 0x42000000, 0x00000064,
+	0x0201f800, 0x001066a0, 0x59940024, 0x80080400,
+	0x48032824, 0x1c01f000, 0x42001000, 0x00105065,
+	0x0401fef0, 0x42001000, 0x00105058, 0x0401ffe1,
+	0x42001000, 0x00104148, 0x0401feea, 0x42001000,
+	0x001041bc, 0x0401fee7, 0x42001000, 0x001041f3,
+	0x0401f6f8, 0x4203e000, 0x70000000, 0x4203e000,
+	0xb0300000, 0x41fc0000, 0x40ebf800, 0x80e80480,
+	0x04001011, 0x04000004, 0x82000480, 0x00000003,
+	0x0402100d, 0x42000000, 0x0000000f, 0x04004004,
+	0x80000040, 0x040207fe, 0x0401f007, 0x4203e000,
+	0x70000000, 0x42000000, 0x0010b87e, 0x0201f800,
+	0x0010aa47, 0x1c01f000, 0x4203e000, 0x80000000,
+	0x4203e000, 0xb0400000, 0x41fc0000, 0x40ebf800,
+	0x80e80480, 0x04001011, 0x04000004, 0x82000480,
+	0x00000003, 0x0402100d, 0x42000000, 0x0000000f,
+	0x04005004, 0x80000040, 0x040207fe, 0x0401f007,
+	0x4203e000, 0x80000000, 0x42000000, 0x0010b87f,
+	0x0201f800, 0x0010aa47, 0x1c01f000, 0x59a8000e,
+	0x82000480, 0x00000100, 0x599c0a02, 0x800409c0,
+	0x04020002, 0x80040800, 0x80041480, 0x04001002,
+	0x40000800, 0x48075067, 0x59a8100e, 0x40040000,
+	0x800acc80, 0x4967500e, 0x49675069, 0x59aaa80b,
+	0x41640800, 0x42001000, 0x00000024, 0x0201f800,
+	0x00106681, 0x8206a400, 0x0010d1c0, 0x49535065,
+	0x4152b000, 0x42006000, 0x0010be65, 0x4a006004,
+	0x0000012c, 0x4a006005, 0xda10da10, 0x4a006008,
+	0x00000011, 0x4a006009, 0x0010be65, 0x4a00600a,
+	0x001010b8, 0x599c0014, 0x48006011, 0x599c0015,
+	0x48006012, 0x42006000, 0x0010be41, 0x4a006203,
+	0x00000008, 0x4a006406, 0x00000006, 0x4a006002,
+	0xffff0000, 0x4a006008, 0x0010be65, 0x4a006014,
+	0x0010be65, 0x599c0014, 0x48006015, 0x599c0015,
+	0x48006016, 0x599c0413, 0x48006017, 0x49506018,
+	0x49546019, 0x59a80067, 0x4800601a, 0x4a00601b,
+	0x0010b465, 0x4a00601c, 0x0010b466, 0x4a00601d,
+	0x0010b46a, 0x42000000, 0xb0000000, 0x42000800,
+	0x0010be41, 0x0201f800, 0x00100b68, 0x1c01f000,
+	0x82000d00, 0x000000c0, 0x04000004, 0x82040d80,
+	0x000000c0, 0x04020055, 0x82000d00, 0x00002020,
+	0x59300414, 0x84000512, 0x82040d80, 0x00002020,
+	0x0400000b, 0x8c000514, 0x0402000f, 0x48026414,
+	0x813e79c0, 0x02020000, 0x000206d0, 0x42027000,
+	0x00000043, 0x0201f000, 0x000207a1, 0x59326809,
+	0x59340a00, 0x8c040d0a, 0x040007f3, 0x84000552,
+	0x0401f7f1, 0x84000514, 0x592c080d, 0x48066015,
+	0x0401f7ef, 0x59326809, 0x59340a00, 0x8c040d0a,
+	0x02000000, 0x000206e3, 0x59300c14, 0x84040d52,
+	0x48066414, 0x0201f000, 0x000206e3, 0x0201f800,
+	0x00020086, 0x813e79c0, 0x02020000, 0x000206d0,
+	0x0201f000, 0x000206f1, 0x8c00051e, 0x02000000,
+	0x000206fd, 0x82000d00, 0x00002020, 0x82040d80,
+	0x00002020, 0x04000014, 0x82000500, 0x000000c0,
+	0x82000d80, 0x00000080, 0x04000008, 0x813e79c0,
+	0x02020000, 0x000206d0, 0x42027000, 0x00000041,
+	0x0201f000, 0x000207a1, 0x813e79c0, 0x02020000,
+	0x000206d0, 0x42027000, 0x00000043, 0x0201f000,
+	0x000207a1, 0x59326809, 0x59340a00, 0x8c040d0a,
+	0x040007ea, 0x59300c14, 0x84040d52, 0x48066414,
+	0x0401f7e6, 0x492fc857, 0x42000800, 0x00000006,
+	0x0201f000, 0x000206f8, 0x492fc857, 0x42000800,
+	0x00000004, 0x0201f000, 0x000206f8, 0x4807c856,
+	0x59a80068, 0x800409c0, 0x04000003, 0x80080540,
+	0x0401f002, 0x80080500, 0x48035068, 0x1c01f000,
+	0x4a030800, 0x00000000, 0x4a030802, 0x00000001,
+	0x497b0803, 0x497b0804, 0x1c01f000, 0x59840002,
+	0x8c000500, 0x04000004, 0x84000500, 0x4a030800,
+	0x00000001, 0x84000544, 0x84000506, 0x48030802,
+	0x82000d00, 0x0fffffff, 0x42000000, 0x90000000,
+	0x0201f800, 0x00100b94, 0x59a80069, 0x82000480,
+	0x00000007, 0x48035069, 0x80000580, 0x42000800,
+	0x0010b519, 0x48000800, 0x48000801, 0x1c01f000,
+	0x59a80069, 0x82000480, 0x00000007, 0x48035069,
+	0x1c01f000, 0x83640480, 0x00000008, 0x0400101b,
+	0x58c80a03, 0x80000580, 0x82000400, 0x00000008,
+	0x80040840, 0x040207fd, 0x815c0480, 0x04001013,
+	0x4200b000, 0x00000007, 0x0201f800, 0x0002075a,
+	0x4a026203, 0x00000004, 0x4a026406, 0x00000009,
+	0x4a026203, 0x00000004, 0x4a026007, 0x00000101,
+	0x0401f809, 0x0401f880, 0x8058b040, 0x040207f3,
+	0x80000580, 0x1c01f000, 0x82000540, 0x00000001,
+	0x0401f7fd, 0x0201f800, 0x001007e4, 0x492e6008,
+	0x58c80a03, 0x4a025a04, 0x0000002c, 0x497a5800,
+	0x497a5801, 0x497a5c04, 0x497a5c06, 0x497a5805,
+	0x4a025a08, 0x00000005, 0x4a025a07, 0x00000002,
+	0x58c80201, 0x48025c04, 0x58c80202, 0x48025c07,
+	0x58c80204, 0x48025c08, 0x4a02580d, 0x0000ffff,
+	0x80040840, 0x0400000c, 0x412c2000, 0x0201f800,
+	0x001007e4, 0x4a025a04, 0x0000000a, 0x497a5c04,
+	0x48125800, 0x492c2001, 0x412c2000, 0x80040840,
+	0x040207f7, 0x1c01f000, 0x4d7c0000, 0x4202f800,
+	0x00000010, 0x4df00000, 0x4203e000, 0x50000000,
+	0x59847803, 0x803c79c0, 0x0400001e, 0x4c5c0000,
+	0x583cb808, 0x585c3408, 0x801831c0, 0x0400000b,
+	0x0401f84a, 0x04000016, 0x42001000, 0x0010b519,
+	0x0401f87f, 0x04000012, 0x0201f800, 0x001007d3,
+	0x0400000f, 0x492cb805, 0x585c0005, 0x80000540,
+	0x02000800, 0x001005d8, 0x0401f830, 0x585c5408,
+	0x0401f80b, 0x5c00b800, 0x5c03e000, 0x817ef840,
+	0x040207e1, 0x5c02f800, 0x1c01f000, 0x5c00b800,
+	0x5c03e000, 0x5c02f800, 0x1c01f000, 0x4803c856,
+	0x405c6000, 0x802851c0, 0x04000018, 0x585c0204,
+	0x82000d00, 0x0000000f, 0x82040c00, 0x001010bd,
+	0x50044000, 0x4cf00000, 0x4d000000, 0x4d040000,
+	0x4021e000, 0x40320800, 0x59860004, 0x4c280000,
+	0x0401f934, 0x5c005000, 0x40f04000, 0x41046000,
+	0x0201f800, 0x0010109b, 0x040207f6, 0x5c020800,
+	0x5c020000, 0x5c01e000, 0x58c80204, 0x4800bc08,
+	0x0201f800, 0x00020086, 0x4a026007, 0x00000101,
+	0x497a6009, 0x0401f055, 0x4803c856, 0x59840003,
+	0x80026540, 0x04000003, 0x59300000, 0x48030803,
+	0x1c01f000, 0x4803c856, 0x59840003, 0x48026000,
+	0x49330803, 0x1c01f000, 0x58cc0805, 0x40180000,
+	0x80040480, 0x0400100d, 0x82cc0580, 0x0010b50e,
+	0x02020800, 0x001005d8, 0x58c80205, 0x80040480,
+	0x0400101d, 0x82000540, 0x00000001, 0x1c01f000,
+	0x80003580, 0x0401f7fe, 0x82cc0580, 0x0010b50e,
+	0x02020800, 0x001005d8, 0x58c80400, 0x8c000504,
+	0x040007f8, 0x58c8040b, 0x8c00051e, 0x040007f5,
+	0x8c000500, 0x040207f3, 0x84000540, 0x4801940b,
+	0x42000000, 0x0010b839, 0x0201f800, 0x0010aa47,
+	0x42001000, 0x00008026, 0x0201f800, 0x00103a3e,
+	0x0401f7e8, 0x58c8040b, 0x8c00051e, 0x040007e2,
+	0x8c000502, 0x040207e0, 0x84000542, 0x4801940b,
+	0x42000000, 0x0010b838, 0x0201f800, 0x0010aa47,
+	0x42001000, 0x00008025, 0x42001800, 0x00000000,
+	0x0201f800, 0x00103a3e, 0x0401f7d3, 0x4803c856,
+	0x58080000, 0x42001800, 0x00000007, 0x58080801,
+	0x80040480, 0x04020004, 0x400c0000, 0x80000540,
+	0x0401f005, 0x04001003, 0x800c0480, 0x0401f002,
+	0x80000080, 0x1c01f000, 0x4803c856, 0x59300008,
+	0x80000d40, 0x02000800, 0x001005d8, 0x58040005,
+	0x80000540, 0x02000800, 0x001005d8, 0x59300007,
+	0x82000500, 0x00000101, 0x82000580, 0x00000101,
+	0x02020800, 0x001005d8, 0x42001000, 0x0010b519,
+	0x58080801, 0x82040400, 0x0010b51b, 0x497a6414,
+	0x4a026015, 0x0000ffff, 0x45300000, 0x80040800,
+	0x82040480, 0x00000008, 0x04001002, 0x80000d80,
+	0x48041001, 0x82040400, 0x0010b51b, 0x45780000,
+	0x1c01f000, 0x4933c857, 0x59300808, 0x800409c0,
+	0x02000800, 0x001005d8, 0x4d2c0000, 0x58065805,
+	0x812e59c0, 0x02020800, 0x001007f4, 0x49780805,
+	0x40065800, 0x0201f800, 0x001007fd, 0x5c025800,
+	0x4d300000, 0x0201f800, 0x0002077d, 0x5c026000,
+	0x1c01f000, 0x59300406, 0x82000580, 0x00000009,
+	0x04020006, 0x59300007, 0x8c000510, 0x04000003,
+	0x80000580, 0x1c01f000, 0x82000540, 0x00000001,
+	0x1c01f000, 0x59840802, 0x8c040d04, 0x1c01f000,
+	0x4803c856, 0x59840802, 0x84040d04, 0x84040d40,
+	0x4a030800, 0x00000000, 0x48070802, 0x82040d00,
+	0x0fffffff, 0x42000000, 0x90000000, 0x0201f000,
+	0x00100b94, 0x4807c857, 0x4805980a, 0x49799801,
+	0x49799803, 0x49799806, 0x49799807, 0x49799808,
+	0x49799805, 0x49799809, 0x0401f8c9, 0x0400000a,
+	0x0401f8eb, 0x04000008, 0x48359800, 0x48359802,
+	0x48359806, 0x4a019804, 0x00000001, 0x4a019807,
+	0x00000005, 0x1c01f000, 0x4807c857, 0x58cc1007,
+	0x40040000, 0x80080480, 0x04021020, 0x4c040000,
+	0x4c080000, 0x0401f8da, 0x5c001000, 0x5c000800,
+	0x0400001c, 0x58cc0006, 0x80006540, 0x0402000b,
+	0x48359800, 0x48359802, 0x48359806, 0x49799801,
+	0x49799803, 0x49786801, 0x49786800, 0x49799804,
+	0x49799807, 0x0401f005, 0x48306801, 0x48346000,
+	0x48359806, 0x49786800, 0x58cc0004, 0x58cc1007,
+	0x80000000, 0x82081400, 0x00000005, 0x48019804,
+	0x48099807, 0x0401f7df, 0x80000580, 0x1c01f000,
+	0x82000540, 0x00000001, 0x1c01f000, 0x480bc857,
+	0x4c500000, 0x4c540000, 0x4c580000, 0x40083000,
+	0x58cc0801, 0x82040480, 0x00000005, 0x02021800,
+	0x001005d8, 0x82040400, 0x00106418, 0x50000000,
+	0x58cca800, 0x8054ac00, 0x42001800, 0x00000005,
+	0x40040000, 0x800c0480, 0x80082480, 0x04021002,
+	0x40080000, 0x8000b0c2, 0x8058b400, 0x5450a800,
+	0x8050a000, 0x8054a800, 0x8058b040, 0x040207fc,
+	0x40001000, 0x58cc2805, 0x58cc0807, 0x58cc2001,
+	0x80142c00, 0x80040c80, 0x80102400, 0x48159805,
+	0x48059807, 0x48119801, 0x82100580, 0x00000005,
+	0x0400000c, 0x48119801, 0x40080000, 0x80181480,
+	0x40083000, 0x04000003, 0x040217d6, 0x80000580,
+	0x5c00b000, 0x5c00a800, 0x5c00a000, 0x1c01f000,
+	0x58cc0800, 0x800409c0, 0x02000800, 0x001005d8,
+	0x58040800, 0x48059800, 0x41782000, 0x0401f7ee,
+	0x0401f813, 0x50f00000, 0x81040400, 0x40001800,
+	0x585c0204, 0x4803c857, 0x82000580, 0x0000002c,
+	0x02020800, 0x001005d8, 0x58040202, 0x800000e0,
+	0x81000540, 0x48001802, 0x58040000, 0x48001800,
+	0x58040001, 0x48001801, 0x1c01f000, 0x4807c856,
+	0x58cc0005, 0x80000040, 0x02001800, 0x001005d8,
+	0x48019805, 0x58cc1003, 0x82080480, 0x00000005,
+	0x02021800, 0x001005d8, 0x82080400, 0x00106418,
+	0x50000000, 0x58cc0802, 0x80040c00, 0x80081000,
+	0x82080480, 0x00000005, 0x0402000f, 0x58cc2002,
+	0x58100000, 0x80006d40, 0x04000009, 0x4c340000,
+	0x0401f858, 0x5c006800, 0x49786801, 0x48359802,
+	0x58cc0004, 0x80000040, 0x48019804, 0x49799803,
+	0x0401f002, 0x48099803, 0x1c01f000, 0x4807c856,
+	0x41781800, 0x58c80201, 0x80000540, 0x04000002,
+	0x800c1800, 0x58c80c01, 0x80040c80, 0x0400100a,
+	0x04000009, 0x800c1800, 0x58c80202, 0x80041480,
+	0x04001005, 0x04000004, 0x800c1800, 0x40080800,
+	0x0401f7fb, 0x480d9204, 0x400c0000, 0x42002000,
+	0x00000001, 0x80000040, 0x04000007, 0x04001006,
+	0x80102000, 0x82000480, 0x00000005, 0x04000002,
+	0x040217fc, 0x48119203, 0x1c01f000, 0x4807c856,
+	0x4d2c0000, 0x58cc000a, 0x80000540, 0x02000800,
+	0x001005d8, 0x82002400, 0x00000005, 0x0201f800,
+	0x001007d3, 0x04000012, 0x492d9809, 0x497a5800,
+	0x497a5801, 0x0201f800, 0x001007d3, 0x0400000c,
+	0x58cc0009, 0x48025800, 0x497a5801, 0x492d9809,
+	0x82102480, 0x00000005, 0x040217f7, 0x82000540,
+	0x00000001, 0x5c025800, 0x1c01f000, 0x58cc0009,
+	0x80025d40, 0x040007fc, 0x592c2000, 0x0201f800,
+	0x001007f4, 0x40100000, 0x0401f7fa, 0x58cc0009,
+	0x48cfc857, 0x80006d40, 0x04000005, 0x50340000,
+	0x48019809, 0x49786800, 0x49786801, 0x1c01f000,
+	0x4813c857, 0x58cc0009, 0x48002000, 0x48119809,
+	0x1c01f000, 0x4807c856, 0x4d2c0000, 0x58cc0009,
+	0x80025d40, 0x04000007, 0x592c0000, 0x4c000000,
+	0x0201f800, 0x001007f4, 0x5c000000, 0x0401f7f9,
+	0x5c025800, 0x1c01f000, 0x4807c856, 0x4d2c0000,
+	0x58cc0002, 0x80025d40, 0x04000007, 0x592c0000,
+	0x4c000000, 0x0201f800, 0x001007f4, 0x5c000000,
+	0x0401f7f9, 0x49799800, 0x49799802, 0x49799801,
+	0x49799803, 0x49799806, 0x49799807, 0x49799808,
+	0x49799809, 0x4979980a, 0x5c025800, 0x1c01f000,
+	0x00000003, 0x00000006, 0x00000009, 0x0000000c,
+	0x0000000f, 0x00000012, 0x4803c856, 0x0401f857,
+	0x4a00c204, 0x0000003c, 0x59301009, 0x82080580,
+	0x0010b524, 0x04000013, 0x58080802, 0x82040d00,
+	0x00ffffff, 0x58080403, 0x4804c005, 0x4800c406,
+	0x4a00c207, 0x00000003, 0x59300811, 0x585c0404,
+	0x4978c206, 0x4804c407, 0x80000540, 0x0400000d,
+	0x58600206, 0x84000540, 0x4800c206, 0x0401f009,
+	0x585c080a, 0x82040d00, 0x00ffffff, 0x4804c005,
+	0x4a00c406, 0x000007ff, 0x4978c207, 0x0401f7ef,
+	0x82603c00, 0x00000008, 0x58605404, 0x40282000,
+	0x405c6000, 0x585c0a04, 0x82040d00, 0x0000000f,
+	0x82040c00, 0x001010bd, 0x50044000, 0x80004d80,
+	0x50200000, 0x80307400, 0x58380402, 0x8c244d00,
+	0x04020003, 0x48003a00, 0x0401f003, 0x48003c00,
+	0x801c3800, 0x80244800, 0x80102040, 0x04000006,
+	0x0201f800, 0x0010109b, 0x02000800, 0x001005d8,
+	0x0401f7f0, 0x1c01f000, 0x4803c856, 0x4d340000,
+	0x59300009, 0x80026d40, 0x02000800, 0x001005d8,
+	0x59340401, 0x80000540, 0x0400000e, 0x59840000,
+	0x80000540, 0x0400000b, 0x836c0580, 0x00000003,
+	0x04020008, 0x59341c03, 0x42002000, 0x00000004,
+	0x42003000, 0x00000004, 0x0201f800, 0x00103aae,
+	0x5c026800, 0x1c01f000, 0x4803c856, 0x80001580,
+	0x58c80c01, 0x59300011, 0x80040c80, 0x48066011,
+	0x58c80201, 0x80000540, 0x04000005, 0x80081000,
+	0x80040c80, 0x04001007, 0x04000006, 0x58c80202,
+	0x80081000, 0x80040c80, 0x04001002, 0x040207fd,
+	0x4808bc08, 0x4808c404, 0x1c01f000, 0x4803c856,
+	0x4a0370e5, 0x00020000, 0x59b800e5, 0x8c000524,
+	0x040207fc, 0x4a0370e5, 0x00030000, 0x40000000,
+	0x40000000, 0x59b800e5, 0x8c000524, 0x040207f5,
+	0x5934000e, 0x80006d40, 0x04000010, 0x81300580,
+	0x04020004, 0x58340000, 0x4802680e, 0x0401f00a,
+	0x40347800, 0x58340000, 0x80006d40, 0x02000800,
+	0x001005d8, 0x81300580, 0x040207fa, 0x58340000,
+	0x48007800, 0x497a6000, 0x4a0370e5, 0x00020000,
+	0x1c01f000, 0x4803c856, 0x4d300000, 0x4d2c0000,
+	0x42000800, 0x000003ff, 0x4a0370e5, 0x00020000,
+	0x59b800e5, 0x8c000524, 0x04000005, 0x80040840,
+	0x040207fa, 0x0201f800, 0x001005d8, 0x4a0370e5,
+	0x00030000, 0x40000000, 0x40000000, 0x59b800e5,
+	0x8c000524, 0x040207f1, 0x5934000e, 0x80026540,
+	0x0400000e, 0x4933c857, 0x59300000, 0x4802680e,
+	0x4a026203, 0x00000004, 0x497a6206, 0x497a6009,
+	0x4a026007, 0x00000101, 0x59325808, 0x497a5c08,
+	0x0401fd81, 0x0401f7f1, 0x4a0370e5, 0x00020000,
+	0x5c025800, 0x5c026000, 0x1c01f000, 0x4803c856,
+	0x4c000000, 0x0201f800, 0x00105c9a, 0x04020011,
+	0x0201f800, 0x001045a6, 0x02020800, 0x001005d8,
+	0x5c000000, 0x48026802, 0x0201f800, 0x0002075a,
+	0x04000009, 0x49366009, 0x4a026406, 0x00000001,
+	0x42027000, 0x00000001, 0x0201f000, 0x000207a1,
+	0x5c000000, 0x1c01f000, 0x59300203, 0x82000c80,
+	0x0000000e, 0x02021800, 0x001005d8, 0x4803c857,
+	0x0c01f001, 0x00106503, 0x00106503, 0x00106503,
+	0x00106505, 0x00106565, 0x00106503, 0x00106503,
+	0x001065b7, 0x001065b8, 0x00106503, 0x00106503,
+	0x00106503, 0x00106503, 0x00106503, 0x0201f800,
+	0x001005d8, 0x493bc857, 0x83380480, 0x00000050,
+	0x02021800, 0x001005d8, 0x83380480, 0x00000049,
+	0x02001800, 0x001005d8, 0x0c01f001, 0x00106518,
+	0x0010653a, 0x00106516, 0x00106516, 0x00106516,
+	0x00106516, 0x00106549, 0x0201f800, 0x001005d8,
+	0x4d2c0000, 0x59325808, 0x592c0206, 0x48025c06,
+	0x4a025a06, 0x00000000, 0x4c5c0000, 0x592cbc0a,
+	0x592c0000, 0x48026008, 0x0201f800, 0x00104cde,
+	0x59300008, 0x80000540, 0x04000008, 0x4a026203,
+	0x00000007, 0x42027000, 0x00000043, 0x5c00b800,
+	0x5c025800, 0x0401f08a, 0x8c5cbd08, 0x04020006,
+	0x4a026203, 0x00000007, 0x497a6206, 0x497a6008,
+	0x0401f003, 0x0201f800, 0x0002077d, 0x5c00b800,
+	0x5c025800, 0x1c01f000, 0x0201f800, 0x00106b8a,
+	0x4d2c0000, 0x59325808, 0x0201f800, 0x00109037,
+	0x04000006, 0x4d400000, 0x42028000, 0x00000001,
+	0x0401f8f8, 0x5c028000, 0x5c025800, 0x0201f000,
+	0x0002077d, 0x0201f800, 0x00106b8a, 0x4d3c0000,
+	0x417a7800, 0x0201f800, 0x0010203c, 0x5c027800,
+	0x42003000, 0x00000014, 0x0201f800, 0x0010a942,
+	0x42000000, 0x0010b864, 0x0201f800, 0x0010aa47,
+	0x4d2c0000, 0x59325808, 0x0201f800, 0x00109037,
+	0x04000006, 0x4d400000, 0x42028000, 0x00000029,
+	0x0401f8dc, 0x5c028000, 0x5c025800, 0x0201f000,
+	0x0002077d, 0x493bc857, 0x497a6206, 0x83380480,
+	0x00000054, 0x02021800, 0x001005d8, 0x83380480,
+	0x00000047, 0x02001800, 0x001005d8, 0x0c01f001,
+	0x001065b6, 0x0010657f, 0x0010657d, 0x0010657d,
+	0x0010657d, 0x0010657d, 0x0010657d, 0x0010657d,
+	0x0010657d, 0x0010657d, 0x0010657d, 0x0010657d,
+	0x00106583, 0x0201f800, 0x001005d8, 0x59300011,
+	0x82000500, 0xffff0000, 0x04020034, 0x59840802,
+	0x8c040d04, 0x04000025, 0x59300009, 0x80026d40,
+	0x0400001f, 0x4c5c0000, 0x4c600000, 0x497a6206,
+	0x5930b808, 0x585c0005, 0x8000c540, 0x02000800,
+	0x001005d8, 0x0401fe8d, 0x40625800, 0x0201f800,
+	0x00104cde, 0x4978b805, 0x0401fef5, 0x497a6009,
+	0x585c3408, 0x0401fcbd, 0x0400000e, 0x42001000,
+	0x0010b519, 0x0401fcf2, 0x0400000a, 0x0201f800,
+	0x001007e4, 0x04000007, 0x492cb805, 0x585c5408,
+	0x0401fc83, 0x5c00c000, 0x5c00b800, 0x1c01f000,
+	0x0401fca9, 0x0401f7fc, 0x8c040d06, 0x040207fc,
+	0x59300009, 0x80026d40, 0x04000006, 0x5934000e,
+	0x80000540, 0x02020800, 0x001005d8, 0x497a6009,
+	0x0401fd0d, 0x0401f7f2, 0x0401f06f, 0x4803c856,
+	0x4803c856, 0x83380580, 0x00000043, 0x02020800,
+	0x001005d8, 0x4a026203, 0x00000003, 0x493a6403,
+	0x59325808, 0x592c000f, 0x48026011, 0x497a6013,
+	0x592c0406, 0x800000c2, 0x800010c4, 0x80081400,
+	0x480a6206, 0x0201f800, 0x00100f4e, 0x42000800,
+	0x80000060, 0x0401f154, 0x42000000, 0x0010b875,
+	0x0201f800, 0x0010aa47, 0x59300203, 0x82000c80,
+	0x0000000e, 0x02021800, 0x001005d8, 0x4803c857,
+	0x82000d80, 0x00000003, 0x04000006, 0x82000d80,
+	0x00000004, 0x04000045, 0x0201f800, 0x001005d8,
+	0x0201f800, 0x00106c55, 0x59300004, 0x8c00053e,
+	0x04020007, 0x0201f800, 0x00106b6c, 0x02020800,
+	0x001005d8, 0x0201f000, 0x00106c4b, 0x0401f9c3,
+	0x0201f800, 0x00106c4b, 0x59325808, 0x42028000,
+	0x00000006, 0x0401f84b, 0x0201f000, 0x0002077d,
+	0x4803c856, 0x59300203, 0x82000c80, 0x0000000e,
+	0x02021800, 0x001005d8, 0x82000d80, 0x00000003,
+	0x04000006, 0x82000d80, 0x00000004, 0x04000023,
+	0x0201f800, 0x001005d8, 0x4803c856, 0x0201f800,
+	0x00106c55, 0x4df00000, 0x59300004, 0x8c00053e,
+	0x04020006, 0x0201f800, 0x00106f60, 0x02020800,
+	0x001005d8, 0x0401f010, 0x0201f800, 0x00108cd6,
+	0x04020004, 0x0201f800, 0x00106e62, 0x0402000a,
+	0x0401f99a, 0x02020800, 0x001005d8, 0x5c03e000,
+	0x02000800, 0x00106c4b, 0x82000540, 0x00000001,
+	0x1c01f000, 0x5c03e000, 0x02000800, 0x00106c4b,
+	0x80000580, 0x1c01f000, 0x4933c857, 0x0201f800,
+	0x00100e99, 0x4933c857, 0x4c5c0000, 0x4d340000,
+	0x497a6206, 0x5930b808, 0x59300009, 0x80026d40,
+	0x04020e5f, 0x42001000, 0x0010b519, 0x0401fc60,
+	0x04000009, 0x58c80204, 0x4800bc08, 0x41785000,
+	0x0201f800, 0x00106227, 0x5c026800, 0x5c00b800,
+	0x1c01f000, 0x4978bc08, 0x0401fc17, 0x0401f7fb,
+	0x4803c856, 0x0201f800, 0x00109037, 0x0400000f,
+	0x592c0000, 0x80000d40, 0x04000009, 0x497a5800,
+	0x49425a06, 0x4c040000, 0x0201f800, 0x000202da,
+	0x5c000800, 0x40065800, 0x0401f7f6, 0x49425a06,
+	0x0201f800, 0x000202da, 0x1c01f000, 0x4933c857,
+	0x59300c06, 0x82040580, 0x0000000e, 0x04000004,
+	0x82040580, 0x00000009, 0x04020004, 0x0401ffe5,
+	0x497a6008, 0x80000580, 0x1c01f000, 0x592e6009,
+	0x83300480, 0x0010d1c0, 0x04001016, 0x41580000,
+	0x81300480, 0x04021013, 0x40040000, 0x59300c06,
+	0x80040580, 0x04020012, 0x59300a03, 0x82040580,
+	0x00000007, 0x02020800, 0x001005d8, 0x59300008,
+	0x80000540, 0x02020800, 0x001005d8, 0x0201f800,
+	0x0002077d, 0x42000000, 0x00000000, 0x0401f009,
+	0x42000000, 0x00000008, 0x0401f006, 0x82040580,
+	0x00000007, 0x040207fb, 0x42000000, 0x00000005,
+	0x592c0a06, 0x48065c06, 0x48025a06, 0x0201f000,
+	0x000202da, 0x4c0c0000, 0x4c100000, 0x4c140000,
+	0x4c180000, 0x80001d80, 0x80002580, 0x42003000,
+	0x00000020, 0x82040500, 0x00000001, 0x04000003,
+	0x40080000, 0x800c1c00, 0x400c2800, 0x800c1902,
+	0x80102102, 0x82140500, 0x00000001, 0x04000003,
+	0x82102540, 0x80000000, 0x80040902, 0x80183040,
+	0x040207f1, 0x40100800, 0x400c0000, 0x5c003000,
+	0x5c002800, 0x5c002000, 0x5c001800, 0x1c01f000,
+	0x4c580000, 0x4200b000, 0x00000020, 0x80000540,
+	0x04000018, 0x80041c80, 0x04021016, 0x800810c2,
+	0x80040982, 0x04001006, 0x80041c80, 0x04021005,
+	0x8058b040, 0x040207fa, 0x0401f006, 0x80041c80,
+	0x400c0800, 0x80081000, 0x8058b040, 0x040207f4,
+	0x4c000000, 0x41f00000, 0x82000500, 0xf7ffffff,
+	0x4003e000, 0x5c000000, 0x5c00b000, 0x1c01f000,
+	0x4c000000, 0x41f00000, 0x82000540, 0x08000000,
+	0x0401f7f8, 0x4a0378e8, 0x00000000, 0x4a03c821,
+	0x00000010, 0x4a03c823, 0x00000004, 0x0401f82c,
+	0x4a0378e9, 0x00003a0d, 0x4a0378e8, 0x00000001,
+	0x42000000, 0x00001000, 0x50000000, 0x82000480,
+	0x24220001, 0x04000004, 0x59e00002, 0x84000548,
+	0x4803c002, 0x42000800, 0x00000005, 0x4203a000,
+	0x00007600, 0x42000000, 0x00001000, 0x50000000,
+	0x82000480, 0x24320001, 0x04021003, 0x4a03a005,
+	0xd0000001, 0x59d00006, 0x4a03a005, 0x90000001,
+	0x83d3a400, 0x00000020, 0x80040840, 0x040207fa,
+	0x59e00003, 0x82000500, 0xffffffe0, 0x82000540,
+	0x00008000, 0x4803c003, 0x59c40006, 0x82000500,
+	0xfffcffff, 0x48038806, 0x1c01f000, 0x4d900000,
+	0x4d180000, 0x4a0378e7, 0xaaaaaaaa, 0x4a0378e6,
+	0xaaaaaaaa, 0x4a0378e5, 0xaaaaaaaa, 0x4a0378e4,
+	0xaaaaaaaa, 0x42000800, 0x0000bf00, 0x4a00081a,
+	0x0010b7d4, 0x4a00081b, 0x001010bd, 0x4a00081c,
+	0x001010cd, 0x4a031800, 0x00000000, 0x4a031801,
+	0x0010b544, 0x4a031802, 0x0010b54b, 0x42000800,
+	0x0010b7d7, 0x417a3000, 0x811b20c8, 0x83932400,
+	0x0000bf32, 0x48072000, 0x4a032001, 0x00000000,
+	0x83180400, 0x001070ea, 0x50000000, 0x48032002,
+	0x82040c00, 0x00000003, 0x811a3000, 0x83180480,
+	0x00000005, 0x040017f1, 0x5c023000, 0x5c032000,
+	0x1c01f000, 0x48066004, 0x497a6000, 0x497a6001,
+	0x59bc00ea, 0x8c000516, 0x040207fe, 0x83300400,
+	0xa0000000, 0x480378e1, 0x1c01f000, 0x4933c857,
+	0x42000800, 0x80000040, 0x48066004, 0x497a6000,
+	0x59bc00ea, 0x8c000516, 0x040207fe, 0x83300400,
+	0x60000000, 0x480378e1, 0x1c01f000, 0x0201f800,
+	0x00106c55, 0x4df00000, 0x4d300000, 0x4d340000,
+	0x4d2c0000, 0x4d180000, 0x4c5c0000, 0x4c600000,
+	0x4d900000, 0x4dd00000, 0x4da40000, 0x4d140000,
+	0x42003000, 0x0000bf2e, 0x581a6001, 0x813261c0,
+	0x0400002c, 0x41302800, 0x4178c000, 0x59300000,
+	0x4c000000, 0x59326809, 0x5930b801, 0x59300406,
+	0x82000d80, 0x00000006, 0x04020003, 0x8d3e7d18,
+	0x04000010, 0x8d3e7d06, 0x04000007, 0x82000580,
+	0x00000003, 0x04020004, 0x59340200, 0x8c00050e,
+	0x04020008, 0x0401f92f, 0x4c0c0000, 0x4c140000,
+	0x0401fb5f, 0x5c002800, 0x5c001800, 0x0401f005,
+	0x41301800, 0x8060c1c0, 0x04020002, 0x400cc000,
+	0x805cb9c0, 0x04000003, 0x405e6000, 0x0401f7e3,
+	0x5c026000, 0x813261c0, 0x04000006, 0x8060c1c0,
+	0x04000002, 0x40602800, 0x4178c000, 0x0401f7d8,
+	0x417a3000, 0x0201f800, 0x001070d8, 0x59926004,
+	0x813261c0, 0x04000023, 0x59326809, 0x4130c000,
+	0x59300001, 0x8000bd40, 0x04000016, 0x40026000,
+	0x40602800, 0x5930b801, 0x59300406, 0x82000d80,
+	0x00000006, 0x0400000e, 0x8d3e7d06, 0x04000007,
+	0x82000580, 0x00000003, 0x04020004, 0x59340200,
+	0x8c00050e, 0x04020006, 0x0401f8dc, 0x4c140000,
+	0x0401fb2f, 0x5c002800, 0x0401f002, 0x41302800,
+	0x405e6000, 0x813261c0, 0x040207eb, 0x8060c1c0,
+	0x04000004, 0x40626000, 0x4178c000, 0x0401f7e7,
+	0x811a3000, 0x83180480, 0x00000005, 0x040017d6,
+	0x5c022800, 0x5c034800, 0x5c03a000, 0x5c032000,
+	0x5c00c000, 0x5c00b800, 0x5c023000, 0x5c025800,
+	0x5c026800, 0x5c026000, 0x5c03e000, 0x02000800,
+	0x00106c4b, 0x1c01f000, 0x4933c857, 0x0201f800,
+	0x00106c55, 0x4df00000, 0x4d340000, 0x4d180000,
+	0x4d900000, 0x42003000, 0x0000bf2e, 0x59326809,
+	0x58182001, 0x40102800, 0x801021c0, 0x04000016,
+	0x41300000, 0x80100580, 0x04000011, 0x58100009,
+	0x81340580, 0x0402000b, 0x40101800, 0x58102001,
+	0x41300000, 0x801021c0, 0x0400000b, 0x80100d80,
+	0x04000007, 0x40101800, 0x58102001, 0x0401f7fa,
+	0x40102800, 0x58102000, 0x0401f7ec, 0x0401f8bd,
+	0x0401f01a, 0x42032000, 0x0000bf32, 0x417a3000,
+	0x59902004, 0x40102800, 0x801021c0, 0x0400000b,
+	0x58100009, 0x81340580, 0x04020008, 0x41300000,
+	0x80100580, 0x0400000c, 0x40102800, 0x58102001,
+	0x801021c0, 0x040207fa, 0x811a3000, 0x83180480,
+	0x00000005, 0x0402100d, 0x83932400, 0x00000010,
+	0x0401f7ec, 0x0401f881, 0x5c032000, 0x5c023000,
+	0x5c026800, 0x5c03e000, 0x02000800, 0x00106c4b,
+	0x80000580, 0x1c01f000, 0x0401fb6f, 0x040007f7,
+	0x5c032000, 0x5c023000, 0x5c026800, 0x5c03e000,
+	0x02000800, 0x00106c4b, 0x82000540, 0x00000001,
+	0x1c01f000, 0x0201f800, 0x00106c55, 0x4df00000,
+	0x4d300000, 0x4d340000, 0x4d180000, 0x4d2c0000,
+	0x4c5c0000, 0x4c600000, 0x4d900000, 0x4dd00000,
+	0x4da40000, 0x4d140000, 0x42003000, 0x0000bf2e,
+	0x581a6001, 0x813261c0, 0x04000023, 0x41302800,
+	0x5930b800, 0x59326809, 0x59340403, 0x81440580,
+	0x04000006, 0x805cb9c0, 0x0400001b, 0x41302800,
+	0x405e6000, 0x0401f7f7, 0x5930b801, 0x8d3e7d00,
+	0x04000003, 0x0401fb67, 0x0402000e, 0x59300406,
+	0x82000580, 0x00000006, 0x04020003, 0x8d3e7d18,
+	0x04000008, 0x0401f867, 0x4c0c0000, 0x4c140000,
+	0x0401fa97, 0x5c002800, 0x5c001800, 0x0401f002,
+	0x41301800, 0x405e6000, 0x813261c0, 0x040207eb,
+	0x0401f02d, 0x417a3000, 0x0201f800, 0x001070d8,
+	0x59926004, 0x813261c0, 0x04000005, 0x59326809,
+	0x59340403, 0x81440580, 0x04000006, 0x811a3000,
+	0x83180480, 0x00000005, 0x040017f4, 0x0401f01e,
+	0x4130c000, 0x59300001, 0x8000bd40, 0x04000012,
+	0x40026000, 0x40602800, 0x5930b801, 0x8d3e7d00,
+	0x04000003, 0x0401fb3b, 0x0402000a, 0x59300406,
+	0x82000580, 0x00000006, 0x04000006, 0x0401f81b,
+	0x4c140000, 0x0401fa6e, 0x5c002800, 0x0401f002,
+	0x41302800, 0x405e6000, 0x813261c0, 0x040207ef,
+	0x8060c1c0, 0x04000004, 0x40626000, 0x4178c000,
+	0x0401f7eb, 0x5c022800, 0x5c034800, 0x5c03a000,
+	0x5c032000, 0x5c00c000, 0x5c00b800, 0x5c025800,
+	0x5c023000, 0x5c026800, 0x5c026000, 0x5c03e000,
+	0x04000be3, 0x1c01f000, 0x0401fbc8, 0x59900004,
+	0x81300580, 0x04020018, 0x4c140000, 0x0201f800,
+	0x00106dc3, 0x0401fbb8, 0x5c002800, 0x59300001,
+	0x800001c0, 0x04020003, 0x497a680c, 0x1c01f000,
+	0x42003000, 0x0000bf2e, 0x497a6001, 0x58180801,
+	0x800409c0, 0x04020004, 0x48003000, 0x48003001,
+	0x1c01f000, 0x58180800, 0x48000800, 0x48003000,
+	0x1c01f000, 0x59300001, 0x48002801, 0x800001c0,
+	0x04020002, 0x4816680c, 0x497a6001, 0x1c01f000,
+	0x0401fba6, 0x42003000, 0x0000bf2e, 0x58180001,
+	0x81300580, 0x0402001c, 0x59300801, 0x800409c0,
+	0x0400000e, 0x59300000, 0x800001c0, 0x04020005,
+	0x48043001, 0x48043000, 0x497a6001, 0x1c01f000,
+	0x59300000, 0x48000800, 0x48043001, 0x497a6000,
+	0x497a6001, 0x1c01f000, 0x59300800, 0x800409c0,
+	0x04020005, 0x49783001, 0x49783000, 0x497a680c,
+	0x1c01f000, 0x48043001, 0x497a6000, 0x497a680c,
+	0x1c01f000, 0x58180000, 0x81300580, 0x0402000c,
+	0x59300001, 0x800001c0, 0x04020005, 0x48143000,
+	0x49782800, 0x497a680c, 0x1c01f000, 0x48003000,
+	0x48002800, 0x497a6001, 0x1c01f000, 0x59300000,
+	0x800001c0, 0x04020008, 0x59300001, 0x48001801,
+	0x800001c0, 0x04020002, 0x480e680c, 0x497a6001,
+	0x1c01f000, 0x59300801, 0x800409c0, 0x04020006,
+	0x59300800, 0x48042800, 0x497a6000, 0x497a680c,
+	0x1c01f000, 0x59300000, 0x48000800, 0x48042800,
+	0x497a6000, 0x497a6001, 0x1c01f000, 0x0401fb82,
+	0x4df00000, 0x0401f839, 0x040208c4, 0x04020945,
+	0x04020a89, 0x04020005, 0x5c03e000, 0x04000b70,
+	0x80000580, 0x1c01f000, 0x5c03e000, 0x04000b6c,
+	0x82000540, 0x00000001, 0x1c01f000, 0x4d2c0000,
+	0x4d340000, 0x4d300000, 0x41783000, 0x598e6009,
+	0x813261c0, 0x04000021, 0x59300406, 0x82000580,
+	0x00000006, 0x04020004, 0x8d3e7d18, 0x0402000a,
+	0x0401f017, 0x82040580, 0x00000005, 0x04020006,
+	0x8d3e7d16, 0x04000004, 0x59300420, 0x8c000500,
+	0x0402000f, 0x0401fa4e, 0x59300000, 0x4c000000,
+	0x8d3e7d06, 0x04000004, 0x0201f800, 0x001092d7,
+	0x04000005, 0x0401f867, 0x4c180000, 0x0401f9bc,
+	0x5c003000, 0x5c026000, 0x0401f7e2, 0x41303000,
+	0x59326000, 0x0401f7df, 0x5c026000, 0x5c026800,
+	0x5c025800, 0x1c01f000, 0x4933c857, 0x4c5c0000,
+	0x813261c0, 0x02000800, 0x001005d8, 0x41300000,
+	0x598cb809, 0x41783000, 0x805cb9c0, 0x04000013,
+	0x805c0d80, 0x04000004, 0x405c3000, 0x5818b800,
+	0x0401f7fa, 0x0401f84b, 0x598c000d, 0x81300580,
+	0x02000800, 0x001070b9, 0x59300403, 0x82000580,
+	0x00000042, 0x04020002, 0x497a6007, 0x80000580,
+	0x5c00b800, 0x1c01f000, 0x82000540, 0x00000001,
+	0x5c00b800, 0x1c01f000, 0x0401fb27, 0x4df00000,
+	0x4d2c0000, 0x4d340000, 0x4d300000, 0x41783000,
+	0x598e6009, 0x813261c0, 0x0400002c, 0x59300c06,
+	0x82040580, 0x00000006, 0x04020004, 0x8d3e7d18,
+	0x0402000a, 0x0401f022, 0x82040580, 0x00000005,
+	0x04020006, 0x8d3e7d18, 0x04000004, 0x59300420,
+	0x8c000500, 0x0402001a, 0x59326809, 0x59340403,
+	0x81440580, 0x04020016, 0x8d3e7d00, 0x04000006,
+	0x82040580, 0x00000003, 0x04020011, 0x0401fa35,
+	0x0402000f, 0x0401f9f6, 0x59300000, 0x4c000000,
+	0x8d3e7d06, 0x04000004, 0x0201f800, 0x001092d7,
+	0x04000005, 0x0401f80f, 0x4c180000, 0x0401f964,
+	0x5c003000, 0x5c026000, 0x0401f7d7, 0x41303000,
+	0x59326000, 0x0401f7d4, 0x5c026000, 0x5c026800,
+	0x5c025800, 0x5c03e000, 0x04000ae5, 0x1c01f000,
+	0x59300800, 0x497a6000, 0x0401fac8, 0x801831c0,
+	0x04020009, 0x598c0008, 0x81300580, 0x04020004,
+	0x48031808, 0x48031809, 0x0401f008, 0x48071809,
+	0x0401f006, 0x48043000, 0x598c0008, 0x81300580,
+	0x04020002, 0x481b1808, 0x0401f2ca, 0x4d2c0000,
+	0x4d300000, 0x4d340000, 0x41783000, 0x598e600b,
+	0x813261c0, 0x04000013, 0x8d3e7d06, 0x04000005,
+	0x59326809, 0x59340200, 0x8c00050e, 0x0402000a,
+	0x0401f9bf, 0x59300000, 0x4c000000, 0x0401f853,
+	0x4c180000, 0x0401f932, 0x5c003000, 0x5c026000,
+	0x0401f7f0, 0x41303000, 0x59326000, 0x0401f7ed,
+	0x0201f800, 0x00104773, 0x5c026800, 0x5c026000,
+	0x5c025800, 0x1c01f000, 0x4933c857, 0x4c5c0000,
+	0x813261c0, 0x02000800, 0x001005d8, 0x41300000,
+	0x598cb80b, 0x41783000, 0x805cb9c0, 0x0400000f,
+	0x805c0d80, 0x04000004, 0x405c3000, 0x5818b800,
+	0x0401f7fa, 0x0401f835, 0x598c000d, 0x81300580,
+	0x02000800, 0x001070b9, 0x497a6007, 0x80000580,
+	0x5c00b800, 0x1c01f000, 0x82000540, 0x00000001,
+	0x5c00b800, 0x1c01f000, 0x0401fa9f, 0x4df00000,
+	0x4d340000, 0x4d300000, 0x4d2c0000, 0x0201f800,
+	0x00020245, 0x02020800, 0x001005d8, 0x41783000,
+	0x598e600b, 0x813261c0, 0x04000014, 0x59300009,
+	0x81340580, 0x0402000e, 0x8d3e7d00, 0x04000003,
+	0x0401f9bc, 0x0402000a, 0x0401f97d, 0x59300000,
+	0x4c000000, 0x0401f811, 0x4c180000, 0x0401f8f0,
+	0x5c003000, 0x5c026000, 0x0401f7ef, 0x41303000,
+	0x59326000, 0x0401f7ec, 0x0201f800, 0x0010479c,
+	0x5c025800, 0x5c026000, 0x5c026800, 0x5c03e000,
+	0x04000a6f, 0x1c01f000, 0x59300800, 0x497a6000,
+	0x0401fa52, 0x801831c0, 0x04020009, 0x598c000a,
+	0x81300580, 0x04020004, 0x4803180a, 0x4803180b,
+	0x0401f008, 0x4807180b, 0x0401f006, 0x48043000,
+	0x598c000a, 0x81300580, 0x04020002, 0x481b180a,
+	0x0401f254, 0x0401fa64, 0x4df00000, 0x4d300000,
+	0x598e6005, 0x813261c0, 0x04000020, 0x59300000,
+	0x4c000000, 0x59300c06, 0x82040580, 0x00000011,
+	0x04020007, 0x833c0500, 0x00001800, 0x04000015,
+	0x8d3e7d16, 0x04020013, 0x0401f009, 0x82040580,
+	0x00000004, 0x04020006, 0x8d3e7d16, 0x04000004,
+	0x59300420, 0x8c000500, 0x0402000a, 0x0201f800,
+	0x0010914e, 0x02000800, 0x0010801c, 0x0201f800,
+	0x00109326, 0x0201f800, 0x0002077d, 0x0401fa31,
+	0x5c026000, 0x0401f7e0, 0x497b1805, 0x497b1804,
+	0x5c026000, 0x5c03e000, 0x04000a31, 0x1c01f000,
+	0x4933c857, 0x4c5c0000, 0x4c600000, 0x813261c0,
+	0x02000800, 0x001005d8, 0x41300000, 0x598cb805,
+	0x405cc000, 0x805cb9c0, 0x04000025, 0x805c0d80,
+	0x04000004, 0x405cc000, 0x5860b800, 0x0401f7fa,
+	0x598c000d, 0x81300580, 0x02000800, 0x001070b9,
+	0x0401fa02, 0x598c0005, 0x805c0580, 0x04020009,
+	0x585c0000, 0x48031805, 0x4978b800, 0x598c0004,
+	0x805c0580, 0x0402000d, 0x497b1804, 0x0401f00b,
+	0x598c0004, 0x805c0580, 0x04020005, 0x48631804,
+	0x4978b800, 0x4978c000, 0x0401f004, 0x585c0000,
+	0x4800c000, 0x4978b800, 0x0401f9fe, 0x80000580,
+	0x5c00c000, 0x5c00b800, 0x1c01f000, 0x82000540,
+	0x00000001, 0x5c00c000, 0x5c00b800, 0x1c01f000,
+	0x4933c857, 0x0401fa04, 0x4df00000, 0x4d2c0000,
+	0x4d340000, 0x4d300000, 0x4c5c0000, 0x4178b800,
+	0x8d3e7d18, 0x0400000d, 0x8d3e7d16, 0x0402000b,
+	0x0201f800, 0x00109037, 0x04000008, 0x0201f800,
+	0x00109597, 0x04020005, 0x592c0207, 0x492fc857,
+	0x8200bd00, 0x0000000f, 0x41783000, 0x598e6005,
+	0x813261c0, 0x04000029, 0x59326809, 0x813669c0,
+	0x04000023, 0x59340403, 0x81440580, 0x04020020,
+	0x59300c06, 0x82040580, 0x00000011, 0x0400001a,
+	0x82040580, 0x00000004, 0x04020004, 0x59300420,
+	0x8c000500, 0x04020016, 0x0201f800, 0x00109037,
+	0x04000008, 0x0201f800, 0x00109597, 0x04020005,
+	0x59300403, 0x82000580, 0x00000043, 0x0400000c,
+	0x0401f8c3, 0x59300000, 0x4c000000, 0x0401f812,
+	0x4c180000, 0x0401f836, 0x5c003000, 0x5c026000,
+	0x0401f7dc, 0x805cb9c0, 0x040207ec, 0x41303000,
+	0x59326000, 0x0401f7d7, 0x5c00b800, 0x5c026000,
+	0x5c026800, 0x5c025800, 0x5c03e000, 0x040009b4,
+	0x1c01f000, 0x59300800, 0x497a6000, 0x0401f997,
+	0x801831c0, 0x04020009, 0x598c0004, 0x81300580,
+	0x04020004, 0x48031804, 0x48031805, 0x0401f008,
+	0x48071805, 0x0401f006, 0x48043000, 0x598c0004,
+	0x81300580, 0x04020002, 0x481b1804, 0x0401f199,
+	0x4943c857, 0x0401f9a8, 0x4df00000, 0x0401fe34,
+	0x0401fecb, 0x5c03e000, 0x04000999, 0x1c01f000,
+	0x4947c857, 0x0401f9a0, 0x4df00000, 0x4d3c0000,
+	0x853e7d00, 0x0401fe75, 0x0401fefc, 0x5c027800,
+	0x5c03e000, 0x0400098e, 0x1c01f000, 0x5c000000,
+	0x4c000000, 0x4803c857, 0x4d340000, 0x4d2c0000,
+	0x59326809, 0x59325808, 0x59300406, 0x82000c80,
+	0x00000012, 0x02021800, 0x001005d8, 0x4933c857,
+	0x4943c857, 0x493fc857, 0x4803c857, 0x0c01f804,
+	0x5c025800, 0x5c026800, 0x1c01f000, 0x00106ae5,
+	0x00106ae7, 0x00106af1, 0x00106b0b, 0x00106ae7,
+	0x00106afb, 0x00106b23, 0x00106ae5, 0x00106ae5,
+	0x00106b36, 0x00106b2d, 0x00106ae5, 0x00106ae5,
+	0x00106ae5, 0x00106ae5, 0x00106ae5, 0x00106b3c,
+	0x00106b3c, 0x0201f800, 0x001005d8, 0x0201f800,
+	0x00109134, 0x02000800, 0x00102074, 0x0201f800,
+	0x00109326, 0x0201f800, 0x0010801c, 0x0201f000,
+	0x00107911, 0x812e59c0, 0x02020800, 0x001005d8,
+	0x5930021d, 0x82000580, 0x00000003, 0x02000800,
+	0x0010912a, 0x0201f000, 0x00107911, 0x0201f800,
+	0x00109037, 0x02000000, 0x00107911, 0x592c1204,
+	0x82081500, 0x000000ff, 0x82080580, 0x00000055,
+	0x02020800, 0x001005d8, 0x49425a06, 0x0201f800,
+	0x000202da, 0x0201f000, 0x00107911, 0x59300004,
+	0x8400055c, 0x48026004, 0x59300007, 0x8c000500,
+	0x02020800, 0x00100e99, 0x0201f800, 0x00109037,
+	0x0400000d, 0x4a025a04, 0x00000103, 0x49425a06,
+	0x497a5c09, 0x0201f800, 0x001091c6, 0x0201f800,
+	0x0010a693, 0x0201f800, 0x000202da, 0x0201f800,
+	0x0010912a, 0x0201f000, 0x00107911, 0x59300007,
+	0x8c000500, 0x02020800, 0x00100e99, 0x0201f800,
+	0x00109037, 0x02020800, 0x0010a3ef, 0x0201f000,
+	0x00107911, 0x0201f800, 0x00109037, 0x04000005,
+	0x49425a06, 0x497a5c09, 0x0201f800, 0x000202da,
+	0x0201f000, 0x00107911, 0x0201f800, 0x00109037,
+	0x02020800, 0x0010664f, 0x0201f000, 0x00107911,
+	0x0201f800, 0x00109037, 0x04000004, 0x49425a06,
+	0x0201f800, 0x000202da, 0x59325817, 0x0201f800,
+	0x001007fd, 0x0201f000, 0x00107911, 0x598c000d,
+	0x81300580, 0x04000003, 0x497a6007, 0x1c01f000,
+	0x59c40004, 0x82000500, 0x0000000c, 0x04000005,
+	0x4a038804, 0x0000000c, 0x497b2807, 0x0401f00a,
+	0x0401facd, 0x59300403, 0x82000d80, 0x00000040,
+	0x04000004, 0x82000580, 0x00000042, 0x04020002,
+	0x497a6007, 0x0201f800, 0x001070b9, 0x80000580,
+	0x1c01f000, 0x59300804, 0x8c040d3e, 0x04020004,
+	0x82000540, 0x00000001, 0x0401f005, 0x4933c857,
+	0x84040d3e, 0x48066004, 0x80000580, 0x1c01f000,
+	0x59300804, 0x8c040d20, 0x04020004, 0x82000540,
+	0x00000001, 0x1c01f000, 0x4933c857, 0x4d380000,
+	0x59300804, 0x84040d20, 0x48066004, 0x42027000,
+	0x00000049, 0x59300203, 0x82000580, 0x00000003,
+	0x04000003, 0x42027000, 0x00000013, 0x0201f800,
+	0x000207a1, 0x80000580, 0x5c027000, 0x1c01f000,
+	0x59300017, 0x81480580, 0x04020003, 0x59300018,
+	0x814c0580, 0x1c01f000, 0x4d2c0000, 0x4d300000,
+	0x0401f8c9, 0x4df00000, 0x0201f800, 0x00106062,
+	0x59900001, 0x82000500, 0x00000003, 0x0c01f001,
+	0x00106bba, 0x00106b9a, 0x00106b98, 0x00106b98,
+	0x0201f800, 0x001005d8, 0x59926004, 0x0401f88e,
+	0x813261c0, 0x0400001d, 0x59300004, 0x8c000516,
+	0x04000004, 0x59325808, 0x497a5808, 0x497a5809,
+	0x0401f88e, 0x59300001, 0x800001c0, 0x0400000e,
+	0x497a6001, 0x42003000, 0x0000bf2e, 0x58180801,
+	0x800409c0, 0x04020004, 0x48003001, 0x48003000,
+	0x0401f00a, 0x58180800, 0x48000800, 0x48003000,
+	0x0401f006, 0x59300809, 0x800409c0, 0x02000800,
+	0x001005d8, 0x4978080c, 0x5c03e000, 0x04000890,
+	0x5c026000, 0x5c025800, 0x1c01f000, 0x4d300000,
+	0x497b2807, 0x0401f894, 0x4df00000, 0x598c0000,
+	0x82000500, 0x00000007, 0x4803c857, 0x0c01f001,
+	0x00106bef, 0x00106bd2, 0x00106bdb, 0x00106bdf,
+	0x00106bea, 0x00106bef, 0x00106bd0, 0x00106bd0,
+	0x0201f800, 0x001005d8, 0x598c000d, 0x80026540,
+	0x04000004, 0x0401f81e, 0x02020800, 0x001005d8,
+	0x0201f800, 0x001070b9, 0x0401f015, 0x0401f827,
+	0x0201f800, 0x001070b9, 0x0401f011, 0x598c000d,
+	0x80026540, 0x0400000e, 0x0401f838, 0x04000004,
+	0x0401f80f, 0x04000002, 0x0401f81c, 0x0201f800,
+	0x001070b9, 0x0401f006, 0x0401f830, 0x02020800,
+	0x001005d8, 0x0201f800, 0x001070b9, 0x5c03e000,
+	0x0400085b, 0x5c026000, 0x1c01f000, 0x598c0009,
+	0x81300580, 0x0402000c, 0x0401f84e, 0x0401f83b,
+	0x59300000, 0x800001c0, 0x04000004, 0x48031809,
+	0x497a6000, 0x0401f003, 0x497b1809, 0x497b1808,
+	0x80000580, 0x1c01f000, 0x4d2c0000, 0x59300406,
+	0x82000580, 0x00000003, 0x04020012, 0x598c000b,
+	0x81300580, 0x0402000f, 0x0401f83a, 0x59325808,
+	0x497a5808, 0x497a5809, 0x0401f824, 0x59300000,
+	0x800001c0, 0x04000004, 0x4803180b, 0x497a6000,
+	0x0401f003, 0x497b180a, 0x497b180b, 0x80000580,
+	0x5c025800, 0x1c01f000, 0x598c0005, 0x81300580,
+	0x0402000c, 0x0401f827, 0x0401f814, 0x59300000,
+	0x800001c0, 0x04000004, 0x48031805, 0x497a6000,
+	0x0401f003, 0x497b1805, 0x497b1804, 0x80000580,
+	0x1c01f000, 0x4a032001, 0x00000000, 0x497b2004,
+	0x497b2005, 0x59900006, 0x82000500, 0x0000ffff,
+	0x48032006, 0x1c01f000, 0x4c040000, 0x59300004,
+	0x82000500, 0x7ffeffff, 0x48026004, 0x59bc00e4,
+	0x8c000514, 0x04000009, 0x42000800, 0x0000bf00,
+	0x58040012, 0x81300580, 0x04020004, 0x49780812,
+	0x4a0378e4, 0x00000800, 0x5c000800, 0x1c01f000,
+	0x4803c856, 0x598c000c, 0x80000540, 0x04000003,
+	0x80000040, 0x4803180c, 0x1c01f000, 0x59bc00ea,
+	0x82000500, 0x00000007, 0x82000580, 0x00000003,
+	0x04020004, 0x4803c856, 0x4a0378e8, 0x00000001,
+	0x1c01f000, 0x59bc00ea, 0x82000500, 0x00000007,
+	0x82000580, 0x00000001, 0x04020011, 0x4803c856,
+	0x42000800, 0x00000000, 0x0401f80e, 0x42000800,
+	0x00001000, 0x59bc00ea, 0x82000500, 0x00000007,
+	0x82000580, 0x00000003, 0x04000005, 0x80040840,
+	0x040207f9, 0x0201f800, 0x001005d8, 0x1c01f000,
+	0x59bc00ea, 0x82000500, 0x00000007, 0x82000580,
+	0x00000001, 0x02020800, 0x001005d8, 0x59bc00ea,
+	0x8c000516, 0x040207fe, 0x480778e1, 0x1c01f000,
+	0x59bc00ea, 0x8c000516, 0x040207fe, 0x480778e1,
+	0x59bc00ea, 0x8c000516, 0x040207fe, 0x480b78e1,
+	0x1c01f000, 0x82000d00, 0x80000018, 0x02020800,
+	0x001005d0, 0x0201f800, 0x001005d8, 0x00106c97,
+	0x00106d3b, 0x00106d55, 0x00106c97, 0x00106c99,
+	0x00106cba, 0x00106cd9, 0x00106d0d, 0x00106c97,
+	0x00106d39, 0x00106c97, 0x00106c97, 0x00106c97,
+	0x00106c97, 0x00106c97, 0x00106c97, 0x0201f800,
+	0x001005d8, 0x4d300000, 0x4d900000, 0x4dd00000,
+	0x4da40000, 0x4d140000, 0x0201f800, 0x001070d8,
+	0x59bc00ea, 0x8c000510, 0x040007fe, 0x59be60e0,
+	0x59300004, 0x8c000520, 0x04000011, 0x82000500,
+	0xfffefeff, 0x48026004, 0x4a026203, 0x00000003,
+	0x0401ffa9, 0x0201f800, 0x00100fd0, 0x5c022800,
+	0x5c034800, 0x5c03a000, 0x5c032000, 0x5c026000,
+	0x4a0378e4, 0x00000008, 0x0401f795, 0x84000510,
+	0x48026004, 0x0401f7f6, 0x4d300000, 0x4d900000,
+	0x4dd00000, 0x4da40000, 0x4d140000, 0x0201f800,
+	0x001070d8, 0x59bc00ea, 0x8c000510, 0x040007fe,
+	0x59be60e0, 0x59300004, 0x8c000520, 0x0400000f,
+	0x82000500, 0xfffefeff, 0x48026004, 0x0401ff8a,
+	0x0201f800, 0x0010100e, 0x5c022800, 0x5c034800,
+	0x5c03a000, 0x5c032000, 0x5c026000, 0x4a0378e4,
+	0x00000008, 0x0401f776, 0x84000510, 0x48026004,
+	0x0401f7f6, 0x4d300000, 0x4d2c0000, 0x4d340000,
+	0x4da40000, 0x4cd00000, 0x59bc00ea, 0x8c000510,
+	0x040007fe, 0x59be60e0, 0x813261c0, 0x02000800,
+	0x001005d8, 0x59300004, 0x8c000520, 0x0400001d,
+	0x82000500, 0xfffefeff, 0x48026004, 0x59326809,
+	0x42034800, 0x0010b544, 0x04011000, 0x4a03c840,
+	0x0010b54b, 0x4a03c842, 0x00000012, 0x04011000,
+	0x4a03c840, 0x0010b55d, 0x4a03c842, 0x000000ff,
+	0x04011000, 0x4a03c840, 0x0010b65c, 0x4a03c842,
+	0x000000ff, 0x0401fbf2, 0x5c01a000, 0x5c034800,
+	0x5c026800, 0x5c025800, 0x5c026000, 0x1c01f000,
+	0x84000510, 0x48026004, 0x5c01a000, 0x5c034800,
+	0x5c026800, 0x5c025800, 0x5c026000, 0x1c01f000,
+	0x1c01f000, 0x4d300000, 0x4d2c0000, 0x4d340000,
+	0x4cd00000, 0x4d900000, 0x4dd00000, 0x4da40000,
+	0x4d140000, 0x0401fbc3, 0x59bc00ea, 0x8c000510,
+	0x040007fe, 0x59be60e0, 0x813261c0, 0x02000800,
+	0x001005d8, 0x59300004, 0x8c000520, 0x0400000f,
+	0x82000500, 0xfffefeff, 0x48026004, 0x0201f800,
+	0x0010783a, 0x5c022800, 0x5c034800, 0x5c03a000,
+	0x5c032000, 0x5c01a000, 0x5c026800, 0x5c025800,
+	0x5c026000, 0x1c01f000, 0x84000510, 0x48026004,
+	0x5c022800, 0x5c034800, 0x5c03a000, 0x5c032000,
+	0x5c01a000, 0x5c026800, 0x5c025800, 0x5c026000,
+	0x1c01f000, 0x0201f800, 0x001005d8, 0x4d300000,
+	0x4d380000, 0x42000000, 0x0010b8c4, 0x0201f800,
+	0x0010aa47, 0x0401ff14, 0x598e600d, 0x59c40004,
+	0x8c000506, 0x04000004, 0x0401f8db, 0x4a038804,
+	0x00000008, 0x813261c0, 0x04000006, 0x0401fb87,
+	0x42027000, 0x00000014, 0x0201f800, 0x000207a1,
+	0x4a0378e4, 0x00000002, 0x5c027000, 0x5c026000,
+	0x0401f6f7, 0x4d180000, 0x4d300000, 0x4d380000,
+	0x4d900000, 0x4dd00000, 0x4da40000, 0x4d140000,
+	0x0401fef9, 0x417a3000, 0x59c40804, 0x83180400,
+	0x0010709f, 0x50000000, 0x80040500, 0x0400001b,
+	0x42000000, 0x0010b8c5, 0x0201f800, 0x0010aa47,
+	0x0401fb70, 0x59926004, 0x0401f859, 0x83180400,
+	0x0010709f, 0x50000000, 0x48038804, 0x813261c0,
+	0x0400000a, 0x59300004, 0x8c00050c, 0x04020003,
+	0x4a026203, 0x00000003, 0x42027000, 0x0000004a,
+	0x0201f800, 0x000207a1, 0x59c40004, 0x82000500,
+	0x00f80000, 0x04000005, 0x811a3000, 0x83180480,
+	0x00000005, 0x040017dd, 0x4a0378e4, 0x00000008,
+	0x5c022800, 0x5c034800, 0x5c03a000, 0x5c032000,
+	0x5c027000, 0x5c026000, 0x5c023000, 0x0401f6c0,
+	0x4d2c0000, 0x4d340000, 0x59326809, 0x598c0800,
+	0x82040580, 0x00000004, 0x04020004, 0x838c1400,
+	0x00000005, 0x0401f00c, 0x82040580, 0x00000001,
+	0x04020004, 0x838c1400, 0x00000009, 0x0401f006,
+	0x82040580, 0x00000002, 0x04020022, 0x838c1400,
+	0x0000000b, 0x41306800, 0x58340000, 0x80007d40,
+	0x0400001c, 0x583c0009, 0x81340580, 0x04020006,
+	0x403c6800, 0x583c0000, 0x80007d40, 0x040207fa,
+	0x0401f014, 0x4933c857, 0x483fc857, 0x583c0000,
+	0x48006800, 0x49307800, 0x443c1000, 0x80000580,
+	0x4803180d, 0x4803180f, 0x598c0000, 0x82000580,
+	0x00000003, 0x04000003, 0x4a031800, 0x00000000,
+	0x80000580, 0x5c026800, 0x5c025800, 0x1c01f000,
+	0x82000540, 0x00000001, 0x0401f7fb, 0x491bc857,
+	0x59c80840, 0x82040540, 0x00000010, 0x48039040,
+	0x59c41008, 0x82080500, 0xffffff7f, 0x48038808,
+	0x4c040000, 0x4c080000, 0x0401fabb, 0x04020007,
+	0x0401fabf, 0x04000022, 0x48038804, 0x0201f800,
+	0x0010107a, 0x0401f042, 0x4a038803, 0x00000008,
+	0x59c40003, 0x82000500, 0x00000003, 0x040007fd,
+	0x8c000502, 0x04020007, 0x0401fab1, 0x04000014,
+	0x48038804, 0x0201f800, 0x0010107a, 0x0401f034,
+	0x59c80040, 0x8400056a, 0x48039040, 0x59c80040,
+	0x8c00052a, 0x040207fe, 0x59c40005, 0x82000500,
+	0xc0000000, 0x04000006, 0x59c400a3, 0x84000540,
+	0x480388a3, 0x4a038805, 0xc0000000, 0x0201f800,
+	0x0010101d, 0x4a03a005, 0x30000000, 0x59d00006,
+	0x4a03a005, 0x30000000, 0x59900006, 0x82000500,
+	0xffff0000, 0x48032006, 0x59d00005, 0x8c000504,
+	0x040207fe, 0x42000800, 0x00007600, 0x83180540,
+	0x60000000, 0x480008a1, 0x811800dc, 0x59c80840,
+	0x80040540, 0x48039040, 0x82000540, 0x00003000,
+	0x48039040, 0x59c80040, 0x82000500, 0x00003000,
+	0x040207fd, 0x0201f800, 0x00101068, 0x83180400,
+	0x0010709f, 0x50000000, 0x48038804, 0x80000580,
+	0x4df00000, 0x0201f800, 0x00106062, 0x5c03e000,
+	0x5c001000, 0x5c000800, 0x480b8808, 0x48079040,
+	0x1c01f000, 0x4803c856, 0x59c80840, 0x82040540,
+	0x00000010, 0x48039040, 0x59c41008, 0x82080500,
+	0xffffff7f, 0x48038808, 0x4c040000, 0x4c080000,
+	0x59c40004, 0x82000500, 0x00000003, 0x04020010,
+	0x59c40004, 0x82000500, 0x0000000c, 0x04000005,
+	0x4a038804, 0x0000000c, 0x8c000504, 0x0401f025,
+	0x59c80040, 0x8400056e, 0x48039040, 0x59c80040,
+	0x8c00052e, 0x040207fe, 0x0401f01e, 0x4a038803,
+	0x00000008, 0x59c40003, 0x82000500, 0x00000003,
+	0x040007fd, 0x8c000502, 0x04020006, 0x59c40004,
+	0x4a038804, 0x0000000c, 0x8c000504, 0x0401f011,
+	0x59c80040, 0x8400056a, 0x48039040, 0x59c80040,
+	0x8c00052a, 0x040207fe, 0x59c40005, 0x82000500,
+	0xc0000000, 0x04000007, 0x59c400a3, 0x84000540,
+	0x480388a3, 0x4a038805, 0xc0000000, 0x80000580,
+	0x497b2807, 0x5c001000, 0x5c000800, 0x480b8808,
+	0x48079040, 0x1c01f000, 0x4933c857, 0x4d900000,
+	0x4dd00000, 0x4da40000, 0x4d140000, 0x0401fdee,
+	0x4df00000, 0x0401fa6f, 0x59900004, 0x800001c0,
+	0x04000011, 0x81300580, 0x0402000f, 0x59300004,
+	0x84000520, 0x48026004, 0x0401ff51, 0x04020009,
+	0x5c03e000, 0x04000dd6, 0x80000580, 0x5c022800,
+	0x5c034800, 0x5c03a000, 0x5c032000, 0x1c01f000,
+	0x0401fd0e, 0x42027000, 0x00000049, 0x59300004,
+	0x84000520, 0x48026004, 0x8c00050c, 0x02020800,
+	0x000207a1, 0x5c03e000, 0x04000dc5, 0x82000540,
+	0x00000001, 0x5c022800, 0x5c034800, 0x5c03a000,
+	0x5c032000, 0x1c01f000, 0x4933c857, 0x0401fdc6,
+	0x4df00000, 0x598c000d, 0x80026540, 0x04000012,
+	0x59300004, 0x84000520, 0x48026004, 0x0401ff8a,
+	0x04000017, 0x0401fd26, 0x42027000, 0x00000013,
+	0x59300004, 0x8c00050c, 0x02020800, 0x000207a1,
+	0x5c03e000, 0x04000daa, 0x82000540, 0x00000001,
+	0x1c01f000, 0x836c1580, 0x00000001, 0x040007f9,
+	0x836c1580, 0x00000004, 0x040007f6, 0x42001000,
+	0x00104148, 0x0201f800, 0x00105f90, 0x5c03e000,
+	0x04000d9b, 0x80000580, 0x1c01f000, 0x4d300000,
+	0x4d180000, 0x4d3c0000, 0x0401fd9f, 0x4df00000,
+	0x4a0378e4, 0x0000000f, 0x0401f9ff, 0x417a3000,
+	0x59926004, 0x813261c0, 0x04000010, 0x417a7800,
+	0x0201f800, 0x001048d9, 0x0400000a, 0x59300c06,
+	0x82040580, 0x00000003, 0x04000004, 0x82040580,
+	0x00000006, 0x04020003, 0x42027800, 0x00000002,
+	0x0201f800, 0x00108be3, 0x811a3000, 0x83180480,
+	0x00000005, 0x040017eb, 0x42000800, 0x00000040,
+	0x0201f800, 0x00101345, 0x4a0378e4, 0x0000000a,
+	0x5c03e000, 0x04000d72, 0x5c027800, 0x5c023000,
+	0x5c026000, 0x1c01f000, 0x4803c856, 0x4d300000,
+	0x0401fd75, 0x4df00000, 0x59c80840, 0x82040540,
+	0x00000010, 0x48039040, 0x59c41008, 0x82080500,
+	0xffffff7f, 0x48038808, 0x4c040000, 0x4c080000,
+	0x42001000, 0x00000003, 0x0401f9c2, 0x598e600d,
+	0x813261c0, 0x04020f9d, 0x040009c7, 0x497b2807,
+	0x0401f80a, 0x5c001000, 0x5c000800, 0x480b8808,
+	0x84040d74, 0x48079040, 0x5c03e000, 0x04000d50,
+	0x5c026000, 0x1c01f000, 0x4d380000, 0x4d180000,
+	0x4d300000, 0x4d900000, 0x4dd00000, 0x4da40000,
+	0x4d140000, 0x59c41004, 0x480bc857, 0x82080500,
+	0x00003ff0, 0x04000025, 0x417a3000, 0x4c080000,
+	0x0201f800, 0x00106062, 0x5c001000, 0x82080500,
+	0x00000210, 0x04020004, 0x811a3000, 0x80081102,
+	0x0401f7f7, 0x0401f9c3, 0x59926004, 0x4933c857,
+	0x813261c0, 0x04020005, 0x59c400a3, 0x8c00051a,
+	0x02000800, 0x001005d8, 0x0401fea5, 0x04000009,
+	0x0401fc6a, 0x42027000, 0x00000049, 0x59300004,
+	0x8c00050c, 0x02020800, 0x000207a1, 0x0401f007,
+	0x42027000, 0x0000004a, 0x4a026203, 0x00000003,
+	0x0201f800, 0x000207a1, 0x5c022800, 0x5c034800,
+	0x5c03a000, 0x5c032000, 0x5c026000, 0x5c023000,
+	0x5c027000, 0x1c01f000, 0x4d300000, 0x4d180000,
+	0x4d900000, 0x0401fd1c, 0x42001000, 0x00000000,
+	0x598c0000, 0x82000580, 0x00000005, 0x04000971,
+	0x417a3000, 0x811b20c8, 0x83932400, 0x0000bf32,
+	0x59900001, 0x82000580, 0x00000001, 0x0402000d,
+	0x42000800, 0x000007d0, 0x59926004, 0x59300011,
+	0x82000500, 0xfff00000, 0x80000540, 0x04000003,
+	0x42000800, 0x00001b58, 0x0201f800, 0x00106054,
+	0x811a3000, 0x83180480, 0x00000005, 0x040017ea,
+	0x59c81040, 0x84081534, 0x480b9040, 0x0401fcf0,
+	0x5c032000, 0x5c023000, 0x5c026000, 0x1c01f000,
+	0x4933c857, 0x4d900000, 0x4dd00000, 0x4da40000,
+	0x4d140000, 0x4d380000, 0x0401fcef, 0x4df00000,
+	0x59300004, 0x8c00053e, 0x04020007, 0x8c000520,
+	0x04000025, 0x0201f800, 0x00106b6c, 0x04000022,
+	0x0401f02a, 0x598c000d, 0x81300580, 0x04000011,
+	0x0201f800, 0x00108cd6, 0x04020024, 0x0401f918,
+	0x04000022, 0x48038804, 0x0401f95e, 0x0201f800,
+	0x0010107a, 0x0401fc0d, 0x42027000, 0x00000049,
+	0x59300004, 0x8c00050c, 0x0402000d, 0x0401f00e,
+	0x59c40004, 0x8c000504, 0x04000014, 0x4a038804,
+	0x00000004, 0x0401fc36, 0x42027000, 0x00000013,
+	0x59300004, 0x8c00050c, 0x04000003, 0x0201f800,
+	0x000207a1, 0x5c03e000, 0x04000cb9, 0x5c027000,
+	0x5c022800, 0x5c034800, 0x5c03a000, 0x5c032000,
+	0x80000580, 0x1c01f000, 0x5c03e000, 0x04000cb0,
+	0x5c027000, 0x5c022800, 0x5c034800, 0x5c03a000,
+	0x5c032000, 0x82000540, 0x00000001, 0x1c01f000,
+	0x497b2807, 0x0401fcb0, 0x59c400af, 0x800001c0,
+	0x04020004, 0x0401fca2, 0x0201f000, 0x001014fb,
+	0x598c000f, 0x82001480, 0x00000002, 0x04021007,
+	0x80000000, 0x4803180f, 0x80000580, 0x0201f800,
+	0x0010604d, 0x0400000e, 0x0401fed8, 0x0402000c,
+	0x0401fdd4, 0x0400000a, 0x0201f800, 0x0010a9c7,
+	0x0401f916, 0x4d380000, 0x42027000, 0x00000014,
+	0x0201f800, 0x000207a1, 0x5c027000, 0x0401fc88,
+	0x0201f000, 0x001014fb, 0x4d900000, 0x4dd00000,
+	0x4da40000, 0x4d140000, 0x4d300000, 0x0201f800,
+	0x00106062, 0x0401fc88, 0x59c400af, 0x800001c0,
+	0x04000027, 0x0401f907, 0x59926004, 0x4933c857,
+	0x59300004, 0x8c000516, 0x0400000b, 0x0401fe8b,
+	0x0402001f, 0x0201f800, 0x00106b8a, 0x0401fc70,
+	0x42000800, 0x80000804, 0x0201f800, 0x00106721,
+	0x0401f017, 0x42001800, 0x00007530, 0x0401f8c1,
+	0x04020004, 0x0201f800, 0x00106052, 0x0401f010,
+	0x0401fe7a, 0x0402000e, 0x0201f800, 0x0010a9c7,
+	0x59300004, 0x8c00050c, 0x04020003, 0x4a026203,
+	0x00000003, 0x4d380000, 0x42027000, 0x0000004a,
+	0x0201f800, 0x000207a1, 0x5c027000, 0x0401fc54,
+	0x5c026000, 0x5c022800, 0x5c034800, 0x5c03a000,
+	0x5c032000, 0x0201f000, 0x001014fb, 0x4d900000,
+	0x4dd00000, 0x4da40000, 0x4d140000, 0x4d300000,
+	0x4d2c0000, 0x0401fc50, 0x0401f8d2, 0x59926004,
+	0x4933c857, 0x0401f880, 0x04000016, 0x0201f800,
+	0x00106062, 0x813261c0, 0x04000034, 0x59325808,
+	0x812e59c0, 0x02000800, 0x001005d8, 0x0201f800,
+	0x0010513b, 0x0402001d, 0x592c0208, 0x84000550,
+	0x48025a08, 0x0201f800, 0x00105258, 0x04020027,
+	0x592c0208, 0x84000510, 0x48025a08, 0x0401f023,
+	0x0201f800, 0x00106052, 0x0401f020, 0x0201f800,
+	0x0010a9c7, 0x0401fd9e, 0x592c0208, 0x84000550,
+	0x48025a08, 0x4d380000, 0x42027000, 0x0000004a,
+	0x4a026203, 0x00000003, 0x0201f800, 0x000207a1,
+	0x5c027000, 0x0401f011, 0x59900006, 0x82000500,
+	0xffff0000, 0x040207ee, 0x59c408af, 0x82040480,
+	0x000003e8, 0x040217ea, 0x59900006, 0x82000400,
+	0x00010000, 0x48032006, 0x0201f800, 0x00106052,
+	0x0201f800, 0x0010411d, 0x5c025800, 0x5c026000,
+	0x5c022800, 0x5c034800, 0x5c03a000, 0x5c032000,
+	0x0401f403, 0x4d300000, 0x4d2c0000, 0x0401fc0a,
+	0x598e600d, 0x4933c857, 0x59c41004, 0x8c081500,
+	0x04000007, 0x0201f800, 0x0010513b, 0x04020007,
+	0x0201f800, 0x00105258, 0x0402002f, 0x0201f800,
+	0x0010604d, 0x0401f02c, 0x598c000f, 0x80000540,
+	0x04020011, 0x59c408af, 0x82040480, 0x000003e8,
+	0x0402100d, 0x598c080f, 0x80040800, 0x4807180f,
+	0x0201f800, 0x0010604d, 0x42000000, 0x0010b852,
+	0x0201f800, 0x0010aa47, 0x0201f800, 0x0010411d,
+	0x0401f019, 0x0401fdb4, 0x813261c0, 0x04020003,
+	0x0401f849, 0x0401f014, 0x0201f800, 0x0010a9c7,
+	0x59300406, 0x82000580, 0x00000003, 0x04020007,
+	0x59325808, 0x812e59c0, 0x04000004, 0x592c0208,
+	0x84000550, 0x48025a08, 0x0401f854, 0x4d380000,
+	0x42027000, 0x00000014, 0x0201f800, 0x000207a1,
+	0x5c027000, 0x5c025800, 0x5c026000, 0x0201f000,
+	0x00106c4b, 0x59c40804, 0x83180400, 0x00107095,
+	0x50000000, 0x80040500, 0x1c01f000, 0x59c40804,
+	0x83180400, 0x0010709a, 0x50000000, 0x80040500,
+	0x1c01f000, 0x00000210, 0x00000420, 0x00000840,
+	0x00001080, 0x00002100, 0x00004000, 0x00008000,
+	0x00010000, 0x00020000, 0x00040000, 0x00080000,
+	0x00100000, 0x00200000, 0x00400000, 0x00800000,
+	0x59900806, 0x80040120, 0x800c0480, 0x04021004,
+	0x82000540, 0x00000001, 0x0401f005, 0x82040c00,
+	0x00010000, 0x48072006, 0x80000580, 0x1c01f000,
+	0x480bc857, 0x0201f800, 0x00106c55, 0x4df00000,
+	0x480b1800, 0x5c03e000, 0x02000800, 0x00106c4b,
+	0x1c01f000, 0x4803c856, 0x0201f800, 0x00106c55,
+	0x4df00000, 0x497b180d, 0x497b1803, 0x497b180e,
+	0x497b180f, 0x497b1810, 0x598c0000, 0x82000580,
+	0x00000003, 0x04000009, 0x836c0580, 0x00000002,
+	0x04020004, 0x4a031800, 0x00000005, 0x0401f003,
+	0x4a031800, 0x00000000, 0x5c03e000, 0x02000800,
+	0x00106c4b, 0x1c01f000, 0x59300004, 0x8c00050c,
+	0x04020003, 0x4a026203, 0x00000001, 0x1c01f000,
+	0x83180480, 0x00000005, 0x02021800, 0x001005d8,
+	0x491bc857, 0x811b20c8, 0x83932400, 0x0000bf32,
+	0x811ba0ca, 0x83d3a400, 0x00007600, 0x83180400,
+	0x001070ea, 0x50034800, 0x811a28c2, 0x83162c00,
+	0x00006100, 0x1c01f000, 0x0010b75b, 0x0010b772,
+	0x0010b789, 0x0010b7a0, 0x0010b7b7, 0x4933c857,
+	0x59300406, 0x82000c80, 0x00000012, 0x04021016,
+	0x4803c857, 0x04011000, 0x0c01f001, 0x00107109,
+	0x00107198, 0x001074d1, 0x00107556, 0x00107198,
+	0x001074d1, 0x00107556, 0x00107109, 0x00107198,
+	0x00107109, 0x00107109, 0x00107109, 0x00107109,
+	0x00107109, 0x00107109, 0x00107109, 0x0010710f,
+	0x0010710f, 0x0201f800, 0x00106c55, 0x0201f800,
+	0x00106bbf, 0x0201f000, 0x00106c4b, 0x42001000,
+	0x0010b7f6, 0x50081000, 0x4930100c, 0x58080002,
+	0x82000580, 0x00000100, 0x04020032, 0x59325808,
+	0x812e59c0, 0x02000800, 0x001005d8, 0x59326809,
+	0x813669c0, 0x04000019, 0x592c040b, 0x82000500,
+	0x0000e000, 0x04000003, 0x0401fba8, 0x0401f002,
+	0x0401fb98, 0x42001000, 0x0010b7f6, 0x50081000,
+	0x4930100b, 0x492c100a, 0x82d00400, 0x00000006,
+	0x48001003, 0x592c000d, 0x80000104, 0x48001004,
+	0x592c000e, 0x48001007, 0x592c000f, 0x48001008,
+	0x0201f000, 0x00100858, 0x42026800, 0x0010be0d,
+	0x592c080a, 0x48066802, 0x82040500, 0x00ffff00,
+	0x04000007, 0x497a6a12, 0x59a81010, 0x82081500,
+	0x00ffff00, 0x80080580, 0x040207dc, 0x82040d00,
+	0x000000ff, 0x800408d0, 0x48066a12, 0x0401f7d7,
+	0x1c01f000, 0x4d2c0000, 0x4d300000, 0x4c580000,
+	0x4c540000, 0x4c500000, 0x5832580a, 0x812e59c0,
+	0x02000800, 0x001005d8, 0x58300002, 0x4a006002,
+	0x00000100, 0x82000580, 0x00000100, 0x0402001c,
+	0x5830000b, 0x5832600c, 0x81300580, 0x04020010,
+	0x0401f828, 0x04020010, 0x592c080d, 0x80040904,
+	0x4004b000, 0x4200a000, 0x0010b54b, 0x4050a800,
+	0x0201f800, 0x0010ab28, 0x42001000, 0x0000dc00,
+	0x0201f800, 0x001078bc, 0x0401f003, 0x0401f819,
+	0x04000fa3, 0x5c00a000, 0x5c00a800, 0x5c00b000,
+	0x5c026000, 0x5c025800, 0x1c01f000, 0x5830000b,
+	0x5832600c, 0x81300580, 0x040207f5, 0x0401f80d,
+	0x040207f5, 0x0201f800, 0x001068d3, 0x02020800,
+	0x001005d8, 0x4a025a06, 0x00000002, 0x0201f800,
+	0x000202da, 0x0201f800, 0x00107911, 0x0401f7ea,
+	0x0201f800, 0x00106c55, 0x4df00000, 0x598c000d,
+	0x81300580, 0x04020009, 0x598c0005, 0x81300580,
+	0x04020006, 0x5c03e000, 0x02000800, 0x00106c4b,
+	0x80000580, 0x1c01f000, 0x5c03e000, 0x02000800,
+	0x00106c4b, 0x82000540, 0x00000001, 0x1c01f000,
+	0x59300403, 0x82000c80, 0x00000056, 0x02021800,
+	0x001005d8, 0x4803c857, 0x0c01f001, 0x00107302,
+	0x0010731d, 0x0010732e, 0x00107431, 0x001073f1,
+	0x001073f5, 0x00107406, 0x0010741a, 0x0010740f,
+	0x0010741a, 0x00107455, 0x0010741a, 0x00107497,
+	0x0010741a, 0x001074a5, 0x0010741a, 0x0010740f,
+	0x0010741a, 0x001074a9, 0x001071f5, 0x001071f5,
+	0x001071f5, 0x001071f5, 0x001071f5, 0x001071f5,
+	0x001071f5, 0x001071f5, 0x001071f5, 0x001071f5,
+	0x001071f5, 0x00107574, 0x00107593, 0x0010759d,
+	0x001071f5, 0x001075b3, 0x00107406, 0x001071f5,
+	0x00107406, 0x0010741a, 0x001071f5, 0x0010732e,
+	0x00107431, 0x001071f5, 0x00107603, 0x0010741a,
+	0x001071f5, 0x00107613, 0x0010741a, 0x001071f5,
+	0x0010740f, 0x001072f3, 0x001071f7, 0x001071f5,
+	0x0010762a, 0x0010765d, 0x001076d7, 0x001071f5,
+	0x001076e7, 0x00107404, 0x001076da, 0x001071f5,
+	0x001075bf, 0x00107700, 0x001071f5, 0x00107735,
+	0x00107788, 0x001071f5, 0x0010720c, 0x00107265,
+	0x00107272, 0x001071f5, 0x00107406, 0x001071f5,
+	0x001072b9, 0x001072c4, 0x001071f5, 0x001071f5,
+	0x00107220, 0x00107245, 0x001077c7, 0x00107808,
+	0x0010782e, 0x001071f5, 0x001071f5, 0x001071f5,
+	0x001077fc, 0x0201f800, 0x001005d8, 0x0401fac5,
+	0x59325808, 0x592c0009, 0x4801a006, 0x592c000a,
+	0x4801a007, 0x592c000b, 0x4801a008, 0x592c000c,
+	0x4801a009, 0x592c000d, 0x4801a00a, 0x4979a00b,
+	0x592c0809, 0x82040d00, 0x00000fff, 0x80040904,
+	0x42001000, 0x0000dc00, 0x0201f000, 0x001078bc,
+	0x4a026202, 0x0000ffff, 0x0401faae, 0x4d2c0000,
+	0x4a01a006, 0x05000000, 0x59325808, 0x592c0009,
+	0x4801a007, 0x592c000a, 0x4801a008, 0x592c000b,
+	0x4801a009, 0x42000800, 0x00000004, 0x42001000,
+	0x0000dc00, 0x5c025800, 0x0201f000, 0x001078bc,
+	0x4c580000, 0x4c500000, 0x4c540000, 0x4d2c0000,
+	0x0401fa98, 0x59325808, 0x5930040b, 0x800000c2,
+	0x4200a800, 0x0010b54b, 0x592cb205, 0x832ca400,
+	0x00000006, 0x0201f800, 0x0010ab17, 0x40580000,
+	0x8054ac00, 0x592c0001, 0x80000540, 0x04000003,
+	0x40025800, 0x0401f7f5, 0x4200a000, 0x0010b54b,
+	0x4050a800, 0x5930b40b, 0x0201f800, 0x0010ab28,
+	0x59300c0b, 0x42001000, 0x0000dc00, 0x5c025800,
+	0x5c00a800, 0x5c00b000, 0x5c00a000, 0x0201f000,
+	0x001078bc, 0x4c580000, 0x4c500000, 0x4c540000,
+	0x4d2c0000, 0x42034800, 0x0010b544, 0x0401fa7f,
+	0x59325808, 0x4a025805, 0x02000000, 0x592c0802,
+	0x82d0ac00, 0x00000006, 0x592cb011, 0x832ca400,
+	0x00000005, 0x0201f800, 0x0010ab17, 0x40580000,
+	0x8054ac00, 0x592e5801, 0x41780000, 0x812e5d40,
+	0x040207f6, 0x42001000, 0x0000dc00, 0x5c025800,
+	0x5c00a800, 0x5c00b000, 0x5c00a000, 0x0201f000,
+	0x001078bc, 0x0401fa57, 0x4a01a006, 0x78000000,
+	0x5930001c, 0x840001c0, 0x4801a407, 0x4979a207,
+	0x42000800, 0x00000002, 0x42001000, 0x0000dc00,
+	0x0201f000, 0x001078bc, 0x4c580000, 0x4c540000,
+	0x4c500000, 0x0401fa55, 0x4a01a006, 0x02000000,
+	0x59a80002, 0x4801a008, 0x59a80003, 0x4801a009,
+	0x59a80000, 0x4801a00a, 0x59a80001, 0x4801a00b,
+	0x5930001c, 0x82000d80, 0x0000e000, 0x04000016,
+	0x82000d80, 0x0000df00, 0x04000006, 0x4a01a407,
+	0x00000010, 0x42000800, 0x00000006, 0x0401f027,
+	0x4a03c840, 0x0010b4eb, 0x4a03c842, 0x0000000d,
+	0x42001800, 0x0010b4eb, 0x0201f800, 0x001007af,
+	0x42000000, 0x0000df00, 0x4200a000, 0x0010b4eb,
+	0x0401f00d, 0x4a03c840, 0x0010b4f8, 0x4a03c842,
+	0x0000000d, 0x42001800, 0x0010b4f8, 0x0201f800,
+	0x001007af, 0x42000000, 0x0000e000, 0x4200a000,
+	0x0010b4f8, 0x82000540, 0x00000010, 0x4801a407,
+	0x4a01a207, 0x00000034, 0x4200b000, 0x0000000d,
+	0x82d0ac00, 0x0000000c, 0x0201f800, 0x0010ab17,
+	0x42000800, 0x00000013, 0x42001000, 0x0000dc00,
+	0x5c00a000, 0x5c00a800, 0x5c00b000, 0x0201f000,
+	0x001078bc, 0x0401fa03, 0x4a01a006, 0x63000028,
+	0x5930001c, 0x4801a007, 0x42000800, 0x00000002,
+	0x42001000, 0x0000dc00, 0x0201f000, 0x001078bc,
+	0x0401fa06, 0x41780000, 0x41780800, 0x42002000,
+	0x00080000, 0x0c01f81b, 0x80000000, 0x80040800,
+	0x42001000, 0x0000000c, 0x59841802, 0x8c0c1d00,
+	0x04020008, 0x42002000, 0x00050000, 0x0c01f811,
+	0x80000000, 0x80040800, 0x82081400, 0x00000004,
+	0x82080540, 0x02000000, 0x4801a006, 0x800408e0,
+	0x5930001c, 0x80040540, 0x4801a007, 0x80080904,
+	0x42001000, 0x0000dc00, 0x0201f000, 0x001078bc,
+	0x001072e9, 0x001072eb, 0x001072ed, 0x001072ef,
+	0x001072f1, 0x4811a008, 0x1c01f000, 0x4811a009,
+	0x1c01f000, 0x4811a00a, 0x1c01f000, 0x4811a00b,
+	0x1c01f000, 0x4811a00c, 0x1c01f000, 0x4a026009,
+	0x0010be0d, 0x59a80010, 0x82000500, 0x000000ff,
+	0x800000d0, 0x42026800, 0x0010be0d, 0x48026a12,
+	0x0401fa3b, 0x41780800, 0x42001000, 0x00005c00,
+	0x0201f000, 0x001078bc, 0x0401f9ba, 0x4a01a006,
+	0x52000000, 0x4979a007, 0x599c0017, 0x8c000500,
+	0x04000005, 0x599c0402, 0x0201f800, 0x001015da,
+	0x4805a007, 0x59a80002, 0x4801a008, 0x59a80003,
+	0x4801a009, 0x59a80000, 0x4801a00a, 0x59a80001,
+	0x4801a00b, 0x59a80010, 0x4801a00c, 0x42000800,
+	0x00000007, 0x42001000, 0x0000dc00, 0x0201f000,
+	0x001078bc, 0x4a026202, 0x0000ffff, 0x0401f99d,
+	0x4a01a006, 0x05000000, 0x59a80010, 0x4801a007,
+	0x59a80002, 0x59a80803, 0x4801a008, 0x4805a009,
+	0x42000800, 0x00000004, 0x42001000, 0x0000dc00,
+	0x0201f000, 0x001078bc, 0x4a026202, 0x0000ffff,
+	0x0401f98c, 0x4d3c0000, 0x417a7800, 0x0201f800,
+	0x001048f6, 0x5c027800, 0x4a01a006, 0x03000000,
+	0x59340403, 0x82000580, 0x000007fe, 0x0402006e,
+	0x4a01a006, 0x04000000, 0x81a40800, 0x4a000800,
+	0x22fffffe, 0x5934000a, 0x84000500, 0x4802680a,
+	0x59c41002, 0x8408150c, 0x480b8802, 0x59a80026,
+	0x8c000508, 0x04000010, 0x59a8002a, 0x4801a007,
+	0x59a8002b, 0x82000500, 0xffff2000, 0x599c0818,
+	0x8c040d16, 0x04000002, 0x8400056a, 0x4801a008,
+	0x4a01a009, 0x00002710, 0x59a8002d, 0x4801a00a,
+	0x0401f039, 0x59a8002a, 0x4801a007, 0x0201f800,
+	0x0010513b, 0x04020009, 0x497b8880, 0x82000500,
+	0x0000ffff, 0x4c000000, 0x0201f800, 0x00101606,
+	0x5c000000, 0x48038880, 0x59a8002b, 0x0201f800,
+	0x0010513b, 0x04020004, 0x82000500, 0x37ffffff,
+	0x0401f003, 0x82000500, 0x3fffffff, 0x599c0818,
+	0x8c040d16, 0x04000002, 0x8400056a, 0x59a80805,
+	0x8c040d10, 0x04000019, 0x59300c03, 0x82041580,
+	0x00000051, 0x04000015, 0x82041580, 0x00000031,
+	0x04000012, 0x4c580000, 0x4c500000, 0x4c540000,
+	0x4200b000, 0x00000004, 0x4200a000, 0x0010b8fa,
+	0x82d0ac00, 0x0000001f, 0x4c000000, 0x0201f800,
+	0x0010ab17, 0x5c000000, 0x5c00a800, 0x5c00a000,
+	0x5c00b000, 0x8400057a, 0x4801a008, 0x4979a009,
+	0x4979a00a, 0x59a80002, 0x59a80803, 0x4801a00b,
+	0x4805a00c, 0x59a80000, 0x59a80801, 0x4801a00d,
+	0x4805a00e, 0x4979a00f, 0x4979a010, 0x4979a011,
+	0x4979a012, 0x4979a013, 0x4979a014, 0x4979a015,
+	0x4979a016, 0x59a8002e, 0x84000576, 0x4801a017,
+	0x59a8002f, 0x4801a018, 0x4979a019, 0x4979a01a,
+	0x0401f043, 0x59a80026, 0x8c000508, 0x0400000d,
+	0x59a8002a, 0x82000500, 0x0000ffff, 0x59c40880,
+	0x80040d80, 0x04000007, 0x497b8880, 0x4c000000,
+	0x0201f800, 0x00101606, 0x5c000000, 0x48038880,
+	0x59a8002a, 0x4801a007, 0x4c640000, 0x4d2c0000,
+	0x59a8c82b, 0x0201f800, 0x00109037, 0x0400000d,
+	0x0201f800, 0x00109597, 0x0402000a, 0x592c0207,
+	0x8c00050e, 0x04000007, 0x8264cd00, 0x0000ffff,
+	0x592c0009, 0x82000500, 0xffff0000, 0x8064cd40,
+	0x4865a008, 0x5c025800, 0x5c00c800, 0x59a8002c,
+	0x4801a009, 0x59a8002d, 0x4801a00a, 0x59a80002,
+	0x59a80803, 0x4801a00b, 0x4805a00c, 0x59a80000,
+	0x59a80801, 0x4801a00d, 0x4805a00e, 0x4979a00f,
+	0x4979a010, 0x4979a011, 0x4979a012, 0x4979a013,
+	0x4979a014, 0x4979a015, 0x4979a016, 0x59a8002e,
+	0x4801a017, 0x59a8002f, 0x4801a018, 0x59a80030,
+	0x4801a019, 0x59a80031, 0x4801a01a, 0x42000800,
+	0x0000001d, 0x42001000, 0x0000dc00, 0x0201f000,
+	0x001078bc, 0x0401f8cb, 0x4a01a006, 0x50000000,
+	0x0401f7b5, 0x0401f8c7, 0x4a01a406, 0x21000010,
+	0x4a01a206, 0x00000014, 0x4979a007, 0x4979a008,
+	0x4979a009, 0x4979a00a, 0x42000800, 0x00000005,
+	0x42001000, 0x0000dc00, 0x0201f000, 0x001078bc,
+	0x0401f8bf, 0x0401f002, 0x0401f8c4, 0x4a01a006,
+	0x02000000, 0x42000800, 0x00000001, 0x42001000,
+	0x0000dc00, 0x0201f000, 0x001078bc, 0x0401f8bb,
+	0x4a01a006, 0x02000000, 0x59300403, 0x82000580,
+	0x00000031, 0x04020794, 0x81a40800, 0x4a000801,
+	0x00fffffe, 0x0401f72b, 0x0401f8b0, 0x4a01a006,
+	0x01000000, 0x5930041a, 0x80000540, 0x04000003,
+	0x4801a407, 0x0401f003, 0x4a01a407, 0x00000003,
+	0x5930021a, 0x80000540, 0x04000003, 0x4801a207,
+	0x0401f003, 0x4a01a207, 0x00002a00, 0x42000800,
+	0x00000002, 0x42001000, 0x0000dc00, 0x0201f000,
+	0x001078bc, 0x4a026202, 0x0000ffff, 0x0401f889,
+	0x4a01a406, 0x00002010, 0x4a01a206, 0x00000014,
+	0x4a01a407, 0x00000800, 0x4a01a207, 0x00002000,
+	0x80000580, 0x599c0817, 0x8c040d0a, 0x04020003,
+	0x82000540, 0x00000020, 0x8c040d08, 0x04000003,
+	0x82000540, 0x00000010, 0x82000540, 0x00000002,
+	0x5934080a, 0x8c040d14, 0x04000005, 0x82040d00,
+	0x00000380, 0x80040540, 0x0401f006, 0x599c0818,
+	0x8c040d18, 0x04000003, 0x82000540, 0x00000380,
+	0x0401f03c, 0x0401f875, 0x4a01a406, 0x00000210,
+	0x4a01a206, 0x00000014, 0x4a01a407, 0x00000800,
+	0x5934000a, 0x8c000516, 0x04000014, 0x59340c05,
+	0x82040500, 0x00000030, 0x04000013, 0x59340a05,
+	0x82040500, 0x0000c000, 0x04020009, 0x8c040d1a,
+	0x04000004, 0x4a01a207, 0x00002100, 0x0401f00c,
+	0x4a01a207, 0x00000100, 0x0401f009, 0x4a01a207,
+	0x00000400, 0x0401f006, 0x4a01a207, 0x00000700,
+	0x0401f003, 0x4a01a207, 0x00000800, 0x80000580,
+	0x599c0817, 0x8c040d0a, 0x04020003, 0x82000540,
+	0x00000020, 0x8c040d08, 0x04000003, 0x82000540,
+	0x00000010, 0x82000540, 0x00000002, 0x59340a00,
+	0x8c040d0e, 0x0400000b, 0x84000550, 0x599c1017,
+	0x8c08150a, 0x04020004, 0x8c040d0a, 0x04000002,
+	0x8400054e, 0x8c040d1c, 0x04000002, 0x84000552,
+	0x4801a20a, 0x42000800, 0x00000005, 0x42001000,
+	0x0000dc00, 0x0201f000, 0x001078bc, 0x0401f833,
+	0x4a01a006, 0x02100014, 0x4a01a007, 0x01000000,
+	0x4979a008, 0x4979a009, 0x4979a00a, 0x42000800,
+	0x00000005, 0x42001000, 0x0000dc00, 0x0201f000,
+	0x001078bc, 0x0401f825, 0x4a01a006, 0x02000000,
+	0x0401f65d, 0x4933c857, 0x0401f820, 0x4a01a006,
+	0x01000000, 0x4a01a407, 0x0000000b, 0x42000800,
+	0x00000002, 0x42001000, 0x0000dc00, 0x0201f000,
+	0x001078bc, 0x42005000, 0x32000000, 0x42006000,
+	0x08290000, 0x41786800, 0x41787800, 0x0401f3df,
+	0x42005000, 0x22000000, 0x42006000, 0x01290000,
+	0x41786800, 0x41787800, 0x0401f3d8, 0x42005000,
+	0x33000000, 0x42006000, 0x08980000, 0x41786800,
+	0x41787800, 0x0401f3d1, 0x42005000, 0x23000000,
+	0x42006000, 0x01980000, 0x41786800, 0x41787800,
+	0x0401f3ca, 0x59300403, 0x82000c80, 0x00000085,
+	0x02001800, 0x001005d8, 0x82000c80, 0x00000093,
+	0x02021800, 0x001005d8, 0x82000480, 0x00000085,
+	0x0c01f001, 0x001074eb, 0x001074ed, 0x001074fb,
+	0x001074eb, 0x001074eb, 0x001074eb, 0x001074eb,
+	0x001074eb, 0x001074eb, 0x001074eb, 0x001074eb,
+	0x001074eb, 0x001074eb, 0x00107506, 0x0201f800,
+	0x001005d8, 0x4933c857, 0x0401f850, 0x59300402,
+	0x4801a407, 0x5930001c, 0x4801a207, 0x4979a408,
+	0x4a01a208, 0x0000ffff, 0x42000800, 0x00000003,
+	0x42001000, 0x0000dc00, 0x0401f3c2, 0x4933c857,
+	0x0401f84e, 0x4a01a406, 0x00000003, 0x4a01a206,
+	0x00000300, 0x42000800, 0x00000001, 0x42001000,
+	0x0000dc00, 0x0401f3b7, 0x4d2c0000, 0x59325808,
+	0x4933c857, 0x492fc857, 0x812e59c0, 0x02000800,
+	0x001005d8, 0x59340a12, 0x82040d00, 0x0000ff00,
+	0x592c000a, 0x82000500, 0x000000ff, 0x900001c0,
+	0x80040540, 0x82000540, 0x00000011, 0x44034800,
+	0x81a5a000, 0x42001000, 0x00000009, 0x42000800,
+	0x00000003, 0x592c0009, 0x82000500, 0xff000000,
+	0x82001d80, 0x84000000, 0x04000009, 0x82001d80,
+	0x85000000, 0x02020800, 0x001005d8, 0x42001000,
+	0x00000007, 0x42000800, 0x00000001, 0x832c1c00,
+	0x00000009, 0x500c0000, 0x4401a000, 0x800c1800,
+	0x80d1a000, 0x80081040, 0x040207fb, 0x42001000,
+	0x0000dc00, 0x5c025800, 0x0401f386, 0x42005000,
+	0x81000000, 0x42006000, 0x00090000, 0x41786800,
+	0x41787800, 0x0401f35d, 0x42005000, 0x84000000,
+	0x42006000, 0x00990000, 0x59300406, 0x82000580,
+	0x00000005, 0x04000002, 0x8430652e, 0x41786800,
+	0x41787800, 0x0401f351, 0x42005000, 0x85000000,
+	0x42006000, 0x00990000, 0x59300406, 0x82000580,
+	0x00000005, 0x04000002, 0x8430652e, 0x41786800,
+	0x41787800, 0x0401f345, 0x59300403, 0x82000c80,
+	0x00000053, 0x02021800, 0x001005d8, 0x82000480,
+	0x0000004b, 0x02001800, 0x001005d8, 0x59326809,
+	0x59368c03, 0x4803c857, 0x0c01f001, 0x001075da,
+	0x001075e2, 0x001075ea, 0x001075f2, 0x0010756b,
+	0x0010756b, 0x0010756b, 0x001075d2, 0x0201f800,
+	0x001005d8, 0x42005000, 0x06000000, 0x42006000,
+	0x08290000, 0x41786800, 0x41787800, 0x0401f327,
+	0x4933c857, 0x0401ff47, 0x4a01a006, 0x12000000,
+	0x59300406, 0x82000580, 0x00000004, 0x04020003,
+	0x59340002, 0x0401f002, 0x59a80010, 0x82000500,
+	0x00ffffff, 0x4801a007, 0x59300419, 0x4801a408,
+	0x59300219, 0x4801a208, 0x4979a009, 0x4979a00a,
+	0x4979a00b, 0x4979a00c, 0x4979a00d, 0x4979a00e,
+	0x4979a00f, 0x4979a010, 0x42000800, 0x0000000b,
+	0x42001000, 0x0000dc00, 0x0401f32a, 0x0401ff29,
+	0x4a01a006, 0x0f000000, 0x5930001c, 0x4801a007,
+	0x42000800, 0x00000002, 0x42001000, 0x0000dc00,
+	0x0401f320, 0x0401ff2d, 0x4a01a006, 0x02000000,
+	0x59c40085, 0x48031004, 0x59880000, 0x4801a007,
+	0x59880001, 0x4801a008, 0x59880002, 0x4801a009,
+	0x59880003, 0x4801a00a, 0x59880004, 0x4801a00b,
+	0x59880005, 0x4801a00c, 0x42000800, 0x00000007,
+	0x42001000, 0x0000dc00, 0x0401f30a, 0x4a026202,
+	0x0000ffff, 0x0401ff07, 0x4a01a006, 0x62000000,
+	0x5930001c, 0x4801a007, 0x42000800, 0x00000002,
+	0x42001000, 0x0000dc00, 0x0401f2fe, 0x0401fefd,
+	0x59300808, 0x4c500000, 0x4c540000, 0x4c580000,
+	0x8204a400, 0x0000000a, 0x5930b01c, 0x82d0ac00,
+	0x00000006, 0x0201f800, 0x0010ab17, 0x5930081c,
+	0x42001000, 0x0000dc00, 0x5c00b000, 0x5c00a800,
+	0x5c00a000, 0x0401f2eb, 0x0401ff9b, 0x59300017,
+	0x4801a006, 0x59300018, 0x4801a007, 0x4a01a008,
+	0x00001000, 0x0401f020, 0x0401ff93, 0x59300017,
+	0x4801a006, 0x59300018, 0x4801a007, 0x4a01a008,
+	0x00004000, 0x0401f018, 0x0401ff8b, 0x59300017,
+	0x4801a006, 0x59300018, 0x4801a007, 0x4a01a008,
+	0x00002000, 0x0401f010, 0x0401ff83, 0x59300017,
+	0x4801a006, 0x59300018, 0x4801a007, 0x4a01a008,
+	0x00000400, 0x0401f008, 0x0401ff7b, 0x59300017,
+	0x4801a006, 0x59300018, 0x4801a007, 0x4a01a008,
+	0x00000200, 0x4979a009, 0x4979a00a, 0x4979a00b,
+	0x4979a00c, 0x4979a00d, 0x42000800, 0x00000008,
+	0x42001000, 0x0000dc00, 0x0401f2ba, 0x0401fec7,
+	0x4a01a006, 0x02000014, 0x4979a407, 0x4979a207,
+	0x59a8003a, 0x4801a008, 0x59a8003b, 0x4801a009,
+	0x4a01a00a, 0x00047878, 0x42000800, 0x00000005,
+	0x42001000, 0x0000dc00, 0x0401f2aa, 0x0401feb7,
+	0x4a01a006, 0x02140018, 0x4a01a407, 0x00000800,
+	0x5930001c, 0x82000d00, 0xff000000, 0x900409c0,
+	0x4805a207, 0x82000500, 0x00ffffff, 0x4801a00a,
+	0x4979a408, 0x4979a208, 0x4979a409, 0x4979a209,
+	0x4979a00b, 0x42000800, 0x00000006, 0x42001000,
+	0x0000dc00, 0x0401f293, 0x4803c856, 0x4d380000,
+	0x4d1c0000, 0x42027000, 0x00000035, 0x0201f800,
+	0x001093ba, 0x0402001e, 0x0401fe8a, 0x4a01a006,
+	0x13000000, 0x5932381e, 0x591c0019, 0x4801a005,
+	0x591c0406, 0x82000580, 0x00000003, 0x04000007,
+	0x59300809, 0x58040002, 0x82000500, 0x00ffffff,
+	0x4801a007, 0x0401f003, 0x59a80010, 0x4801a007,
+	0x59300419, 0x4801a408, 0x59300219, 0x4801a208,
+	0x42000800, 0x00000003, 0x42001000, 0x0000dc00,
+	0x5c023800, 0x5c027000, 0x0401f26e, 0x0201f800,
+	0x00106c55, 0x598c000d, 0x81300580, 0x02020800,
+	0x001005d8, 0x0201f800, 0x00106bbf, 0x0201f800,
+	0x0002077d, 0x5c023800, 0x5c027000, 0x0201f000,
+	0x00106c4b, 0x4803c856, 0x4d2c0000, 0x4d1c0000,
+	0x5932381e, 0x811e39c0, 0x02000800, 0x001005d8,
+	0x591c0c06, 0x82040580, 0x00000006, 0x0400000d,
+	0x82040580, 0x00000003, 0x04000036, 0x4a026403,
+	0x00000037, 0x4a02641a, 0x00000003, 0x4a02621a,
+	0x00001700, 0x5c023800, 0x5c025800, 0x0401f064,
+	0x0401f84b, 0x42001000, 0x40000000, 0x591c0203,
+	0x591c0804, 0x8c040d3e, 0x04020023, 0x82000c80,
+	0x0000000e, 0x0c001003, 0x0201f800, 0x001005d8,
+	0x00107691, 0x0010769d, 0x00107693, 0x0010769d,
+	0x00107699, 0x00107691, 0x00107691, 0x0010769d,
+	0x0010769d, 0x00107691, 0x00107691, 0x00107691,
+	0x00107691, 0x00107691, 0x0010769d, 0x00107691,
+	0x0010769d, 0x0201f800, 0x001005d8, 0x591c0414,
+	0x4803c857, 0x8c000518, 0x04000003, 0x8c000512,
+	0x04000003, 0x80001580, 0x0401f003, 0x42001000,
+	0x20000000, 0x591c0015, 0x4801a00a, 0x0401f018,
+	0x0401f81f, 0x591e5808, 0x812e59c0, 0x02000800,
+	0x001005d8, 0x592c100f, 0x591c0011, 0x80080480,
+	0x4801a00a, 0x591c0203, 0x591c0804, 0x8c040d3e,
+	0x04020007, 0x82000d80, 0x00000002, 0x04000007,
+	0x82000d80, 0x00000004, 0x04000004, 0x42001000,
+	0x40000000, 0x0401f002, 0x80001580, 0x4809a00b,
+	0x42000800, 0x00000006, 0x42001000, 0x0000dc00,
+	0x5c023800, 0x5c025800, 0x0401f1fe, 0x4803c856,
+	0x0401fe0a, 0x4a01a006, 0x02000000, 0x59300c19,
+	0x4805a407, 0x59300a19, 0x4805a207, 0x59a81010,
+	0x59300809, 0x58041802, 0x820c1d00, 0x00ffffff,
+	0x5930081e, 0x58040406, 0x82000580, 0x00000003,
+	0x04020004, 0x4809a008, 0x480da009, 0x0401f003,
+	0x480da008, 0x4809a009, 0x1c01f000, 0x4803c856,
+	0x0401fdf2, 0x0401f003, 0x4803c856, 0x0401fde8,
+	0x4a01a006, 0x01000000, 0x5930041a, 0x4801a407,
+	0x5930021a, 0x4801a207, 0x42000800, 0x00000002,
+	0x42001000, 0x0000dc00, 0x0401f1d6, 0x4803c856,
+	0x4d1c0000, 0x0401fdcc, 0x4a01a006, 0x14000000,
+	0x5932381e, 0x591c0019, 0x4801a005, 0x59300419,
+	0x4801a407, 0x59300219, 0x4801a207, 0x59300015,
+	0x4801a008, 0x59300216, 0x82000500, 0x000000ff,
+	0x840001c0, 0x4801a409, 0x42000800, 0x00000004,
+	0x42001000, 0x0000dc00, 0x5c023800, 0x0401f1bd,
+	0x4803c856, 0x0401f80b, 0x5930041a, 0x900001c0,
+	0x4801a005, 0x0401f9ec, 0x41780800, 0x42001000,
+	0x00005c00, 0x0401f9b3, 0x0201f000, 0x0010604d,
+	0x4803c856, 0x59300817, 0x82041c00, 0x00000005,
+	0x46034800, 0x00000021, 0x58040404, 0x82000500,
+	0x0000f000, 0x82000580, 0x00003000, 0x04000003,
+	0x46034800, 0x00000041, 0x81a5a000, 0x580c0001,
+	0x82000d00, 0x00ffffff, 0x82040d40, 0xc2000000,
+	0x4805a000, 0x580c0800, 0x82041500, 0x00ffffff,
+	0x82000500, 0xff000000, 0x80080540, 0x4801a001,
+	0x580c0002, 0x82000580, 0x00c00000, 0x82000500,
+	0x00fd0300, 0x4801a002, 0x580c0003, 0x4801a003,
+	0x580c0404, 0x4801a404, 0x580c0204, 0x4801a204,
+	0x1c01f000, 0x4803c856, 0x59a80026, 0x82000500,
+	0x00000028, 0x04020009, 0x59a80026, 0x82000500,
+	0x00000028, 0x04000003, 0x497a6a12, 0x0401f003,
+	0x4a026a12, 0x0000ff00, 0x42005000, 0x22000000,
+	0x42006000, 0x01380000, 0x41786800, 0x41787800,
+	0x0401f952, 0x59301008, 0x4a01a006, 0x54000000,
+	0x59a80010, 0x82000500, 0x00ffffff, 0x58080c0a,
+	0x800408f0, 0x80040540, 0x4801a007, 0x5808000a,
+	0x82000500, 0xff000000, 0x4801a008, 0x59a80002,
+	0x4801a009, 0x59a80003, 0x4801a00a, 0x59a80000,
+	0x4801a00b, 0x59a80001, 0x4801a00c, 0x5808000c,
+	0x9c0001c0, 0x4801a00d, 0x5808000d, 0x9c0001c0,
+	0x4801a00e, 0x5808000e, 0x9c0001c0, 0x4801a00f,
+	0x5808000f, 0x9c0001c0, 0x4801a010, 0x58080010,
+	0x9c0001c0, 0x4801a011, 0x58080011, 0x9c0001c0,
+	0x4801a012, 0x58080012, 0x9c0001c0, 0x4801a013,
+	0x58080013, 0x9c0001c0, 0x4801a014, 0x58080010,
+	0x9c0001c0, 0x4801a015, 0x58080011, 0x9c0001c0,
+	0x4801a016, 0x58080012, 0x9c0001c0, 0x4801a017,
+	0x58080013, 0x9c0001c0, 0x4801a018, 0x42000800,
+	0x00000013, 0x42001000, 0x0000dc00, 0x0401f135,
+	0x4803c856, 0x42005000, 0x22000000, 0x42006000,
+	0x01290000, 0x41786800, 0x41787800, 0x0401f90b,
+	0x59301008, 0x4a01a006, 0x55000000, 0x5808000b,
+	0x82000500, 0x00ffffff, 0x58080c0a, 0x800408f0,
+	0x80040540, 0x4801a007, 0x5808080a, 0x82040d00,
+	0xff000000, 0x59a80010, 0x82000500, 0x00ffffff,
+	0x80040540, 0x4801a008, 0x5808000c, 0x9c0001c0,
+	0x4801a009, 0x5808000d, 0x9c0001c0, 0x4801a00a,
+	0x5808000e, 0x9c0001c0, 0x4801a00b, 0x5808000f,
+	0x9c0001c0, 0x4801a00c, 0x59a80002, 0x4801a00d,
+	0x59a80003, 0x4801a00e, 0x59a80000, 0x4801a00f,
+	0x59a80001, 0x4801a010, 0x58080010, 0x4801a011,
+	0x58080011, 0x4801a012, 0x58080012, 0x4801a013,
+	0x58080013, 0x4801a014, 0x4979a015, 0x4979a016,
+	0x4979a017, 0x4979a018, 0x42000800, 0x00000013,
+	0x42001000, 0x0000dc00, 0x0401f0f6, 0x0401fd03,
+	0x5930001c, 0x800001c0, 0x04000008, 0x4a01a006,
+	0x01000000, 0x4a01a407, 0x00000003, 0x42000800,
+	0x00000002, 0x0401f028, 0x4a01a006, 0x02000000,
+	0x41780800, 0x836c0580, 0x00000004, 0x04020003,
+	0x84040d42, 0x0401f00d, 0x0201f800, 0x0010513b,
+	0x04020003, 0x84040d4a, 0x0401f002, 0x84040d48,
+	0x59a80026, 0x8c000506, 0x04020003, 0x8c00050a,
+	0x04000002, 0x84040d46, 0x4805a207, 0x59c40085,
+	0x48031004, 0x4c580000, 0x4c500000, 0x4c540000,
+	0x4200b000, 0x00000006, 0x8388a400, 0x00000000,
+	0x82d0ac00, 0x00000008, 0x0201f800, 0x0010ab17,
+	0x5c00a800, 0x5c00a000, 0x5c00b000, 0x42000800,
+	0x00000008, 0x42001000, 0x0000dc00, 0x0401f0c1,
+	0x0401fcc0, 0x4a01a006, 0x56000000, 0x59340006,
+	0x4801a007, 0x59340007, 0x4801a008, 0x42000800,
+	0x00000003, 0x42001000, 0x0000dc00, 0x0401f0b5,
+	0x4803c856, 0x0401fcc1, 0x5930081c, 0x800409c0,
+	0x0400000e, 0x82040580, 0x0000ffff, 0x04000004,
+	0x82040480, 0x00000007, 0x04021008, 0x4a01a006,
+	0x01000000, 0x4a01a407, 0x00000003, 0x42000800,
+	0x00000002, 0x0401f012, 0x4a01a006, 0x0200001c,
+	0x4a01a007, 0x00000001, 0x42001000, 0x0010b4f0,
+	0x50080000, 0x9c0001c0, 0x4801a009, 0x59a80010,
+	0x4801a00a, 0x59a80002, 0x59a80803, 0x4801a00b,
+	0x4805a00c, 0x42000800, 0x00000007, 0x42001000,
+	0x0000dc00, 0x0401f08f, 0x4d2c0000, 0x0401fc8d,
+	0x59325808, 0x592c0008, 0x82000500, 0x00ffffff,
+	0x4801a001, 0x4a01a006, 0x51000000, 0x5c025800,
+	0x0201f000, 0x00107344, 0x4803c856, 0x59a80810,
+	0x82040d00, 0x000000ff, 0x59325808, 0x59326809,
+	0x59a83026, 0x8c18350a, 0x04020008, 0x8c00050e,
+	0x04020006, 0x80001d80, 0x59a82010, 0x82102500,
+	0x000000ff, 0x0401f001, 0x59300406, 0x4803c857,
+	0x82000d80, 0x00000009, 0x04000006, 0x82000d80,
+	0x0000000a, 0x0400002e, 0x0201f800, 0x001005d8,
+	0x59300015, 0x8c00051e, 0x04020020, 0x42005000,
+	0x04000000, 0x42006000, 0x05000000, 0x592c040a,
+	0x82000500, 0x00000030, 0x800000e0, 0x80306540,
+	0x5934000a, 0x8c000508, 0x04000002, 0x84306546,
+	0x41786800, 0x41787800, 0x0401f831, 0x59300c14,
+	0x80040000, 0x48026414, 0x40040000, 0x800000d0,
+	0x82000540, 0x00000020, 0x4801a403, 0x83180d40,
+	0x00000038, 0x42001000, 0x0000c920, 0x0401f860,
+	0x0201f000, 0x00106052, 0x59a80026, 0x82000500,
+	0x00000028, 0x04000003, 0x497a6a12, 0x0401f7dc,
+	0x4a026a12, 0x0000ff00, 0x0401f7d9, 0x42005000,
+	0x02000000, 0x42006000, 0x20290000, 0x41786800,
+	0x41787800, 0x0401f812, 0x83180d40, 0x00000038,
+	0x42001000, 0x0000c9a0, 0x0401f849, 0x42000800,
+	0x000007d0, 0x59300011, 0x82000500, 0xfff00000,
+	0x80000540, 0x04000003, 0x42000800, 0x00001b58,
+	0x41781000, 0x0201f000, 0x00106054, 0x4201a000,
+	0x00000000, 0x0401f003, 0x4201a000, 0x00000011,
+	0x59340a12, 0x82040d00, 0x0000ff00, 0x59a80010,
+	0x82000500, 0x000000ff, 0x900001c0, 0x80040540,
+	0x80d00540, 0x44034800, 0x81a5a000, 0x59340002,
+	0x82000500, 0x00ffffff, 0x80280540, 0x4801a000,
+	0x59a80010, 0x4801a001, 0x4831a002, 0x82340540,
+	0x00000000, 0x4801a003, 0x59300402, 0x4801a404,
+	0x59300a02, 0x4805a204, 0x8c30652e, 0x04000003,
+	0x4805a404, 0x4801a204, 0x483da005, 0x1c01f000,
+	0x4803c856, 0x4c040000, 0x0401f822, 0x5c000800,
+	0x40040000, 0x80081540, 0x800000c4, 0x82000540,
+	0x00002000, 0x4803910a, 0x59b400f6, 0x82000500,
+	0x00000018, 0x040207fd, 0x4a0368f0, 0x0010b544,
+	0x4a0368f1, 0x0010b54b, 0x480b68f3, 0x4a0378e4,
+	0x00008000, 0x0201f000, 0x0010604d, 0x4807c857,
+	0x480a2800, 0x4c040000, 0x0401f80a, 0x5c000800,
+	0x59b400f6, 0x8c00050a, 0x040207fe, 0x49a768f2,
+	0x480768f4, 0x4a0378e4, 0x00008000, 0x1c01f000,
+	0x4a0378e4, 0x0000c000, 0x59bc00e4, 0x8c000520,
+	0x0400000c, 0x4a0378e4, 0x00008000, 0x42007000,
+	0x000003e8, 0x59bc00e4, 0x8c000520, 0x040007f5,
+	0x80387040, 0x02000800, 0x001005d8, 0x0401f7fa,
+	0x1c01f000, 0x82000500, 0xffff0000, 0x82000580,
+	0x01050000, 0x0402000d, 0x599c0818, 0x8c040d10,
+	0x0400000a, 0x59a80807, 0x8c040d0a, 0x04000007,
+	0x42001000, 0x0000804f, 0x41781800, 0x41782000,
+	0x0201f800, 0x00103a3e, 0x1c01f000, 0x41781000,
+	0x42026000, 0x0010d1c0, 0x59a8180e, 0x480a6402,
+	0x4a026202, 0x0000ffff, 0x80081000, 0x800c1840,
+	0x04000004, 0x83326400, 0x00000024, 0x0401f7f8,
+	0x1c01f000, 0x4933c857, 0x59300203, 0x82000580,
+	0x00000000, 0x0400002c, 0x59300406, 0x4803c857,
+	0x82000d80, 0x00000004, 0x04000011, 0x82000d80,
+	0x00000001, 0x0400000e, 0x82000d80, 0x00000003,
+	0x04000006, 0x82000d80, 0x00000006, 0x04020011,
+	0x0201f800, 0x0010a5df, 0x5930001c, 0x800001c0,
+	0x02020800, 0x0010984e, 0x0401f00a, 0x5930081e,
+	0x4807c857, 0x800409c0, 0x04000006, 0x5804001c,
+	0x4803c857, 0x81300580, 0x04020002, 0x4978081c,
+	0x497a6008, 0x4a026004, 0x00004000, 0x59a80037,
+	0x82000c80, 0x00000051, 0x04001002, 0x80000102,
+	0x48026206, 0x497a6205, 0x497a6009, 0x4a026406,
+	0x00000007, 0x1c01f000, 0x8166c9c0, 0x0400001c,
+	0x41626000, 0x41580000, 0x59300a03, 0x82040d80,
+	0x00000000, 0x04000008, 0x83326400, 0x00000024,
+	0x81300c80, 0x040017f9, 0x42026000, 0x0010d1c0,
+	0x0401f7f6, 0x4933c857, 0x8166c840, 0x83300c00,
+	0x00000024, 0x80040480, 0x04021006, 0x4006c000,
+	0x4a026203, 0x00000008, 0x813261c0, 0x1c01f000,
+	0x4202c000, 0x0010d1c0, 0x0401f7fa, 0x42000000,
+	0x0010b854, 0x0201f800, 0x0010aa47, 0x4933c856,
+	0x417a6000, 0x0401f7f5, 0x4933c857, 0x83380580,
+	0x00000013, 0x0402000b, 0x59300004, 0x8c00053e,
+	0x04000007, 0x0201f800, 0x00106c55, 0x0201f800,
+	0x00106bbf, 0x0201f800, 0x00106c4b, 0x1c01f000,
+	0x4933c857, 0x59880052, 0x80000000, 0x48031052,
+	0x1c01f000, 0x4933c857, 0x59300203, 0x82003480,
+	0x0000000e, 0x02021800, 0x001005d8, 0x4d2c0000,
+	0x0c01f803, 0x5c025800, 0x1c01f000, 0x00107991,
+	0x00107efd, 0x0010804a, 0x00107991, 0x001080b0,
+	0x00107af5, 0x00107991, 0x00107991, 0x00107e93,
+	0x00107991, 0x00107991, 0x00107991, 0x00107991,
+	0x00107991, 0x0201f800, 0x001005d8, 0x4933c857,
+	0x59300203, 0x82003480, 0x0000000e, 0x02021800,
+	0x001005d8, 0x0c01f001, 0x001079a8, 0x00108a3d,
+	0x001079a8, 0x001079a8, 0x001079a8, 0x001079a8,
+	0x001079a8, 0x001079a8, 0x001089e5, 0x00108a58,
+	0x00108ac6, 0x00108a58, 0x00108ac6, 0x001079a8,
+	0x0201f800, 0x001005d8, 0x0201f800, 0x001005d8,
+	0x4933c857, 0x4d2c0000, 0x59325808, 0x59300203,
+	0x82003480, 0x0000000e, 0x02021800, 0x001005d8,
+	0x0c01f803, 0x5c025800, 0x1c01f000, 0x001079c5,
+	0x001079c5, 0x001079c5, 0x001079e1, 0x00107a2d,
+	0x001079c5, 0x001079c5, 0x001079c5, 0x001079c7,
+	0x001079c5, 0x001079c5, 0x001079c5, 0x001079c5,
+	0x001079c5, 0x0201f800, 0x001005d8, 0x4933c857,
+	0x83380580, 0x00000040, 0x02020800, 0x001005d8,
+	0x4a026007, 0x00082000, 0x4a026203, 0x00000003,
+	0x493a6403, 0x4a025c08, 0x00000001, 0x592c000d,
+	0x48026011, 0x497a6013, 0x592c0208, 0x800000c2,
+	0x800010c4, 0x80081400, 0x480a6206, 0x0201f800,
+	0x00100f4e, 0x42000800, 0x80000060, 0x0201f000,
+	0x00106721, 0x4933c857, 0x83380480, 0x00000050,
+	0x02021800, 0x001005d8, 0x83380480, 0x00000049,
+	0x02001800, 0x001005d8, 0x0c01f001, 0x001079f4,
+	0x001079ff, 0x001079f2, 0x001079f2, 0x001079f2,
+	0x001079f2, 0x00107a0a, 0x0201f800, 0x001005d8,
+	0x4a026203, 0x00000004, 0x4a025c08, 0x00000002,
+	0x592c0207, 0x48025c09, 0x592c0209, 0x48025a07,
+	0x592c000c, 0x4802580d, 0x1c01f000, 0x0201f800,
+	0x00106b8a, 0x0201f800, 0x00109037, 0x04000005,
+	0x4a025a06, 0x00000006, 0x0201f800, 0x000202da,
+	0x0201f000, 0x0002077d, 0x0201f800, 0x00106b8a,
+	0x4d3c0000, 0x417a7800, 0x0201f800, 0x0010203c,
+	0x5c027800, 0x42003000, 0x00000014, 0x41782800,
+	0x42002000, 0x00000002, 0x4d400000, 0x4d440000,
+	0x59368c03, 0x42028000, 0x00000029, 0x0201f800,
+	0x0010985e, 0x5c028800, 0x5c028000, 0x42000000,
+	0x0010b864, 0x0201f800, 0x0010aa47, 0x0201f800,
+	0x00109037, 0x02000000, 0x0002077d, 0x4a025a06,
+	0x00000029, 0x0201f800, 0x000202da, 0x0201f000,
+	0x0002077d, 0x4933c857, 0x83380580, 0x00000048,
+	0x04000005, 0x83380580, 0x00000053, 0x02020800,
+	0x001005d8, 0x592c0206, 0x82000580, 0x00000007,
+	0x04000009, 0x59300011, 0x80000540, 0x04000006,
+	0x592c080c, 0x80040480, 0x4802580c, 0x4a025a06,
+	0x00000015, 0x592c0206, 0x80000540, 0x04020003,
+	0x4a025a06, 0x00000000, 0x0201f800, 0x000202da,
+	0x0201f000, 0x0002077d, 0x4933c857, 0x4d2c0000,
+	0x4c500000, 0x4c540000, 0x4c580000, 0x0201f800,
+	0x001007e4, 0x02000800, 0x001005d8, 0x497a5a06,
+	0x59c80017, 0x82000500, 0x0000f000, 0x48025c07,
+	0x59a80816, 0x82040c00, 0x00000018, 0x48065a07,
+	0x412c7800, 0x4d2c0000, 0x41cca000, 0x42002800,
+	0x00000001, 0x42001000, 0x0000002c, 0x82040480,
+	0x0000002d, 0x04021006, 0x832cac00, 0x00000009,
+	0x0201f800, 0x00108b96, 0x0401f02e, 0x40043000,
+	0x42000800, 0x0000002c, 0x832cac00, 0x00000009,
+	0x0201f800, 0x00108b96, 0x82183480, 0x0000002c,
+	0x0201f800, 0x001007e4, 0x0400001a, 0x80142800,
+	0x4a025804, 0x00000110, 0x492c7801, 0x82180c80,
+	0x0000003d, 0x04021007, 0x40180800, 0x832cac00,
+	0x00000005, 0x0201f800, 0x00108b96, 0x0401f015,
+	0x82081400, 0x0000003c, 0x82183480, 0x0000003c,
+	0x42000800, 0x0000003c, 0x412c7800, 0x832cac00,
+	0x00000005, 0x0201f800, 0x00108b96, 0x0401f7e5,
+	0x5c025800, 0x592c0206, 0x8400055e, 0x48025a06,
+	0x592c0407, 0x80080540, 0x48025c07, 0x0401f002,
+	0x5c025800, 0x813669c0, 0x04000003, 0x59343403,
+	0x0401f003, 0x42003000, 0x0000ffff, 0x49325808,
+	0x481a5c06, 0x82100580, 0x00000054, 0x04020002,
+	0x491e5813, 0x841401c0, 0x80100540, 0x48025804,
+	0x592c0001, 0x497a5801, 0x4c000000, 0x0201f800,
+	0x000202da, 0x5c025800, 0x812e59c0, 0x040207f9,
+	0x5c00b000, 0x5c00a800, 0x5c00a000, 0x5c025800,
+	0x1c01f000, 0x4803c856, 0x4c5c0000, 0x4d2c0000,
+	0x4c500000, 0x4c540000, 0x4c580000, 0x412cb800,
+	0x592c040b, 0x8c000516, 0x04000003, 0x41cca000,
+	0x0401f003, 0x83cca400, 0x00000006, 0x4008b000,
+	0x41781000, 0x82580480, 0x00000012, 0x04001004,
+	0x4200b000, 0x00000012, 0x40001000, 0x4c080000,
+	0x4d2c0000, 0x0201f800, 0x001007e4, 0x04000023,
+	0x5c001800, 0x492c1801, 0x485a5800, 0x832cac00,
+	0x00000002, 0x0201f800, 0x0010ab28, 0x585c040b,
+	0x8c000500, 0x0400000e, 0x832c1400, 0x00000002,
+	0x8c000516, 0x04000003, 0x82081400, 0x00000006,
+	0x46001000, 0x00000001, 0x80081000, 0x46001000,
+	0x00000900, 0x84000500, 0x4800bc0b, 0x5c001000,
+	0x800811c0, 0x040207da, 0x82000540, 0x00000001,
+	0x5c00b000, 0x5c00a800, 0x5c00a000, 0x5c025800,
+	0x5c00b800, 0x1c01f000, 0x5c025800, 0x5c001000,
+	0x0401f7f8, 0x4933c857, 0x83380d80, 0x00000015,
+	0x04020003, 0x0201f000, 0x0002077d, 0x83380d80,
+	0x00000016, 0x02020800, 0x001005d8, 0x0201f000,
+	0x0002077d, 0x4933c857, 0x4d2c0000, 0x4c500000,
+	0x4c540000, 0x4c580000, 0x59325808, 0x83cca400,
+	0x00000006, 0x59cc1806, 0x820c0580, 0x01000000,
+	0x04020004, 0x4200b000, 0x00000002, 0x0401f00f,
+	0x4200b000, 0x00000008, 0x832cac00, 0x00000005,
+	0x0201f800, 0x0010ab17, 0x8c0c1d00, 0x0400000b,
+	0x4200b000, 0x00000008, 0x592e5801, 0x812e59c0,
+	0x02000800, 0x001005d8, 0x832cac00, 0x00000005,
+	0x0201f800, 0x0010ab17, 0x0401f816, 0x5c00b000,
+	0x5c00a800, 0x5c00a000, 0x5c025800, 0x1c01f000,
+	0x4933c857, 0x4c500000, 0x4c540000, 0x4c580000,
+	0x83cca400, 0x00000006, 0x5930a808, 0x8254ac00,
+	0x00000005, 0x4200b000, 0x00000007, 0x0201f800,
+	0x0010ab17, 0x5c00b000, 0x5c00a800, 0x5c00a000,
+	0x4933c857, 0x0201f800, 0x00109037, 0x02000000,
+	0x0002077d, 0x4d2c0000, 0x0201f800, 0x00109597,
+	0x0402000b, 0x41780800, 0x4d400000, 0x42028000,
+	0x00000000, 0x0201f800, 0x0010943b, 0x5c028000,
+	0x5c025800, 0x0201f000, 0x0002077d, 0x5931d821,
+	0x58ef400b, 0x58ee580d, 0x4a025a04, 0x00000103,
+	0x58ec0009, 0x0801f800, 0x5c025800, 0x0201f000,
+	0x0002077d, 0x4933c857, 0x59cc1806, 0x820c0580,
+	0x02000000, 0x04020014, 0x4a026802, 0x00fffffd,
+	0x5934000a, 0x84000504, 0x4802680a, 0x59300808,
+	0x800409c0, 0x02000000, 0x0002077d, 0x4a000a04,
+	0x00000103, 0x480c0805, 0x5931d821, 0x58ef400b,
+	0x58ee580d, 0x58ec0009, 0x0801f800, 0x0201f000,
+	0x0002077d, 0x42000000, 0x0010b86c, 0x0201f800,
+	0x0010aa47, 0x4c0c0000, 0x0401f804, 0x5c001800,
+	0x040207eb, 0x1c01f000, 0x4933c857, 0x4d2c0000,
+	0x59325808, 0x812e59c0, 0x04020009, 0x497a6206,
+	0x497a6205, 0x4d380000, 0x42027000, 0x00000022,
+	0x0401fb77, 0x5c027000, 0x80000580, 0x5c025800,
+	0x1c01f000, 0x4933c857, 0x4d2c0000, 0x4c500000,
+	0x4c540000, 0x4c580000, 0x59325808, 0x592e5801,
+	0x832cac00, 0x00000005, 0x83cca400, 0x00000006,
+	0x59c80817, 0x82040d00, 0x000003ff, 0x82041480,
+	0x0000000f, 0x0400101b, 0x4200b000, 0x0000000f,
+	0x0201f800, 0x0010ab17, 0x592e5801, 0x832cac00,
+	0x00000005, 0x82080c80, 0x0000000f, 0x0400100d,
+	0x4200b000, 0x0000000f, 0x0201f800, 0x0010ab17,
+	0x592e5801, 0x832cac00, 0x00000005, 0x82041480,
+	0x0000000f, 0x04001007, 0x42001000, 0x0000000f,
+	0x4008b000, 0x0201f800, 0x0010ab17, 0x0401f004,
+	0x4004b000, 0x0201f800, 0x0010ab17, 0x5931d821,
+	0x58ef400b, 0x58ee580d, 0x4a025a04, 0x00000103,
+	0x592e5801, 0x58ec0009, 0x0801f800, 0x0201f800,
+	0x0002077d, 0x5c00b000, 0x5c00a800, 0x5c00a000,
+	0x5c025800, 0x1c01f000, 0x4933c857, 0x4d2c0000,
+	0x4c500000, 0x4c540000, 0x4c580000, 0x59cc0006,
+	0x82000d80, 0x01000000, 0x0400002c, 0x59cc0007,
+	0x9000b1c0, 0x8258b500, 0x000000ff, 0x8058b104,
+	0x8258b400, 0x00000002, 0x82580c80, 0x00000007,
+	0x04001003, 0x4200b000, 0x00000006, 0x83cca400,
+	0x00000006, 0x59301008, 0x800811c0, 0x02000800,
+	0x001005d8, 0x8208ac00, 0x00000005, 0x0201f800,
+	0x0010ab17, 0x82000d00, 0xff000000, 0x800409c0,
+	0x04000019, 0x8200b500, 0x000000ff, 0x8058b104,
+	0x82580c80, 0x0000000e, 0x04001003, 0x4200b000,
+	0x0000000d, 0x58081001, 0x800811c0, 0x02000800,
+	0x001005d8, 0x8208ac00, 0x00000005, 0x0201f800,
+	0x0010ab17, 0x0401f008, 0x59301008, 0x800811c0,
+	0x02000800, 0x001005d8, 0x48001005, 0x59cc0007,
+	0x48001006, 0x0401ff3b, 0x5c00b000, 0x5c00a800,
+	0x5c00a000, 0x5c025800, 0x1c01f000, 0x4933c857,
+	0x42000800, 0x00000000, 0x59cc0006, 0x82000580,
+	0x02000000, 0x04000003, 0x42000800, 0x00000001,
+	0x4d2c0000, 0x59325808, 0x812e59c0, 0x02000800,
+	0x001005d8, 0x48065a06, 0x0201f800, 0x000202da,
+	0x5c025800, 0x0201f000, 0x0002077d, 0x4933c857,
+	0x4d2c0000, 0x4c500000, 0x4c540000, 0x4c580000,
+	0x4200b000, 0x00000002, 0x59cc0806, 0x82040580,
+	0x01000000, 0x04000004, 0x8204b500, 0x0000ffff,
+	0x8058b104, 0x83cca400, 0x00000006, 0x59300008,
+	0x8200ac00, 0x00000005, 0x0201f800, 0x0010ab17,
+	0x0401ff0c, 0x5c00b000, 0x5c00a800, 0x5c00a000,
+	0x5c025800, 0x1c01f000, 0x4933c857, 0x4803c857,
+	0x4807c857, 0x480bc857, 0x480fc857, 0x4813c857,
+	0x481bc857, 0x492fc857, 0x4d2c0000, 0x4c000000,
+	0x0201f800, 0x001007d3, 0x5c000000, 0x0400000f,
+	0x48025803, 0x5c000000, 0x4802580a, 0x4c000000,
+	0x481a5801, 0x48125809, 0x48065804, 0x480a5807,
+	0x480e5808, 0x412c1000, 0x0201f800, 0x00100858,
+	0x82000540, 0x00000001, 0x5c025800, 0x1c01f000,
+	0x4933c857, 0x4d1c0000, 0x59cc0001, 0x82000500,
+	0x00ffffff, 0x59341002, 0x82081500, 0x00ffffff,
+	0x80080580, 0x0402001f, 0x497a6205, 0x4d380000,
+	0x42027000, 0x00000035, 0x0201f800, 0x001093ba,
+	0x5c027000, 0x04020012, 0x591c001c, 0x800001c0,
+	0x0400000f, 0x497a381c, 0x591c0414, 0x8c000502,
+	0x02000800, 0x001005d8, 0x84000502, 0x48023c14,
+	0x591c1406, 0x82080580, 0x00000003, 0x04000006,
+	0x82080580, 0x00000006, 0x04000005, 0x0401fc9e,
+	0x0401f004, 0x0401f805, 0x0401f002, 0x0401f8c0,
+	0x5c023800, 0x1c01f000, 0x4d2c0000, 0x591e5808,
+	0x4933c857, 0x491fc857, 0x493bc857, 0x492fc857,
+	0x83380580, 0x00000015, 0x040000b3, 0x83380580,
+	0x00000016, 0x040200ae, 0x4d300000, 0x411e6000,
+	0x59cc0207, 0x4803c857, 0x82000d00, 0x0000ff00,
+	0x82040580, 0x00001700, 0x04000004, 0x82040580,
+	0x00000300, 0x0402005b, 0x591c0203, 0x4803c857,
+	0x82000580, 0x0000000d, 0x0400003f, 0x812e59c0,
+	0x0400009a, 0x591c0202, 0x4803c857, 0x82000580,
+	0x0000ffff, 0x0402007e, 0x592c020a, 0x4803c857,
+	0x82000500, 0x00000003, 0x82000580, 0x00000002,
+	0x04020007, 0x592c080f, 0x591c0011, 0x4803c857,
+	0x4807c857, 0x80040580, 0x04020071, 0x591c0414,
+	0x4803c857, 0x8c000500, 0x0402006d, 0x41780800,
+	0x591c1206, 0x42000000, 0x0000000a, 0x0201f800,
+	0x001066a0, 0x592c0406, 0x4803c857, 0x800001c0,
+	0x0400000c, 0x80080c80, 0x04001004, 0x02020800,
+	0x001005d8, 0x80001040, 0x480a5c06, 0x800811c0,
+	0x04020004, 0x0201f800, 0x00108d88, 0x0401f06b,
+	0x0201f800, 0x0010912a, 0x591c0817, 0x591c0018,
+	0x48065808, 0x48025809, 0x59300007, 0x8c000500,
+	0x02020800, 0x00100e99, 0x497a3808, 0x0201f800,
+	0x000201ba, 0x0402004a, 0x411e6000, 0x0401fc3e,
+	0x0401f05a, 0x0401fc6d, 0x04000013, 0x49366009,
+	0x4a026406, 0x00000003, 0x492e6008, 0x591c0817,
+	0x591c1018, 0x48066017, 0x480a6018, 0x4d380000,
+	0x591e7403, 0x4d300000, 0x411e6000, 0x0401fc2e,
+	0x5c026000, 0x0201f800, 0x000207a1, 0x5c027000,
+	0x0401f046, 0x59a80039, 0x48023a05, 0x0401f043,
+	0x59cc0407, 0x82000580, 0x0000000b, 0x04020025,
+	0x59340a00, 0x84040d0e, 0x48066a00, 0x592c0a04,
+	0x82040d00, 0x000000ff, 0x82040d80, 0x00000014,
+	0x04000003, 0x4a02621d, 0x00000003, 0x59300007,
+	0x8c000500, 0x02020800, 0x00100e99, 0x4d400000,
+	0x42028000, 0x00000003, 0x592c0a08, 0x0201f800,
+	0x00104e70, 0x0201f800, 0x000202da, 0x5c028000,
+	0x497a6008, 0x4a026403, 0x00000085, 0x4a026203,
+	0x00000009, 0x4a026406, 0x00000002, 0x42000800,
+	0x8000404b, 0x0201f800, 0x00020721, 0x0401f01b,
+	0x59cc0207, 0x82000580, 0x00002a00, 0x04020004,
+	0x59a80039, 0x48023a05, 0x0401f014, 0x812e59c0,
+	0x02000800, 0x001005d8, 0x4a025a04, 0x00000103,
+	0x591c0007, 0x8c000500, 0x02020800, 0x00100e99,
+	0x591c0402, 0x48025c06, 0x4a025a06, 0x00000003,
+	0x0201f800, 0x000202c1, 0x0201f800, 0x00107911,
+	0x0201f800, 0x001049b2, 0x5c026000, 0x0201f800,
+	0x0002077d, 0x0401f002, 0x5c026000, 0x5c025800,
+	0x1c01f000, 0x0401f819, 0x0401f7fd, 0x4933c857,
+	0x83380580, 0x00000015, 0x04020004, 0x59a80039,
+	0x48023a05, 0x0401f00d, 0x83380580, 0x00000016,
+	0x0402000d, 0x4d300000, 0x411e6000, 0x0201f800,
+	0x0010a5df, 0x0201f800, 0x000206fd, 0x0201f800,
+	0x0002077d, 0x5c026000, 0x497a381c, 0x0201f800,
+	0x0002077d, 0x1c01f000, 0x591c0414, 0x84000540,
+	0x48023c14, 0x59cc100b, 0x4933c857, 0x491fc857,
+	0x492fc857, 0x4803c857, 0x480bc857, 0x8c08153c,
+	0x04000006, 0x59a80039, 0x48023a05, 0x497a381c,
+	0x0201f000, 0x0002077d, 0x4d300000, 0x411e6000,
+	0x0201f800, 0x00108bd7, 0x5c026000, 0x591c0406,
+	0x82000580, 0x00000000, 0x02000000, 0x0002077d,
+	0x591c0403, 0x82000580, 0x00000050, 0x0402000d,
+	0x4d300000, 0x411e6000, 0x4a026203, 0x00000001,
+	0x42000800, 0x80000043, 0x0201f800, 0x00020721,
+	0x5c026000, 0x497a381c, 0x0201f000, 0x0002077d,
+	0x591c0203, 0x82000580, 0x0000000d, 0x04000014,
+	0x812e59c0, 0x02000800, 0x001005d8, 0x591c0203,
+	0x82000580, 0x00000004, 0x04020011, 0x592c020a,
+	0x8c000502, 0x0400000e, 0x4a023812, 0x0fffffff,
+	0x592c0208, 0x8400051e, 0x48025a08, 0x42000000,
+	0x00000001, 0x48023a14, 0x0401f021, 0x42000000,
+	0x00000007, 0x48023a14, 0x0401f01d, 0x592c020a,
+	0x4803c857, 0x8c000500, 0x0402000b, 0x8c000502,
+	0x040007f7, 0x591c0414, 0x8c00051c, 0x040207eb,
+	0x591c0011, 0x4803c857, 0x800001c0, 0x040007f0,
+	0x0401f7e6, 0x8c08153a, 0x040207ed, 0x59cc000a,
+	0x592c180f, 0x4803c857, 0x480fc857, 0x800c0580,
+	0x040007e7, 0x59cc000a, 0x4803c857, 0x48023816,
+	0x42000000, 0x00000005, 0x48023a14, 0x0201f000,
+	0x00109259, 0x4933c857, 0x4d1c0000, 0x59cc0001,
+	0x59341002, 0x80080580, 0x82000500, 0x00ffffff,
+	0x04020041, 0x59301419, 0x0201f800, 0x00109410,
+	0x02000800, 0x001005d8, 0x591c1406, 0x82080580,
+	0x00000007, 0x04000038, 0x82080580, 0x00000002,
+	0x04000035, 0x82080580, 0x00000000, 0x04000032,
+	0x591c0202, 0x82000d80, 0x0000ffff, 0x04000004,
+	0x59301a19, 0x800c0580, 0x0402002b, 0x83380580,
+	0x00000015, 0x04000026, 0x4d300000, 0x4d2c0000,
+	0x411e6000, 0x59325808, 0x0201f800, 0x00109037,
+	0x02000800, 0x001005d8, 0x592c0204, 0x82000500,
+	0x000000ff, 0x82000580, 0x00000014, 0x04000003,
+	0x4a02621d, 0x00000003, 0x42028000, 0x00000003,
+	0x592c0a08, 0x0201f800, 0x00104e70, 0x0201f800,
+	0x000202da, 0x5c025800, 0x497a6008, 0x4a026403,
+	0x00000085, 0x4a026203, 0x00000009, 0x4a026406,
+	0x00000002, 0x42000800, 0x8000404b, 0x0201f800,
+	0x00020721, 0x5c026000, 0x0401f003, 0x59a80039,
+	0x48023a05, 0x497a381c, 0x0201f800, 0x0002077d,
+	0x5c023800, 0x1c01f000, 0x4933c857, 0x4c580000,
+	0x4d2c0000, 0x59325808, 0x83383580, 0x00000015,
+	0x04000010, 0x59342200, 0x84102502, 0x48126a00,
+	0x0201f800, 0x00109037, 0x04000066, 0x0201f800,
+	0x00109597, 0x04020005, 0x4200b000, 0x00000002,
+	0x0201f800, 0x0010957d, 0x0401fa0a, 0x0401f079,
+	0x83cc1400, 0x00000008, 0x4200b000, 0x00000002,
+	0x83341c00, 0x00000006, 0x0201f800, 0x0010855a,
+	0x04020015, 0x83cc1400, 0x0000000a, 0x4200b000,
+	0x00000002, 0x83341c00, 0x00000008, 0x0201f800,
+	0x0010855a, 0x0402000c, 0x0201f800, 0x00102074,
+	0x59342200, 0x59cc1007, 0x800811c0, 0x04000003,
+	0x480a6801, 0x84102542, 0x8410251a, 0x48126a00,
+	0x0401f05f, 0x4d3c0000, 0x417a7800, 0x0201f800,
+	0x0010203c, 0x5c027800, 0x42000000, 0x0010b864,
+	0x0201f800, 0x0010aa47, 0x59340200, 0x84000558,
+	0x48026a00, 0x4d300000, 0x0201f800, 0x0002075a,
+	0x02000800, 0x001005d8, 0x49366009, 0x497a6008,
+	0x4a026406, 0x00000001, 0x4a026403, 0x00000001,
+	0x42003000, 0x00000003, 0x0201f800, 0x0010a942,
+	0x0201f800, 0x00103b25, 0x04000011, 0x41782800,
+	0x42003000, 0x00000001, 0x4d400000, 0x42028000,
+	0x00000029, 0x0201f800, 0x0010a43e, 0x5c028000,
+	0x4a026406, 0x00000004, 0x4a026203, 0x00000007,
+	0x4a026420, 0x00000001, 0x0401f009, 0x4a026203,
+	0x00000001, 0x42000800, 0x0000000b, 0x0201f800,
+	0x00104571, 0x0201f800, 0x0010672b, 0x5c026000,
+	0x0201f800, 0x00109037, 0x04000022, 0x0201f800,
+	0x00109597, 0x04020022, 0x0401f9ae, 0x0401f01d,
+	0x4d3c0000, 0x417a7800, 0x0201f800, 0x0010203c,
+	0x42000000, 0x0010b864, 0x0201f800, 0x0010aa47,
+	0x59340200, 0x84000558, 0x48026a00, 0x42003000,
+	0x00000003, 0x41782800, 0x42002000, 0x00000005,
+	0x4d400000, 0x4d440000, 0x59368c03, 0x42028000,
+	0x00000029, 0x0201f800, 0x0010985e, 0x5c028800,
+	0x5c028000, 0x5c027800, 0x0201f800, 0x00102074,
+	0x0201f800, 0x0002077d, 0x0401f002, 0x0401fca9,
+	0x5c025800, 0x5c00b000, 0x1c01f000, 0x4933c857,
+	0x41380000, 0x83383480, 0x00000056, 0x02021800,
+	0x001005d8, 0x0c01f001, 0x00107ef7, 0x00107ef2,
+	0x00107ef7, 0x00107ef7, 0x00107ef7, 0x00107ef7,
+	0x00107ef0, 0x00107ef0, 0x00107ef0, 0x00107ef0,
+	0x00107ef0, 0x00107ef0, 0x00107ef0, 0x00107ef0,
+	0x00107ef0, 0x00107ef0, 0x00107ef0, 0x00107ef0,
+	0x00107ef0, 0x00107ef0, 0x00107ef0, 0x00107ef0,
+	0x00107ef0, 0x00107ef0, 0x00107ef0, 0x00107ef0,
+	0x00107ef0, 0x00107ef0, 0x00107ef0, 0x00107ef0,
+	0x00107ef0, 0x00107ef7, 0x00107ef0, 0x00107ef7,
+	0x00107ef7, 0x00107ef0, 0x00107ef0, 0x00107ef0,
+	0x00107ef0, 0x00107ef0, 0x00107ef7, 0x00107ef0,
+	0x00107ef0, 0x00107ef0, 0x00107ef0, 0x00107ef0,
+	0x00107ef0, 0x00107ef0, 0x00107ef0, 0x00107ef0,
+	0x00107ef7, 0x00107ef7, 0x00107ef0, 0x00107ef0,
+	0x00107ef0, 0x00107ef0, 0x00107ef0, 0x00107ef0,
+	0x00107ef0, 0x00107ef0, 0x00107ef0, 0x00107ef7,
+	0x00107ef0, 0x00107ef0, 0x00107ef7, 0x00107ef7,
+	0x00107ef0, 0x00107ef7, 0x00107ef7, 0x00107ef0,
+	0x00107ef0, 0x00107ef0, 0x00107ef0, 0x00107ef7,
+	0x00107ef0, 0x00107ef0, 0x00107ef0, 0x00107ef7,
+	0x00107ef0, 0x00107ef0, 0x00107ef0, 0x00107ef7,
+	0x00107ef0, 0x00107ef0, 0x00107ef0, 0x00107ef7,
+	0x0201f800, 0x001005d8, 0x4a026203, 0x00000001,
+	0x493a6403, 0x0201f000, 0x0010672b, 0x4933c857,
+	0x4a026203, 0x00000001, 0x493a6403, 0x0201f000,
+	0x0010672b, 0x4933c857, 0x59300403, 0x82003480,
+	0x00000056, 0x02021800, 0x001005d8, 0x83383580,
+	0x00000013, 0x04000093, 0x83383580, 0x00000027,
+	0x0402004b, 0x0201f800, 0x00106bbf, 0x0201f800,
+	0x00109134, 0x0400000b, 0x0201f800, 0x0010914e,
+	0x04000041, 0x59300403, 0x82000d80, 0x00000022,
+	0x04020038, 0x0401fc61, 0x0400003a, 0x0401f03a,
+	0x0201f800, 0x00102074, 0x42000800, 0x00000007,
+	0x0201f800, 0x00104571, 0x0401f8fe, 0x4d440000,
+	0x59368c03, 0x83440580, 0x000007fe, 0x04020008,
+	0x59a81026, 0x84081540, 0x0201f800, 0x0010513b,
+	0x04020002, 0x8408154a, 0x480b5026, 0x42028000,
+	0x00000029, 0x4d3c0000, 0x417a7800, 0x0201f800,
+	0x0010203c, 0x5c027800, 0x836c0580, 0x00000003,
+	0x0400000c, 0x59326809, 0x59340008, 0x800001c0,
+	0x04020008, 0x59368c03, 0x4933c857, 0x4937c857,
+	0x4947c857, 0x0201f800, 0x001045fb, 0x0401f00c,
+	0x42000000, 0x0010b864, 0x0201f800, 0x0010aa47,
+	0x42003000, 0x00000015, 0x41782800, 0x42002000,
+	0x00000003, 0x0201f800, 0x0010985e, 0x5c028800,
+	0x0201f800, 0x00109326, 0x0201f000, 0x0002077d,
+	0x1c01f000, 0x0401f8cb, 0x0401f7fa, 0x83380580,
+	0x00000014, 0x0400000b, 0x0201f800, 0x00106f60,
+	0x02020000, 0x00107974, 0x59300203, 0x82000580,
+	0x00000002, 0x040000ed, 0x0201f800, 0x001005d8,
+	0x0201f800, 0x00106bbf, 0x4d3c0000, 0x417a7800,
+	0x0201f800, 0x0010203c, 0x5c027800, 0x42003000,
+	0x00000016, 0x41782800, 0x4d400000, 0x4d440000,
+	0x59368c03, 0x42002000, 0x00000009, 0x42028000,
+	0x00000029, 0x0201f800, 0x0010985e, 0x5c028800,
+	0x5c028000, 0x42000000, 0x0010b864, 0x0201f800,
+	0x0010aa47, 0x0201f800, 0x00109134, 0x0402000c,
+	0x0201f800, 0x00102074, 0x0401f89e, 0x59340c03,
+	0x82040580, 0x000007fe, 0x040207ca, 0x59a80826,
+	0x84040d40, 0x48075026, 0x0401f7c6, 0x0201f800,
+	0x0010914e, 0x04020003, 0x0401f892, 0x0401f7c1,
+	0x59300403, 0x82000d80, 0x00000032, 0x04020004,
+	0x0201f800, 0x0010230c, 0x0401f7ba, 0x59300403,
+	0x82000d80, 0x00000022, 0x04000886, 0x0401f7b5,
+	0x4803c857, 0x0c01f001, 0x00108016, 0x00108016,
+	0x00108016, 0x00108016, 0x00108016, 0x00108016,
+	0x00107ff0, 0x00107ff0, 0x00107ff0, 0x00107ff0,
+	0x00107ff0, 0x00107ff0, 0x00107ff0, 0x00107ff0,
+	0x00107ff0, 0x00107ff0, 0x00107ff0, 0x00107ff0,
+	0x00107ff0, 0x00107ff0, 0x00107ff0, 0x00107ff0,
+	0x00107ff0, 0x00107ff0, 0x00107ff0, 0x00107ff0,
+	0x00107ff0, 0x00107ff0, 0x00107ff0, 0x00107ff0,
+	0x00107ff9, 0x00108016, 0x00107ff0, 0x00108016,
+	0x00108016, 0x00107ff0, 0x00107ff0, 0x00107ff0,
+	0x00107ff0, 0x00107ff0, 0x00108016, 0x00108016,
+	0x00107ff0, 0x00107ff0, 0x00107ff0, 0x00107ff0,
+	0x00107ff0, 0x00107ff0, 0x00107ff0, 0x00107ff0,
+	0x00108007, 0x00108016, 0x00107ff0, 0x00108000,
+	0x00107ff0, 0x00107ff0, 0x00107ff0, 0x00108000,
+	0x00107ff0, 0x00107ff0, 0x00107ff0, 0x00108016,
+	0x00108003, 0x00107ff0, 0x00107ff2, 0x00108016,
+	0x00107ff0, 0x00108016, 0x00108016, 0x00107ff0,
+	0x00107ff0, 0x00107ff0, 0x00107ff0, 0x00108016,
+	0x00107ff0, 0x00107ff0, 0x00107ff0, 0x00108016,
+	0x00107ff0, 0x00107ff0, 0x00107ff0, 0x00108016,
+	0x00107ff0, 0x00107ff0, 0x00107ff0, 0x00108016,
+	0x0201f800, 0x001005d8, 0x4d2c0000, 0x59325808,
+	0x0201f800, 0x000202da, 0x5c025800, 0x0201f000,
+	0x0002077d, 0x4a026203, 0x00000005, 0x59a80039,
+	0x48026205, 0x59a80037, 0x48026206, 0x1c01f000,
+	0x5930081e, 0x49780a05, 0x0401f014, 0x0201f800,
+	0x00109326, 0x0201f000, 0x0002077d, 0x0201f800,
+	0x0010230c, 0x0201f800, 0x00106c55, 0x04000005,
+	0x0201f800, 0x00106bbf, 0x0201f000, 0x0002077d,
+	0x0201f800, 0x00106bbf, 0x0201f800, 0x0002077d,
+	0x0201f000, 0x00106c4b, 0x4933c857, 0x4a026203,
+	0x00000002, 0x59a80037, 0x48026206, 0x1c01f000,
+	0x4933c857, 0x0201f800, 0x00109037, 0x0400002a,
+	0x4d2c0000, 0x0201f800, 0x00109597, 0x0402000a,
+	0x4d400000, 0x42028000, 0x00000031, 0x42000800,
+	0x00000004, 0x0201f800, 0x0010943b, 0x5c028000,
+	0x0401f01c, 0x59300c06, 0x82040580, 0x00000010,
+	0x04000004, 0x82040580, 0x00000011, 0x0402000a,
+	0x4a025a06, 0x00000031, 0x4a02580d, 0x00000004,
+	0x4a02580e, 0x000000ff, 0x0201f800, 0x000202da,
+	0x0401f00c, 0x592c0404, 0x8c00051e, 0x04000009,
+	0x4a025a04, 0x00000103, 0x4a025805, 0x01000000,
+	0x5931d821, 0x58ef400b, 0x58ec0009, 0x0801f800,
+	0x5c025800, 0x1c01f000, 0x4933c857, 0x59340400,
+	0x82000500, 0x000000ff, 0x82003480, 0x0000000c,
+	0x02021800, 0x001005d8, 0x59303403, 0x82180d80,
+	0x0000004d, 0x02000000, 0x0010938b, 0x82180d80,
+	0x00000033, 0x02000000, 0x00109349, 0x82180d80,
+	0x00000028, 0x02000000, 0x0010918f, 0x82180d80,
+	0x00000029, 0x02000000, 0x001091a3, 0x82180d80,
+	0x0000001f, 0x02000000, 0x00107b28, 0x82180d80,
+	0x00000055, 0x02000000, 0x00107b01, 0x82180d80,
+	0x00000000, 0x04000591, 0x82180d80, 0x00000022,
+	0x02000000, 0x00107b55, 0x82180d80, 0x00000035,
+	0x02000000, 0x00107c50, 0x82180d80, 0x00000039,
+	0x04000539, 0x82180d80, 0x0000003d, 0x02000000,
+	0x00107b85, 0x82180d80, 0x00000044, 0x02000000,
+	0x00107bc2, 0x82180d80, 0x00000049, 0x02000000,
+	0x00107c17, 0x82180d80, 0x00000041, 0x02000000,
+	0x00107c03, 0x82180d80, 0x00000043, 0x02000000,
+	0x001094dc, 0x82180d80, 0x00000051, 0x02000000,
+	0x00109542, 0x82180d80, 0x00000004, 0x04020003,
+	0x42000000, 0x00000001, 0x83380d80, 0x00000015,
+	0x04000006, 0x83380d80, 0x00000016, 0x02020000,
+	0x00107974, 0x0401f20f, 0x4d2c0000, 0x4d3c0000,
+	0x0c01f804, 0x5c027800, 0x5c025800, 0x1c01f000,
+	0x001080b8, 0x001080bc, 0x001080b8, 0x00108131,
+	0x001080b8, 0x00108226, 0x001082bf, 0x001080b8,
+	0x001080b8, 0x00108288, 0x001080b8, 0x0010829a,
+	0x4933c857, 0x497a6007, 0x59300808, 0x58040000,
+	0x4a000a04, 0x00000103, 0x0201f000, 0x0002077d,
+	0x4933c857, 0x40000000, 0x40000000, 0x1c01f000,
+	0x4933c857, 0x59a80016, 0x82000580, 0x00000074,
+	0x0402005c, 0x0201f800, 0x0010a2c8, 0x04020016,
+	0x0401f85c, 0x0201f800, 0x00109037, 0x0400000c,
+	0x0201f800, 0x00109597, 0x04020009, 0x41780800,
+	0x4d400000, 0x42028000, 0x00000000, 0x0201f800,
+	0x0010943b, 0x5c028000, 0x0401f003, 0x0201f800,
+	0x00102074, 0x0201f800, 0x001048c1, 0x0201f000,
+	0x0002077d, 0x0201f800, 0x00109037, 0x04000007,
+	0x0201f800, 0x00109597, 0x04020004, 0x0401ff3d,
+	0x0201f000, 0x0002077d, 0x417a7800, 0x0201f800,
+	0x0010203c, 0x42000000, 0x0010b864, 0x0201f800,
+	0x0010aa47, 0x59340200, 0x84000558, 0x48026a00,
+	0x42003000, 0x00000003, 0x0201f800, 0x0010a942,
+	0x4d300000, 0x0201f800, 0x0002075a, 0x02000800,
+	0x001005d8, 0x49366009, 0x497a6008, 0x4a026406,
+	0x00000001, 0x4a026403, 0x00000001, 0x0201f800,
+	0x00103b25, 0x04000011, 0x4a026406, 0x00000004,
+	0x4a026203, 0x00000007, 0x4a026420, 0x00000001,
+	0x42003000, 0x00000001, 0x4d400000, 0x42028000,
+	0x00000029, 0x41782800, 0x0201f800, 0x0010a43e,
+	0x5c028000, 0x0401f009, 0x42000800, 0x0000000b,
+	0x0201f800, 0x00104571, 0x4a026203, 0x00000001,
+	0x0201f800, 0x0010672b, 0x5c026000, 0x0401ff05,
+	0x0201f800, 0x00102074, 0x0201f000, 0x0002077d,
+	0x0401ff00, 0x42000000, 0x00000001, 0x0401f0c7,
+	0x4933c857, 0x59340200, 0x8c000500, 0x0400000d,
+	0x4d3c0000, 0x417a7800, 0x0201f800, 0x00104567,
+	0x5c027800, 0x0201f800, 0x00103b25, 0x04000005,
+	0x42000800, 0x00000006, 0x0201f800, 0x00104571,
+	0x1c01f000, 0x4933c857, 0x59a80816, 0x82040580,
+	0x00000074, 0x0400000e, 0x4807c857, 0x82040580,
+	0x00000100, 0x040200a0, 0x59cc0408, 0x4803c857,
+	0x8c000500, 0x0400009c, 0x59341403, 0x82080580,
+	0x000007fe, 0x04000006, 0x0401f097, 0x59341403,
+	0x82080580, 0x000007fe, 0x04020003, 0x0401fa9c,
+	0x0401f04c, 0x0201f800, 0x0010462a, 0x59341403,
+	0x82080580, 0x000007fc, 0x0402001f, 0x4a026802,
+	0x00fffffc, 0x0201f800, 0x00109037, 0x04000012,
+	0x0201f800, 0x00109597, 0x0402000f, 0x0401f8a9,
+	0x41780800, 0x4d400000, 0x42028000, 0x00000000,
+	0x0201f800, 0x0010943b, 0x5c028000, 0x42000800,
+	0x00000004, 0x0201f800, 0x00104571, 0x0201f000,
+	0x0002077d, 0x42000800, 0x00000004, 0x0201f800,
+	0x00104571, 0x0201f800, 0x00102074, 0x0201f000,
+	0x0002077d, 0x59a80005, 0x8c000514, 0x04000011,
+	0x0201f800, 0x0010513b, 0x42001000, 0x00000010,
+	0x04020009, 0x59340002, 0x82000500, 0x00ff0000,
+	0x82000580, 0x00ff0000, 0x04000006, 0x42001000,
+	0x00000008, 0x0201f800, 0x00104c6d, 0x0402005a,
+	0x0201f800, 0x00109037, 0x0400005b, 0x0201f800,
+	0x00109597, 0x04020005, 0x592c0404, 0x8c00051c,
+	0x040207c9, 0x0401f877, 0x42000800, 0x00000005,
+	0x0201f800, 0x00104571, 0x4a026203, 0x00000001,
+	0x4a026403, 0x00000003, 0x0201f000, 0x0010672b,
+	0x59cc0408, 0x8c000518, 0x04000010, 0x0201f800,
+	0x001092e5, 0x0201f800, 0x0010513b, 0x04000004,
+	0x59cc0408, 0x8c000516, 0x040207b3, 0x59a80026,
+	0x8400054a, 0x48035026, 0x59a80010, 0x84000570,
+	0x48038832, 0x0401f7ac, 0x42001000, 0x000000ef,
+	0x480b5010, 0x497b8830, 0x84081570, 0x480b8832,
+	0x59c40802, 0x84040d4c, 0x48078802, 0x0201f800,
+	0x0010930f, 0x59a80026, 0x84000548, 0x48035026,
+	0x0201f800, 0x0010a3da, 0x0402079b, 0x59a80026,
+	0x8400054c, 0x48035026, 0x42000800, 0x00000006,
+	0x0201f800, 0x00104571, 0x417a7800, 0x0201f800,
+	0x00104567, 0x42000000, 0x000000e8, 0x0201f800,
+	0x00105c9a, 0x02000800, 0x001045a6, 0x02020800,
+	0x001005d8, 0x49366009, 0x59340200, 0x8400051a,
+	0x48026a00, 0x42000800, 0x00000003, 0x0201f800,
+	0x00104571, 0x4a026406, 0x00000001, 0x4a026203,
+	0x00000001, 0x4a026403, 0x00000002, 0x0201f000,
+	0x0010672b, 0x0401fe43, 0x42000000, 0x00000001,
+	0x0401f00a, 0x599c0017, 0x8c00050a, 0x040007ab,
+	0x42000800, 0x00000004, 0x0201f800, 0x00104571,
+	0x0201f000, 0x0002077d, 0x4933c857, 0x80003540,
+	0x04000005, 0x42000800, 0x00000007, 0x0201f800,
+	0x00104571, 0x801831c0, 0x0402000e, 0x59302008,
+	0x801021c0, 0x04000004, 0x58100404, 0x8c00051e,
+	0x04020008, 0x59341c03, 0x42002000, 0x00000004,
+	0x42003000, 0x00000012, 0x0201f800, 0x00103aae,
+	0x0201f800, 0x00102074, 0x0201f000, 0x0002077d,
+	0x4c5c0000, 0x4d2c0000, 0x59325808, 0x0201f800,
+	0x00105755, 0x5c025800, 0x59cc0008, 0x48002805,
+	0x59cc0009, 0x48002806, 0x49782807, 0x49782808,
+	0x49782809, 0x4978280a, 0x59cc0013, 0x8c00053e,
+	0x04000009, 0x59cc0414, 0x900001c0, 0x59ccbc15,
+	0x805c0540, 0x48002807, 0x59cc0416, 0x900001c0,
+	0x48002808, 0x59cc0017, 0x8c00053e, 0x04000009,
+	0x59cc0418, 0x900001c0, 0x59ccbc19, 0x805c0540,
+	0x48002809, 0x59cc041a, 0x900001c0, 0x4800280a,
+	0x5c00b800, 0x1c01f000, 0x4933c857, 0x59a80016,
+	0x82000580, 0x00000014, 0x04020048, 0x59a80005,
+	0x8c000514, 0x04000015, 0x0201f800, 0x0010513b,
+	0x42001000, 0x00000010, 0x04020009, 0x59340002,
+	0x82000500, 0x00ff0000, 0x82000580, 0x00ff0000,
+	0x0400000a, 0x42001000, 0x00000008, 0x0201f800,
+	0x00104c6d, 0x04000005, 0x59a80005, 0x84000556,
+	0x48035005, 0x0401f031, 0x836c0580, 0x00000003,
+	0x0402000b, 0x59300008, 0x80000540, 0x04020008,
+	0x59341c03, 0x42002000, 0x00000006, 0x42003000,
+	0x00000013, 0x0201f800, 0x00103aae, 0x0201f800,
+	0x0010468d, 0x0401fecf, 0x0401fa1d, 0x0402001f,
+	0x59340404, 0x80000540, 0x0400001c, 0x42000800,
+	0x00000006, 0x0201f800, 0x00104571, 0x0201f800,
+	0x00109037, 0x04000011, 0x0201f800, 0x00109597,
+	0x0402000a, 0x41780800, 0x4d400000, 0x42028000,
+	0x00000000, 0x0201f800, 0x0010943b, 0x5c028000,
+	0x0201f000, 0x0002077d, 0x4a025a04, 0x00000103,
+	0x4a025805, 0x02000000, 0x0201f800, 0x00102074,
+	0x0201f000, 0x0002077d, 0x0201f800, 0x00104c19,
+	0x0201f800, 0x00109037, 0x04000007, 0x0201f800,
+	0x00109597, 0x04020004, 0x0401fda2, 0x0201f000,
+	0x0002077d, 0x0401fd9f, 0x80000580, 0x59a80005,
+	0x8c000516, 0x04000005, 0x84000516, 0x48035005,
+	0x82000540, 0x00000001, 0x0401ff60, 0x1c01f000,
+	0x4933c857, 0x59a80016, 0x82000580, 0x00000014,
+	0x0402000b, 0x42000800, 0x0000000b, 0x0201f800,
+	0x00104571, 0x4a026203, 0x00000001, 0x4a026403,
+	0x00000001, 0x0201f000, 0x0010672b, 0x42000000,
+	0x00000001, 0x0401f74d, 0x4933c857, 0x40003000,
+	0x59a80016, 0x82000580, 0x00000004, 0x0402000a,
+	0x82183580, 0x0000000b, 0x04020005, 0x42000800,
+	0x00000007, 0x0201f800, 0x00104571, 0x0201f000,
+	0x0002077d, 0x42000000, 0x00000001, 0x0401f73b,
+	0x4803c857, 0x4d2c0000, 0x4d3c0000, 0x0c01f804,
+	0x5c027800, 0x5c025800, 0x1c01f000, 0x001080b8,
+	0x001082ce, 0x001080b8, 0x00108323, 0x001080b8,
+	0x00108391, 0x001082bf, 0x001080b8, 0x001080b8,
+	0x001083b1, 0x001080b8, 0x001083c1, 0x4933c857,
+	0x4d1c0000, 0x59301403, 0x82080580, 0x00000003,
+	0x04000008, 0x82081580, 0x0000001e, 0x04020003,
+	0x0201f800, 0x0002077d, 0x5c023800, 0x1c01f000,
+	0x0401ff5a, 0x0401f7fd, 0x4933c857, 0x0201f800,
+	0x00109037, 0x0400000b, 0x0201f800, 0x00109597,
+	0x04020008, 0x4200b000, 0x00000002, 0x0201f800,
+	0x0010957d, 0x0401fd43, 0x0201f000, 0x0002077d,
+	0x0401f8f5, 0x04020030, 0x417a7800, 0x0201f800,
+	0x00104567, 0x417a7800, 0x0201f800, 0x0010203c,
+	0x42000000, 0x0010b864, 0x0201f800, 0x0010aa47,
+	0x59340200, 0x84000558, 0x48026a00, 0x4a026403,
+	0x00000002, 0x42003000, 0x00000003, 0x0201f800,
+	0x0010a942, 0x0201f800, 0x00103b25, 0x04000011,
+	0x4d400000, 0x41782800, 0x42003000, 0x00000005,
+	0x42028000, 0x00000029, 0x0201f800, 0x0010a43e,
+	0x5c028000, 0x4a026203, 0x00000007, 0x4a026406,
+	0x00000004, 0x4a026420, 0x00000001, 0x1c01f000,
+	0x42000800, 0x00000003, 0x0201f800, 0x00104571,
+	0x4a026203, 0x00000001, 0x0201f800, 0x0010672b,
+	0x0401f7f7, 0x59cc0407, 0x82000580, 0x00000009,
+	0x0402000a, 0x59340412, 0x82000500, 0x000000ff,
+	0x0400000c, 0x80000040, 0x48026c12, 0x4a026206,
+	0x0000000a, 0x0401f7ea, 0x59cc0207, 0x82000500,
+	0x0000ff00, 0x82000580, 0x00001900, 0x040007c2,
+	0x0401fcfc, 0x80000580, 0x0401f6c4, 0x4933c857,
+	0x59a80032, 0x80000540, 0x04000015, 0x59340403,
+	0x82000580, 0x000007fe, 0x04020011, 0x59a80010,
+	0x80000000, 0x48035010, 0x417a7800, 0x0201f800,
+	0x00104567, 0x42000800, 0x00000003, 0x0201f800,
+	0x00104571, 0x4a026203, 0x00000001, 0x4a026403,
+	0x00000002, 0x0201f000, 0x0010672b, 0x0201f800,
+	0x00109037, 0x04000011, 0x0201f800, 0x00109597,
+	0x0402000e, 0x4c580000, 0x4200b000, 0x00000002,
+	0x0201f800, 0x0010957d, 0x5c00b000, 0x0401fcd5,
+	0x42000800, 0x00000007, 0x0201f800, 0x00104571,
+	0x0201f000, 0x0002077d, 0x0401fcce, 0x59cc3407,
+	0x82183500, 0x000000ff, 0x82180580, 0x00000005,
+	0x0400001c, 0x82180580, 0x0000000b, 0x04000016,
+	0x59cc0207, 0x82000500, 0x0000ff00, 0x04020004,
+	0x82180580, 0x00000009, 0x04000012, 0x82000580,
+	0x00001900, 0x0402000c, 0x82180580, 0x00000009,
+	0x0400000c, 0x42000800, 0x00000004, 0x0201f800,
+	0x00104571, 0x0201f800, 0x00102074, 0x0201f000,
+	0x0002077d, 0x42000000, 0x00000001, 0x0401f677,
+	0x0201f800, 0x00109037, 0x59325808, 0x04000008,
+	0x592c0204, 0x82000580, 0x00000139, 0x040007f6,
+	0x592c0404, 0x8c00051e, 0x040207f3, 0x59340403,
+	0x82000580, 0x000007fe, 0x04020007, 0x59a80026,
+	0x84000540, 0x48035026, 0x0201f800, 0x00104229,
+	0x0401f7e9, 0x417a7800, 0x0201f800, 0x0010203c,
+	0x42003000, 0x00000005, 0x0201f800, 0x0010a942,
+	0x42000000, 0x0010b864, 0x0201f800, 0x0010aa47,
+	0x0401f7dd, 0x4933c857, 0x0401f84d, 0x0402000b,
+	0x42000800, 0x00000005, 0x0201f800, 0x00104571,
+	0x4a026203, 0x00000001, 0x4a026403, 0x00000003,
+	0x0201f000, 0x0010672b, 0x42000800, 0x00000004,
+	0x0201f800, 0x00104571, 0x0201f800, 0x00109597,
+	0x0402000a, 0x4c580000, 0x4200b000, 0x00000002,
+	0x0201f800, 0x0010957d, 0x5c00b000, 0x0401fc71,
+	0x0201f000, 0x0002077d, 0x0401fc6e, 0x80000580,
+	0x0401f636, 0x4933c857, 0x0401f82d, 0x0402000b,
+	0x42000800, 0x00000009, 0x0201f800, 0x00104571,
+	0x4a026203, 0x00000001, 0x4a026403, 0x00000005,
+	0x0201f000, 0x0010672b, 0x42000000, 0x00000001,
+	0x0401f626, 0x4933c857, 0x0401f81d, 0x0402000b,
+	0x42000800, 0x0000000b, 0x0201f800, 0x00104571,
+	0x4a026203, 0x00000001, 0x4a026403, 0x00000001,
+	0x0201f000, 0x0010672b, 0x42000000, 0x00000001,
+	0x0401f616, 0x4933c857, 0x59cc0407, 0x82000580,
+	0x00000003, 0x04020009, 0x59cc0207, 0x82000500,
+	0x0000ff00, 0x82000d80, 0x00002a00, 0x04000003,
+	0x82000d80, 0x00001e00, 0x1c01f000, 0x4933c857,
+	0x82000540, 0x00000001, 0x1c01f000, 0x4933c857,
+	0x4d400000, 0x4c580000, 0x59a80026, 0x82000540,
+	0x00000003, 0x48035026, 0x0401f85c, 0x04000038,
+	0x4d340000, 0x4d440000, 0x59a80026, 0x84000552,
+	0x48035026, 0x0201f800, 0x00103b25, 0x0400000c,
+	0x42028000, 0x0000002a, 0x42028800, 0x0000ffff,
+	0x42003000, 0x00000002, 0x0201f800, 0x0010a446,
+	0x59a80805, 0x84040d44, 0x48075005, 0x42028000,
+	0x0000002a, 0x4d3c0000, 0x42027800, 0x00000204,
+	0x0201f800, 0x00101fe5, 0x5c027800, 0x42000000,
+	0x0010b864, 0x0201f800, 0x0010aa47, 0x0201f800,
+	0x00101e45, 0x4200b000, 0x00000010, 0x42028800,
+	0x000007f0, 0x4d2c0000, 0x83440580, 0x000007fe,
+	0x04000003, 0x0201f800, 0x001045fb, 0x81468800,
+	0x8058b040, 0x040207f9, 0x5c025800, 0x59cc0408,
+	0x8c00051e, 0x04000004, 0x59a80026, 0x84000512,
+	0x48035026, 0x5c028800, 0x5c026800, 0x0201f800,
+	0x0010462a, 0x4a026802, 0x00fffffe, 0x59a80826,
+	0x84040d50, 0x59cc0013, 0x8c00053e, 0x04000003,
+	0x8c000536, 0x04000004, 0x59cc0017, 0x8c000536,
+	0x04020002, 0x84040d10, 0x48075026, 0x59cc0800,
+	0x82040d00, 0x00ffffff, 0x48075010, 0x80040110,
+	0x4803501d, 0x48038881, 0x0201f800, 0x0010513b,
+	0x04000007, 0x59cc0009, 0x48035035, 0x59cc000a,
+	0x48035036, 0x0201f800, 0x001092e5, 0x5c00b000,
+	0x5c028000, 0x1c01f000, 0x4933c857, 0x4c580000,
+	0x59a80010, 0x82000500, 0x00ffff00, 0x04000022,
+	0x59cc1000, 0x82081500, 0x00ffff00, 0x80080580,
+	0x04000004, 0x42000000, 0x0010b83b, 0x0401f016,
+	0x83cc1400, 0x0000000b, 0x4200b000, 0x00000002,
+	0x83341c00, 0x00000006, 0x0401f900, 0x04000004,
+	0x42000000, 0x0010b83c, 0x0401f00b, 0x83cc1400,
+	0x0000000d, 0x4200b000, 0x00000002, 0x83341c00,
+	0x00000008, 0x0401f8f5, 0x04000007, 0x42000000,
+	0x0010b83d, 0x0201f800, 0x0010aa47, 0x82000540,
+	0x00000001, 0x5c00b000, 0x1c01f000, 0x4933c857,
+	0x59cc0206, 0x82000580, 0x00000014, 0x04020016,
+	0x59cc0407, 0x82000580, 0x00000800, 0x04020012,
+	0x59cc0207, 0x8c00051a, 0x0400000d, 0x82000500,
+	0x00000f00, 0x82000580, 0x00000100, 0x04020008,
+	0x59cc020a, 0x8c000508, 0x04020003, 0x8c00050a,
+	0x04000003, 0x80000580, 0x1c01f000, 0x82000540,
+	0x00000001, 0x1c01f000, 0x4933c857, 0x4943c857,
+	0x493fc857, 0x4c5c0000, 0x4d300000, 0x4d340000,
+	0x4d2c0000, 0x4d380000, 0x4130b800, 0x42026000,
+	0x0010d1c0, 0x59a8000e, 0x81640480, 0x040210bd,
+	0x8d3e7d12, 0x04000004, 0x405c0000, 0x81300580,
+	0x040000b3, 0x59300406, 0x82000c80, 0x00000012,
+	0x04021015, 0x59326809, 0x0c01f001, 0x0010854f,
+	0x001084bc, 0x001084d3, 0x001084de, 0x001084b7,
+	0x001084ce, 0x00108507, 0x0010854f, 0x001084b5,
+	0x0010851b, 0x0010852a, 0x001084b5, 0x001084b5,
+	0x001084b5, 0x001084b5, 0x0010854f, 0x00108540,
+	0x00108538, 0x0201f800, 0x001005d8, 0x8d3e7d18,
+	0x04000004, 0x59300420, 0x8c000500, 0x04020094,
+	0x59300403, 0x82000580, 0x00000043, 0x04000090,
+	0x0201f800, 0x00109134, 0x02000800, 0x00102074,
+	0x0201f800, 0x0010914e, 0x02000800, 0x0010801c,
+	0x8d3e7d06, 0x04000084, 0x0201f800, 0x001092d7,
+	0x04000083, 0x0401f080, 0x8d3e7d16, 0x04000004,
+	0x59300420, 0x8c000500, 0x0402007d, 0x59325808,
+	0x0201f800, 0x00109037, 0x04000077, 0x49425a06,
+	0x497a5c09, 0x0201f800, 0x000202da, 0x0201f800,
+	0x0010912a, 0x0401f070, 0x813669c0, 0x02000800,
+	0x001005d8, 0x8d3e7d06, 0x04000004, 0x59340200,
+	0x8c00050e, 0x0402006a, 0x59300004, 0x8400055c,
+	0x48026004, 0x59300203, 0x82000580, 0x00000004,
+	0x02000800, 0x00100e99, 0x59325808, 0x0201f800,
+	0x00109037, 0x0400005c, 0x4a025a04, 0x00000103,
+	0x59300402, 0x48025c06, 0x592c0408, 0x8c000512,
+	0x04000006, 0x4d2c0000, 0x592e5809, 0x0201f800,
+	0x001007fd, 0x5c025800, 0x49425a06, 0x497a5c09,
+	0x0201f800, 0x0010959c, 0x0201f800, 0x000202da,
+	0x0201f800, 0x0010912a, 0x0401f047, 0x8c000518,
+	0x04000047, 0x59300203, 0x82000580, 0x00000004,
+	0x02000800, 0x00100e99, 0x59325808, 0x0201f800,
+	0x00109037, 0x0400003c, 0x49425a06, 0x497a5c09,
+	0x0201f800, 0x0010a693, 0x0201f800, 0x0010959c,
+	0x0201f800, 0x000202da, 0x0401f033, 0x0201f800,
+	0x001062d5, 0x04000032, 0x59300203, 0x82000580,
+	0x00000004, 0x04020004, 0x0201f800, 0x00100e99,
+	0x0401f02b, 0x42027000, 0x00000047, 0x0201f800,
+	0x000207a1, 0x0401f026, 0x59300203, 0x82000580,
+	0x00000004, 0x02000800, 0x00100e99, 0x59325808,
+	0x0201f800, 0x00109037, 0x0400001b, 0x49425a06,
+	0x497a5c09, 0x0201f800, 0x000202da, 0x0401f016,
+	0x833c0500, 0x00001800, 0x04000015, 0x8d3e7d16,
+	0x04020013, 0x59325817, 0x0201f800, 0x001007fd,
+	0x59300203, 0x82000580, 0x00000004, 0x02000800,
+	0x00100e99, 0x59325808, 0x0201f800, 0x00109037,
+	0x04000005, 0x49425a06, 0x497a5c09, 0x0201f800,
+	0x000202da, 0x0201f800, 0x00107911, 0x83326400,
+	0x00000024, 0x41580000, 0x81300480, 0x04001742,
+	0x5c027000, 0x5c025800, 0x5c026800, 0x5c026000,
+	0x5c00b800, 0x1c01f000, 0x5c000000, 0x4c000000,
+	0x4803c857, 0x480bc857, 0x480fc857, 0x485bc857,
+	0x50080800, 0x500c0000, 0x80042580, 0x04020007,
+	0x80081000, 0x800c1800, 0x8058b040, 0x040207f9,
+	0x80000580, 0x1c01f000, 0x4803c857, 0x4807c857,
+	0x480bc857, 0x480fc857, 0x80040480, 0x04001006,
+	0x42000000, 0x00000001, 0x82040d40, 0x00000001,
+	0x1c01f000, 0x41780000, 0x0401f7fc, 0x83380480,
+	0x00000053, 0x02021800, 0x001005d8, 0x83380480,
+	0x0000004b, 0x02001800, 0x001005d8, 0x0c01f001,
+	0x0010858a, 0x0010858a, 0x0010858a, 0x0010858a,
+	0x00108588, 0x00108588, 0x00108588, 0x0010858a,
+	0x0201f800, 0x001005d8, 0x493bc857, 0x4a026203,
+	0x0000000d, 0x493a6403, 0x42000800, 0x80000000,
+	0x0201f000, 0x00020721, 0x83380580, 0x00000013,
+	0x04020008, 0x59300403, 0x82000580, 0x00000050,
+	0x02020800, 0x001005d8, 0x0201f000, 0x0002077d,
+	0x4933c857, 0x83380580, 0x00000027, 0x04020030,
+	0x4933c857, 0x0201f800, 0x00106bbf, 0x4d3c0000,
+	0x417a7800, 0x0201f800, 0x0010203c, 0x5c027800,
+	0x42000000, 0x0010b864, 0x0201f800, 0x0010aa47,
+	0x4d2c0000, 0x59325808, 0x0201f800, 0x00109037,
+	0x492fc857, 0x0400000d, 0x4a025a04, 0x00000103,
+	0x59300c02, 0x48065c06, 0x4a025a06, 0x00000029,
+	0x497a5c09, 0x592c0c08, 0x84040d50, 0x48065c08,
+	0x0201f800, 0x000202da, 0x5c025800, 0x42003000,
+	0x00000015, 0x41782800, 0x42002000, 0x00000003,
+	0x4d400000, 0x4d440000, 0x59368c03, 0x42028000,
+	0x00000029, 0x0201f800, 0x0010985e, 0x5c028800,
+	0x5c028000, 0x0201f000, 0x0002077d, 0x83380580,
+	0x00000014, 0x0402000c, 0x59300403, 0x82000c80,
+	0x00000053, 0x02021800, 0x001005d8, 0x82000480,
+	0x00000040, 0x02001800, 0x001005d8, 0x4803c857,
+	0x0c01f00e, 0x83380580, 0x00000053, 0x0400000a,
+	0x83380580, 0x00000048, 0x02020800, 0x001005d8,
+	0x59300403, 0x82000580, 0x00000050, 0x02020800,
+	0x001005d8, 0x1c01f000, 0x001085ff, 0x001085fd,
+	0x001085fd, 0x001085fd, 0x001085fd, 0x001085fd,
+	0x001085fd, 0x001085fd, 0x001085fd, 0x001085fd,
+	0x001085fd, 0x00108616, 0x00108616, 0x00108616,
+	0x00108616, 0x001085fd, 0x00108616, 0x001085fd,
+	0x00108616, 0x0201f800, 0x001005d8, 0x4933c857,
+	0x0201f800, 0x00106bbf, 0x0201f800, 0x00109037,
+	0x02000000, 0x0002077d, 0x4d2c0000, 0x59325808,
+	0x4a025a04, 0x00000103, 0x59300402, 0x48025c06,
+	0x4a025a06, 0x00000006, 0x497a5c09, 0x0201f800,
+	0x000202da, 0x5c025800, 0x0201f800, 0x0010912a,
+	0x0201f000, 0x0002077d, 0x4933c857, 0x0201f800,
+	0x00106bbf, 0x0201f000, 0x0002077d, 0x0201f800,
+	0x001005d8, 0x5930001c, 0x800001c0, 0x02020800,
+	0x0010984e, 0x59300004, 0x8c00053e, 0x04020029,
+	0x59325808, 0x592c0c08, 0x59cc2a08, 0x82141d00,
+	0x00000c00, 0x04000002, 0x59cc1809, 0x84040d58,
+	0x48065c08, 0x82143500, 0x00000fff, 0x04020027,
+	0x59340200, 0x8c00050e, 0x04020080, 0x0201f800,
+	0x0002082b, 0x04020006, 0x4a025a06, 0x00000000,
+	0x59300811, 0x800409c0, 0x0402094b, 0x4a025a04,
+	0x00000103, 0x48065807, 0x480e580a, 0x48165c09,
+	0x59300c02, 0x48065c06, 0x0201f800, 0x000202c1,
+	0x0201f800, 0x001049b2, 0x59cc0208, 0x8c000518,
+	0x02020000, 0x001091d1, 0x0201f000, 0x0002077d,
+	0x0201f800, 0x00106f60, 0x040007d6, 0x4d3c0000,
+	0x42027800, 0x00000002, 0x0201f800, 0x00108be3,
+	0x5c027800, 0x0401f7cf, 0x4817c857, 0x480fc857,
+	0x82180500, 0x000000ff, 0x0400000e, 0x592c0204,
+	0x82000500, 0x000000ff, 0x82000580, 0x00000048,
+	0x04020008, 0x592c0407, 0x800001c0, 0x04000005,
+	0x0201f800, 0x0010973f, 0x0201f000, 0x00109787,
+	0x82180d00, 0x00000c00, 0x04000004, 0x59340200,
+	0x8c00050e, 0x04020032, 0x4a025a06, 0x00000000,
+	0x41782000, 0x8c183510, 0x04000007, 0x59cc000c,
+	0x82000500, 0x000000ff, 0x04000002, 0x4803c857,
+	0x59cc200b, 0x4812580c, 0x41780000, 0x8c183512,
+	0x04000002, 0x59cc000a, 0x4802580b, 0x80100c00,
+	0x040007b8, 0x82041480, 0x0000001d, 0x04001006,
+	0x592c0404, 0x8c00051e, 0x0400000e, 0x42000800,
+	0x0000001c, 0x4c500000, 0x4c540000, 0x83cca400,
+	0x0000000c, 0x832cac00, 0x0000000d, 0x0201f800,
+	0x00108b9f, 0x5c00a800, 0x5c00a000, 0x0401f7a5,
+	0x59300011, 0x59301402, 0x480a5c06, 0x48025807,
+	0x480e580a, 0x48165c09, 0x0201f800, 0x00108b48,
+	0x0201f800, 0x00108b84, 0x0401f7a6, 0x592c020a,
+	0x8c000502, 0x040007cd, 0x592c0208, 0x8c00050e,
+	0x040207ca, 0x59300011, 0x800c0d80, 0x040007c7,
+	0x4803c857, 0x480fc857, 0x8c183514, 0x02000000,
+	0x0010920f, 0x80000540, 0x040007c0, 0x4807c856,
+	0x0201f000, 0x0010920f, 0x592c020a, 0x8c000502,
+	0x04000782, 0x59300011, 0x800001c0, 0x0400077f,
+	0x592c0208, 0x8c00050e, 0x0402077c, 0x0201f000,
+	0x0010920f, 0x59cc2006, 0x59cc2807, 0x0401f035,
+	0x0401f034, 0x1c01f000, 0x4933c857, 0x5930001c,
+	0x800001c0, 0x02020800, 0x0010984e, 0x59325808,
+	0x592c0c08, 0x41782800, 0x41781800, 0x84040d58,
+	0x48065c08, 0x41783000, 0x59340200, 0x8c00050e,
+	0x04020018, 0x0201f800, 0x0002082b, 0x04020007,
+	0x4a025a06, 0x00000000, 0x59300811, 0x4807c857,
+	0x800409c0, 0x040208ac, 0x4a025a04, 0x00000103,
+	0x48065807, 0x480e580a, 0x48165c09, 0x4933c857,
+	0x59300c02, 0x48065c06, 0x0201f800, 0x000202c1,
+	0x0201f800, 0x001049b2, 0x0201f000, 0x0002077d,
+	0x592c020a, 0x8c000502, 0x040007ea, 0x59300011,
+	0x4803c857, 0x800001c0, 0x040007e6, 0x592c0208,
+	0x8c00050e, 0x040207e3, 0x0201f000, 0x0010920f,
+	0x5930001c, 0x800001c0, 0x4c100000, 0x4c140000,
+	0x02020800, 0x0010984e, 0x5c002800, 0x5c002000,
+	0x4a026203, 0x00000002, 0x4a026403, 0x00000043,
+	0x59325808, 0x592c020a, 0x8c000502, 0x04020018,
+	0x40100000, 0x592c080f, 0x80040c80, 0x40140000,
+	0x80040480, 0x04001014, 0x48126013, 0x48166011,
+	0x59300004, 0x8c00053e, 0x04020008, 0x497a6205,
+	0x0201f800, 0x00100f93, 0x04020009, 0x59300804,
+	0x0201f000, 0x00106721, 0x0201f800, 0x00106f60,
+	0x040007f7, 0x0201f000, 0x00107974, 0x4933c857,
+	0x1c01f000, 0x4807c857, 0x40042800, 0x0401f7eb,
+	0x83380480, 0x00000058, 0x04021005, 0x83380480,
+	0x00000040, 0x04001002, 0x0c01f002, 0x1c01f000,
+	0x00108740, 0x00108740, 0x00108740, 0x00108740,
+	0x00108740, 0x00108740, 0x00108740, 0x00108740,
+	0x00108740, 0x00108740, 0x00108742, 0x00108740,
+	0x00108740, 0x00108740, 0x00108740, 0x0010874f,
+	0x00108740, 0x00108740, 0x00108740, 0x00108740,
+	0x0010877d, 0x00108740, 0x00108740, 0x00108740,
+	0x0201f800, 0x001005d8, 0x4933c857, 0x0201f800,
+	0x00106dc3, 0x4a026203, 0x00000002, 0x59a80039,
+	0x48026205, 0x59300011, 0x59300815, 0x80040c80,
+	0x48066015, 0x0201f000, 0x00106b8a, 0x4933c857,
+	0x0201f800, 0x00106b8a, 0x4d3c0000, 0x417a7800,
+	0x0201f800, 0x0010203c, 0x5c027800, 0x42000000,
+	0x0010b864, 0x0201f800, 0x0010aa47, 0x0201f800,
+	0x00109037, 0x04000010, 0x4d2c0000, 0x59325808,
+	0x4a025a04, 0x00000103, 0x59300402, 0x48025c06,
+	0x4a025a06, 0x00000029, 0x497a5c09, 0x592c0c08,
+	0x84040d50, 0x48065c08, 0x0201f800, 0x000202da,
+	0x5c025800, 0x42003000, 0x00000014, 0x41782800,
+	0x4d400000, 0x4d440000, 0x59368c03, 0x42002000,
+	0x00000002, 0x42028000, 0x00000029, 0x0201f800,
+	0x0010985e, 0x5c028800, 0x5c028000, 0x0201f000,
+	0x0002077d, 0x4933c857, 0x59300808, 0x49780c09,
+	0x4978080a, 0x58041408, 0x84081558, 0x48080c08,
+	0x1c01f000, 0x4807c857, 0x8c040d3e, 0x04020023,
+	0x497a5a06, 0x5930001f, 0x80000540, 0x04000017,
+	0x497a5a06, 0x4c040000, 0x4c080000, 0x4c0c0000,
+	0x4c100000, 0x4c140000, 0x58f41003, 0x40040000,
+	0x80081480, 0x5930001f, 0x4809e803, 0x0201f800,
+	0x00100d56, 0x5c002800, 0x5c002000, 0x5c001800,
+	0x5c001000, 0x5c000800, 0x592c0206, 0x80000540,
+	0x04020009, 0x0401f005, 0x592c0408, 0x8c00051c,
+	0x04000002, 0x592c0803, 0x4807c857, 0x4a025a06,
+	0x00000015, 0x1c01f000, 0x5930001f, 0x80000540,
+	0x04000009, 0x4a025a06, 0x00000011, 0x5930001f,
+	0x4c040000, 0x0201f800, 0x00100d56, 0x5c000800,
+	0x0401f7f5, 0x4807c856, 0x4a025a06, 0x00000007,
+	0x1c01f000, 0x83380480, 0x00000058, 0x04021007,
+	0x83380480, 0x00000040, 0x04001004, 0x4d2c0000,
+	0x0c01f803, 0x5c025800, 0x1c01f000, 0x001087db,
+	0x001087db, 0x001087db, 0x001087db, 0x001087db,
+	0x001087dd, 0x001087db, 0x001087db, 0x00108860,
+	0x001087db, 0x001087db, 0x001087db, 0x001087db,
+	0x001087db, 0x001087db, 0x001087db, 0x001087db,
+	0x001087db, 0x001087db, 0x00108910, 0x00108939,
+	0x00108918, 0x001087db, 0x00108945, 0x0201f800,
+	0x001005d8, 0x5930001c, 0x800001c0, 0x02020800,
+	0x0010984e, 0x59300007, 0x8c00050e, 0x0400007c,
+	0x8c000500, 0x0400006e, 0x8c00051c, 0x04000009,
+	0x84000500, 0x48026007, 0x59325808, 0x592c3c08,
+	0x841c3d58, 0x481e5c08, 0x0201f000, 0x000207dd,
+	0x59325808, 0x592c3c08, 0x841c3d58, 0x59300007,
+	0x8c00051c, 0x040207f3, 0x481e5c08, 0x42000000,
+	0x00000005, 0x40000000, 0x80000040, 0x040207fe,
+	0x59300007, 0x8c00051c, 0x040207ea, 0x59cc0a08,
+	0x592c0204, 0x82000500, 0x000000ff, 0x82000580,
+	0x00000048, 0x0402000c, 0x497a580b, 0x82040500,
+	0x000000ff, 0x04000008, 0x592c0407, 0x800001c0,
+	0x04000005, 0x0201f800, 0x0010973f, 0x0201f000,
+	0x00100e56, 0x48065c09, 0x41782000, 0x82040500,
+	0x00000c00, 0x04000002, 0x59cc2009, 0x82043500,
+	0x00000fff, 0x04020027, 0x481e5c08, 0x4a025a06,
+	0x00000000, 0x801831c0, 0x02000000, 0x00100e56,
+	0x41782000, 0x8c183510, 0x04000002, 0x59cc200b,
+	0x4812580c, 0x41780000, 0x8c183512, 0x04000002,
+	0x59cc000a, 0x4802580b, 0x80100c00, 0x02001800,
+	0x001005d8, 0x02000000, 0x00100e56, 0x82041480,
+	0x0000001d, 0x0402100c, 0x4c500000, 0x4c540000,
+	0x83cca400, 0x0000000c, 0x832cac00, 0x0000000d,
+	0x0401fb67, 0x5c00a800, 0x5c00a000, 0x0201f000,
+	0x00100e56, 0x0401fb0b, 0x0201f000, 0x00100e56,
+	0x412c7800, 0x0201f800, 0x001007e4, 0x02000800,
+	0x001005d8, 0x492c7809, 0x841c3d52, 0x481c7c08,
+	0x4a025a04, 0x00000103, 0x4812580a, 0x48065c09,
+	0x583c0404, 0x583c1005, 0x583c2208, 0x48025c04,
+	0x480a5805, 0x48125a08, 0x0401f7c8, 0x8c000524,
+	0x04000794, 0x59325808, 0x4c000000, 0x592c0408,
+	0x8c00051c, 0x5c000000, 0x04020003, 0x4a026011,
+	0xffffffff, 0x84000524, 0x0401f78a, 0x1c01f000,
+	0x59a80039, 0x48026205, 0x59325808, 0x4a026203,
+	0x00000002, 0x592c2408, 0x59300807, 0x4933c857,
+	0x4807c857, 0x592c0204, 0x82000500, 0x000000ff,
+	0x82000580, 0x00000048, 0x04020004, 0x8c102500,
+	0x02020000, 0x00109787, 0x4a025a06, 0x00000000,
+	0x8c040d1e, 0x04000027, 0x41780800, 0x497a5c09,
+	0x592c1c09, 0x59300011, 0x59341200, 0x497a6205,
+	0x8c08150e, 0x0402006e, 0x4807c857, 0x4806580a,
+	0x80000d40, 0x04020f04, 0x59300402, 0x48025c06,
+	0x48065807, 0x4a025a04, 0x00000103, 0x4c040000,
+	0x4c0c0000, 0x4c100000, 0x0201f800, 0x0010959c,
+	0x5c002000, 0x5c001800, 0x5c000800, 0x8c102512,
+	0x0402001a, 0x4c0c0000, 0x0201f800, 0x000202c1,
+	0x0201f800, 0x001049b2, 0x5c001800, 0x8c0c1d18,
+	0x02000000, 0x0002077d, 0x0201f000, 0x001091d1,
+	0x4813c857, 0x8c102518, 0x0400004b, 0x41780800,
+	0x592c1c09, 0x820c0580, 0x00001000, 0x040007d6,
+	0x8c102512, 0x040007d4, 0x592c7809, 0x583c080a,
+	0x583c1c09, 0x0401f7d0, 0x4807c857, 0x592c7809,
+	0x59300402, 0x592c1404, 0x8c08151e, 0x0402000d,
+	0x592c1206, 0x48007c06, 0x48047807, 0x48087a06,
+	0x84102512, 0x48107c08, 0x4c0c0000, 0x0201f800,
+	0x001007fd, 0x403e5800, 0x0401faca, 0x0401f7d9,
+	0x48025c06, 0x48065807, 0x583c080c, 0x583c000b,
+	0x80040c00, 0x82041480, 0x0000001d, 0x04001006,
+	0x583c1001, 0x480a5801, 0x49787801, 0x42000800,
+	0x0000001c, 0x82040c00, 0x00000014, 0x4c0c0000,
+	0x4c500000, 0x4c540000, 0x823ca400, 0x00000008,
+	0x832cac00, 0x00000008, 0x4c100000, 0x4c3c0000,
+	0x0401facb, 0x5c007800, 0x5c002000, 0x5c00a800,
+	0x5c00a000, 0x84102512, 0x48125c08, 0x403e5800,
+	0x0201f800, 0x001007fd, 0x42034000, 0x0010b4a4,
+	0x59a1d81e, 0x80edd9c0, 0x02000800, 0x001005d8,
+	0x48efc857, 0x58ec0009, 0x4803c857, 0x0801f800,
+	0x0401f7ac, 0x4933c857, 0x1c01f000, 0x59301414,
+	0x480bc857, 0x8c08151c, 0x0402000e, 0x80000540,
+	0x4803c857, 0x0400078d, 0x80042c80, 0x0402178b,
+	0x8c081514, 0x04020005, 0x592c080f, 0x4807c857,
+	0x80040480, 0x48026016, 0x8408155c, 0x480a6414,
+	0x59301007, 0x8408151e, 0x480a6007, 0x4a025c09,
+	0x00000001, 0x0201f800, 0x0010959c, 0x497a5c09,
+	0x8c102512, 0x04000006, 0x4d2c0000, 0x403e5800,
+	0x0201f800, 0x001007fd, 0x5c025800, 0x82102500,
+	0xffffedff, 0x48125c08, 0x0201f000, 0x0010920f,
+	0x59325808, 0x592c0408, 0x8c000518, 0x04000004,
+	0x412df800, 0x0201f000, 0x00100e6f, 0x1c01f000,
+	0x4933c857, 0x59325808, 0x497a5c09, 0x4a025a06,
+	0x00000000, 0x4a025a04, 0x00000103, 0x59300811,
+	0x4807c857, 0x800409c0, 0x0402000a, 0x48065807,
+	0x59300c02, 0x48065c06, 0x0201f800, 0x000202c1,
+	0x0201f800, 0x001049b2, 0x0201f000, 0x0002077d,
+	0x59340200, 0x8c00050e, 0x04020005, 0x59300811,
+	0x0401fe55, 0x48065807, 0x0401f7f2, 0x592c0208,
+	0x8c00050e, 0x040207fa, 0x4933c857, 0x0201f000,
+	0x0010920f, 0x4933c857, 0x59325808, 0x812e59c0,
+	0x02000800, 0x001005d8, 0x592c020a, 0x8c000502,
+	0x02000800, 0x001005d8, 0x4a026206, 0x00000002,
+	0x1c01f000, 0x5930001c, 0x800001c0, 0x02020800,
+	0x0010984e, 0x59300007, 0x4933c857, 0x4803c857,
+	0x8c00050e, 0x04000037, 0x8c000500, 0x04000029,
+	0x8c00051c, 0x0400000a, 0x84000500, 0x48026007,
+	0x59325808, 0x592c3c08, 0x481fc857, 0x841c3d58,
+	0x481e5c08, 0x0201f000, 0x000207dd, 0x59325808,
+	0x592c3c08, 0x841c3d58, 0x59300007, 0x8c00051c,
+	0x040207f2, 0x481e5c08, 0x42000000, 0x00000005,
+	0x40000000, 0x80000040, 0x040207fe, 0x59300007,
+	0x8c00051c, 0x040207e9, 0x592c0204, 0x82000500,
+	0x000000ff, 0x82000580, 0x00000048, 0x04020003,
+	0x497a580b, 0x0401f002, 0x497a5c09, 0x481e5c08,
+	0x4a025a06, 0x00000000, 0x0201f000, 0x00100e56,
+	0x8c000524, 0x040007d9, 0x59325808, 0x4c000000,
+	0x592c0408, 0x8c00051c, 0x5c000000, 0x04020003,
+	0x4a026011, 0xffffffff, 0x84000524, 0x0401f7cf,
+	0x1c01f000, 0x4933c857, 0x41780800, 0x83380480,
+	0x00000058, 0x0402100b, 0x83380480, 0x00000040,
+	0x04001008, 0x4d2c0000, 0x59325808, 0x812e59c0,
+	0x0c020806, 0x5c025800, 0x0201f000, 0x0002077d,
+	0x493bc857, 0x1c01f000, 0x001089ae, 0x001089ae,
+	0x001089ae, 0x001089ae, 0x001089ae, 0x001089b0,
+	0x001089ae, 0x001089ae, 0x001089ae, 0x001089ae,
+	0x001089ae, 0x001089ae, 0x001089ae, 0x001089ae,
+	0x001089ae, 0x001089ae, 0x001089ae, 0x001089ae,
+	0x001089ae, 0x001089ae, 0x001089b5, 0x001089ae,
+	0x001089ae, 0x001089ae, 0x0201f800, 0x001005d8,
+	0x59cc0a08, 0x497a5807, 0x4807c857, 0x82040d00,
+	0x00000fff, 0x59300402, 0x48025c06, 0x4a025a04,
+	0x00000103, 0x48065c09, 0x4a025a06, 0x00000000,
+	0x800409c0, 0x02000000, 0x000202c1, 0x59cc0009,
+	0x4802580a, 0x82042500, 0x00000100, 0x04000002,
+	0x59cc200b, 0x4812580c, 0x82040500, 0x00000200,
+	0x04000002, 0x59cc000a, 0x4802580b, 0x80100c00,
+	0x02001800, 0x001005d8, 0x02000000, 0x000202da,
+	0x82041480, 0x0000001d, 0x04001006, 0x592c0404,
+	0x8c00051e, 0x0400000e, 0x42000800, 0x0000001c,
+	0x4c500000, 0x4c540000, 0x83cca400, 0x0000000c,
+	0x832cac00, 0x0000000d, 0x0401f9c1, 0x5c00a800,
+	0x5c00a000, 0x0201f000, 0x000202da, 0x0401f965,
+	0x0401f1a0, 0x83380480, 0x00000093, 0x02021800,
+	0x001005d8, 0x83380480, 0x00000085, 0x02001800,
+	0x001005d8, 0x0c01f001, 0x001089fd, 0x001089fb,
+	0x001089fb, 0x00108a04, 0x001089fb, 0x001089fb,
+	0x001089fb, 0x001089fb, 0x001089fb, 0x001089fb,
+	0x001089fb, 0x001089fb, 0x001089fb, 0x0201f800,
+	0x001005d8, 0x4a026203, 0x00000001, 0x493a6403,
+	0x42000800, 0x80000040, 0x0201f000, 0x00020721,
+	0x4933c857, 0x59cc1204, 0x480a601c, 0x59cc1404,
+	0x0201f800, 0x00109410, 0x0400001b, 0x591c0203,
+	0x82000580, 0x00000000, 0x04000017, 0x591c0009,
+	0x81340580, 0x04020014, 0x4d300000, 0x4d1c0000,
+	0x411e6000, 0x0401f9c2, 0x5c023800, 0x5c026000,
+	0x0400000b, 0x59cc0005, 0x8c000500, 0x04020003,
+	0x0401f98c, 0x0401f003, 0x4a023a03, 0x00000002,
+	0x4a026403, 0x00000086, 0x0401f005, 0x0401f9a6,
+	0x040007f5, 0x4a026403, 0x00000087, 0x4a026203,
+	0x00000001, 0x42000800, 0x80000040, 0x0201f800,
+	0x00020721, 0x59340200, 0x8c00050e, 0x0400000d,
+	0x59cc1404, 0x0201f800, 0x00109410, 0x04000009,
+	0x591c0414, 0x8c00051a, 0x04000006, 0x4d300000,
+	0x411e6000, 0x0201f800, 0x0010921e, 0x5c026000,
+	0x1c01f000, 0x83380580, 0x00000013, 0x0402000a,
+	0x59300403, 0x82000d80, 0x00000086, 0x04000012,
+	0x82000d80, 0x00000087, 0x02020800, 0x001005d8,
+	0x0401f00d, 0x83380580, 0x00000027, 0x04000005,
+	0x83380580, 0x00000014, 0x02020800, 0x001005d8,
+	0x493bc857, 0x0201f800, 0x00106bbf, 0x0201f000,
+	0x00107911, 0x4933c857, 0x0201f000, 0x00107911,
+	0x83380580, 0x00000013, 0x04020005, 0x59300403,
+	0x82000480, 0x00000085, 0x0c01f04d, 0x83380580,
+	0x00000027, 0x04020041, 0x4933c857, 0x0201f800,
+	0x00106bbf, 0x4d3c0000, 0x417a7800, 0x0201f800,
+	0x0010203c, 0x5c027800, 0x42003000, 0x00000015,
+	0x41782800, 0x42002000, 0x00000003, 0x42028000,
+	0x00000029, 0x4d400000, 0x4d440000, 0x59368c03,
+	0x0201f800, 0x0010985e, 0x5c028800, 0x5c028000,
+	0x42000000, 0x0010b864, 0x0201f800, 0x0010aa47,
+	0x0201f800, 0x00109037, 0x0400000c, 0x4d2c0000,
+	0x59325808, 0x4a025a04, 0x00000103, 0x59300402,
+	0x48025c06, 0x497a5c09, 0x49425a06, 0x0201f800,
+	0x000202da, 0x5c025800, 0x0201f800, 0x0010912a,
+	0x0201f000, 0x0002077d, 0x83380580, 0x00000089,
+	0x04000005, 0x83380580, 0x0000008a, 0x02020000,
+	0x00107974, 0x0201f800, 0x00106f60, 0x02020000,
+	0x00107974, 0x59300a03, 0x82040580, 0x0000000a,
+	0x0400002a, 0x82040580, 0x0000000c, 0x04000027,
+	0x0201f800, 0x001005d8, 0x83380580, 0x00000014,
+	0x040207ea, 0x4933c857, 0x0201f800, 0x00106bbf,
+	0x42028000, 0x00000006, 0x0401f7d2, 0x00108aba,
+	0x00108ab8, 0x00108ab8, 0x00108ab8, 0x00108ab8,
+	0x00108ab8, 0x00108ac0, 0x00108ab8, 0x00108ab8,
+	0x00108ab8, 0x00108ab8, 0x00108ab8, 0x00108ab8,
+	0x0201f800, 0x001005d8, 0x4933c857, 0x59a80037,
+	0x48026206, 0x4a026203, 0x0000000a, 0x1c01f000,
+	0x4933c857, 0x59a80037, 0x48026206, 0x4a026203,
+	0x0000000c, 0x1c01f000, 0x83380580, 0x00000089,
+	0x04000008, 0x83380580, 0x0000008a, 0x04000032,
+	0x4933c857, 0x493bc857, 0x0201f000, 0x00107974,
+	0x4933c857, 0x59325808, 0x59300a1d, 0x82040580,
+	0x00000003, 0x04020004, 0x0201f800, 0x001049b2,
+	0x0401f00c, 0x5930021d, 0x82000580, 0x00000001,
+	0x04020008, 0x59300c16, 0x82040580, 0x00000039,
+	0x0400002c, 0x82040580, 0x00000035, 0x04000029,
+	0x4c340000, 0x41306800, 0x0201f800, 0x0002075a,
+	0x04000010, 0x4a026203, 0x00000001, 0x4a026403,
+	0x0000001e, 0x59cc0c07, 0x48066419, 0x59cc0a07,
+	0x48066219, 0x49366009, 0x4a026406, 0x00000001,
+	0x42000800, 0x80000040, 0x0201f800, 0x00020721,
+	0x40366000, 0x0201f800, 0x0002077d, 0x5c006800,
+	0x1c01f000, 0x4933c857, 0x5930021d, 0x82000580,
+	0x00000001, 0x04020040, 0x59300c16, 0x82040580,
+	0x00000035, 0x04000007, 0x82040580, 0x0000001e,
+	0x04000004, 0x82040580, 0x00000039, 0x04020036,
+	0x4933c857, 0x4c500000, 0x4d1c0000, 0x4130a000,
+	0x40067000, 0x0201f800, 0x001093ba, 0x04020029,
+	0x0201f800, 0x0002075a, 0x04000026, 0x491fc857,
+	0x4933c857, 0x83380580, 0x00000035, 0x04000004,
+	0x83380580, 0x00000039, 0x04020002, 0x4932381c,
+	0x493a6403, 0x4a026203, 0x00000001, 0x4a026406,
+	0x00000001, 0x58500809, 0x4807c857, 0x48066009,
+	0x58500c15, 0x4807c857, 0x48066415, 0x58500a15,
+	0x4807c857, 0x48066215, 0x58500a16, 0x4807c857,
+	0x48066216, 0x58500c19, 0x4807c857, 0x48066419,
+	0x58500a19, 0x4807c857, 0x48066219, 0x491e601e,
+	0x42000800, 0x80000040, 0x0201f800, 0x00020721,
+	0x40526000, 0x5c023800, 0x5c00a000, 0x0201f000,
+	0x0002077d, 0x5930021d, 0x82000580, 0x00000003,
+	0x02000800, 0x001049b2, 0x0201f000, 0x0002077d,
+	0x4803c856, 0x4c500000, 0x4c540000, 0x412c7800,
+	0x4c3c0000, 0x42002800, 0x00000001, 0x82040480,
+	0x00000101, 0x04001003, 0x42000800, 0x00000100,
+	0x40043000, 0x42000800, 0x0000001c, 0x83cca400,
+	0x0000000c, 0x832cac00, 0x0000000d, 0x0401f844,
+	0x82183480, 0x0000001c, 0x592e5801, 0x812e59c0,
+	0x02020800, 0x001007fd, 0x0201f800, 0x001007e4,
+	0x04000017, 0x80142800, 0x4a025a04, 0x00000110,
+	0x497a5c04, 0x492c7801, 0x82180c80, 0x0000003d,
+	0x04021006, 0x40180800, 0x832cac00, 0x00000005,
+	0x0401f82f, 0x0401f00a, 0x82183480, 0x0000003c,
+	0x42000800, 0x0000003c, 0x412c7800, 0x832cac00,
+	0x00000005, 0x0401f826, 0x0401f7e8, 0x5c007800,
+	0x841429c0, 0x82142d40, 0x00000003, 0x48147a04,
+	0x403e5800, 0x5c00a800, 0x5c00a000, 0x1c01f000,
+	0x492fc857, 0x812e59c0, 0x0400000f, 0x4d2c0000,
+	0x4c3c0000, 0x592c7801, 0x803c79c0, 0x04000006,
+	0x497a5801, 0x0201f800, 0x000202da, 0x403e5800,
+	0x0401f7f9, 0x5c007800, 0x0201f800, 0x000202da,
+	0x5c025800, 0x1c01f000, 0x4803c856, 0x4c580000,
+	0x82040c00, 0x00000003, 0x8004b104, 0x0201f800,
+	0x0010ab17, 0x5c00b000, 0x1c01f000, 0x4803c856,
+	0x4c580000, 0x82040c00, 0x00000003, 0x8004b104,
+	0x0201f800, 0x0010ab17, 0x5c00b000, 0x1c01f000,
+	0x591c0c06, 0x82040580, 0x00000003, 0x04000004,
+	0x82040580, 0x00000002, 0x0402001a, 0x4d300000,
+	0x4d2c0000, 0x411e6000, 0x59325808, 0x0201f800,
+	0x00109037, 0x0400000f, 0x4d400000, 0x42028000,
+	0x00000013, 0x592c0a08, 0x84040d54, 0x0201f800,
+	0x00104e70, 0x5c028000, 0x0201f800, 0x0010959c,
+	0x0201f800, 0x000202da, 0x0201f800, 0x0010912a,
+	0x0201f800, 0x00107911, 0x5c025800, 0x5c026000,
+	0x1c01f000, 0x59cc0005, 0x8c000500, 0x0402000b,
+	0x591c0406, 0x82000580, 0x00000002, 0x04020007,
+	0x591c0c03, 0x82040580, 0x00000085, 0x04000003,
+	0x82040580, 0x0000008b, 0x1c01f000, 0x4933c857,
+	0x4d3c0000, 0x42027800, 0x00000002, 0x59300406,
+	0x82000c80, 0x00000012, 0x02021800, 0x001005d8,
+	0x0c01f80a, 0x5c027800, 0x1c01f000, 0x4933c857,
+	0x59300406, 0x82000c80, 0x00000012, 0x02021800,
+	0x001005d8, 0x0c01f001, 0x00108c01, 0x00108bfe,
+	0x00108bfe, 0x00108c29, 0x00108bfc, 0x00108bfe,
+	0x00108c1a, 0x00108bfe, 0x00108bfc, 0x001065f4,
+	0x00108bfe, 0x00108bfe, 0x00108bfe, 0x00108bfc,
+	0x00108bfc, 0x00108bfc, 0x00108cf9, 0x00108bfe,
+	0x0201f800, 0x001005d8, 0x4803c856, 0x80000580,
+	0x1c01f000, 0x4803c856, 0x8d3e7d02, 0x04020016,
+	0x0201f800, 0x00109037, 0x0400000f, 0x59325808,
+	0x41780800, 0x4d400000, 0x42028000, 0x00000005,
+	0x0201f800, 0x00104e70, 0x5c028000, 0x0201f800,
+	0x0010959c, 0x0201f800, 0x001091cc, 0x0201f800,
+	0x000202da, 0x0201f800, 0x00107911, 0x82000540,
+	0x00000001, 0x1c01f000, 0x4933c857, 0x0201f800,
+	0x001048d9, 0x0402000c, 0x4d400000, 0x42028000,
+	0x00000010, 0x0201f800, 0x0010a1d1, 0x4a026406,
+	0x00000006, 0x4a026203, 0x00000007, 0x5c028000,
+	0x1c01f000, 0x4933c857, 0x0201f800, 0x00106c55,
+	0x4df00000, 0x0401f8b8, 0x82000c80, 0x0000000e,
+	0x02021800, 0x001005d8, 0x0c01f001, 0x00108c43,
+	0x00108cb0, 0x00108c5a, 0x00108cc3, 0x00108cab,
+	0x00108c41, 0x00108c43, 0x00108c43, 0x00108c47,
+	0x00108c43, 0x00108c43, 0x00108c43, 0x00108c43,
+	0x00108c5a, 0x0201f800, 0x001005d8, 0x5c03e000,
+	0x02000800, 0x00106c4b, 0x0401f7b8, 0x5c03e000,
+	0x02000800, 0x00106c4b, 0x59300406, 0x82000580,
+	0x00000003, 0x040207b4, 0x59300203, 0x82000580,
+	0x0000000d, 0x040007b0, 0x8d3e7d02, 0x040207ae,
+	0x4d340000, 0x59326809, 0x0201f800, 0x001049b2,
+	0x5c026800, 0x0401f7a8, 0x59300004, 0x8400055c,
+	0x48026004, 0x0201f800, 0x00106c4b, 0x59300406,
+	0x82000580, 0x00000006, 0x04000043, 0x8d3e7d02,
+	0x04020041, 0x497a621d, 0x59300203, 0x82000580,
+	0x0000000d, 0x04000003, 0x4a02621d, 0x00000003,
+	0x0401fbcb, 0x04000024, 0x4d2c0000, 0x4d400000,
+	0x59325808, 0x0201f800, 0x001091cc, 0x592c0408,
+	0x8c000512, 0x04000009, 0x4d2c0000, 0x84000512,
+	0x48025c08, 0x592c0809, 0x40065800, 0x0201f800,
+	0x001007fd, 0x5c025800, 0x4d400000, 0x42028000,
+	0x00000005, 0x592c0a08, 0x8c040d0e, 0x04000004,
+	0x42028000, 0x00000002, 0x0401f001, 0x0201f800,
+	0x00104e70, 0x5c028000, 0x0201f800, 0x0010959c,
+	0x0201f800, 0x000202da, 0x497a6008, 0x5c028000,
+	0x5c025800, 0x8d3e7d00, 0x04000009, 0x4d340000,
+	0x59326809, 0x0201f800, 0x001049b2, 0x5c026800,
+	0x0201f800, 0x00107911, 0x0401f00b, 0x4a026403,
+	0x00000085, 0x4a026203, 0x00000009, 0x4a026406,
+	0x00000002, 0x42000800, 0x8000404b, 0x0201f800,
+	0x00020721, 0x5c03e000, 0x02020800, 0x00106c55,
+	0x82000540, 0x00000001, 0x1c01f000, 0x0201f800,
+	0x00106c4b, 0x0201f800, 0x00100e99, 0x0401f7ab,
+	0x598c000d, 0x81300580, 0x04020004, 0x0201f800,
+	0x00106e8e, 0x0402001b, 0x0201f800, 0x001068d3,
+	0x04020006, 0x59300c03, 0x82040580, 0x00000040,
+	0x0400078b, 0x0401f79d, 0x0201f800, 0x00106b6c,
+	0x04000010, 0x0201f800, 0x001005d8, 0x0401f813,
+	0x04020004, 0x0201f800, 0x00106e62, 0x04020009,
+	0x0201f800, 0x001067ae, 0x040207f4, 0x59300c03,
+	0x82040580, 0x00000040, 0x04000779, 0x0401f78b,
+	0x59300203, 0x82000c80, 0x0000000e, 0x02021800,
+	0x001005d8, 0x0c01f75e, 0x417a3000, 0x42032000,
+	0x0000bf32, 0x59900004, 0x81300580, 0x04000009,
+	0x83932400, 0x00000010, 0x811a3000, 0x83180480,
+	0x00000005, 0x040017f8, 0x82000540, 0x00000001,
+	0x1c01f000, 0x59300004, 0x8c00053e, 0x04000010,
+	0x8c00050c, 0x0402000e, 0x8c000516, 0x04020006,
+	0x82000d00, 0x0000001f, 0x82040580, 0x00000005,
+	0x04020004, 0x42000000, 0x00000003, 0x0401f005,
+	0x42000000, 0x00000001, 0x0401f002, 0x59300203,
+	0x1c01f000, 0x4933c857, 0x0201f800, 0x00106c55,
+	0x4df00000, 0x59300203, 0x82000c80, 0x0000000e,
+	0x02021800, 0x001005d8, 0x0c01f001, 0x00108d13,
+	0x00108d30, 0x00108d17, 0x00108d11, 0x00108d11,
+	0x00108d11, 0x00108d11, 0x00108d11, 0x00108d11,
+	0x00108d11, 0x00108d11, 0x00108d11, 0x00108d11,
+	0x00108d11, 0x0201f800, 0x001005d8, 0x5c03e000,
+	0x02000800, 0x00106c4b, 0x0401f6e8, 0x5c03e000,
+	0x02000800, 0x00106c4b, 0x4d2c0000, 0x59325808,
+	0x59300403, 0x82000580, 0x00000052, 0x02000800,
+	0x00101231, 0x0401fb16, 0x02000800, 0x001005d8,
+	0x4a025a06, 0x00000005, 0x0201f800, 0x000202da,
+	0x0201f800, 0x00104c19, 0x0201f800, 0x00107911,
+	0x5c025800, 0x82000540, 0x00000001, 0x1c01f000,
+	0x598c000d, 0x81300580, 0x0402001a, 0x59300004,
+	0x8c000520, 0x04000004, 0x84000520, 0x48026004,
+	0x0401f01a, 0x42001000, 0x0010b7f6, 0x50081000,
+	0x58080002, 0x82000580, 0x00000100, 0x0400000a,
+	0x5808000c, 0x81300580, 0x02020800, 0x001005d8,
+	0x0201f800, 0x001068d3, 0x02020800, 0x001005d8,
+	0x0401f7cf, 0x0201f800, 0x00106e8e, 0x0402000c,
+	0x59300004, 0x8c000520, 0x04000004, 0x84000520,
+	0x48026004, 0x0401f7c6, 0x0201f800, 0x001068d3,
+	0x040007c3, 0x0201f800, 0x001005d8, 0x59300203,
+	0x82000c80, 0x0000000e, 0x02021800, 0x001005d8,
+	0x0c01f7a7, 0x59300406, 0x4933c857, 0x4803c857,
+	0x82000c80, 0x00000012, 0x02021800, 0x001005d8,
+	0x0c01f001, 0x00108d7c, 0x00108e41, 0x00108f79,
+	0x00108d88, 0x00107911, 0x00108d7c, 0x0010a1c0,
+	0x0002077d, 0x00108e41, 0x001065ce, 0x00108fda,
+	0x00108d77, 0x00108d77, 0x00108d77, 0x00108d77,
+	0x00108d77, 0x001096eb, 0x001096eb, 0x0201f800,
+	0x001005d8, 0x0401fbd5, 0x02000000, 0x0010801c,
+	0x1c01f000, 0x0201f800, 0x00106c55, 0x0201f800,
+	0x00106bbf, 0x0201f800, 0x00106c4b, 0x0201f000,
+	0x0002077d, 0x4a026206, 0x00000001, 0x1c01f000,
+	0x42000000, 0x0010b872, 0x0201f800, 0x0010aa47,
+	0x4d2c0000, 0x4d400000, 0x417a5800, 0x0401faa8,
+	0x04000007, 0x59325808, 0x592c0208, 0x8400054c,
+	0x48025a08, 0x42028000, 0x00000006, 0x0201f800,
+	0x00106c55, 0x0401ff4c, 0x4803c857, 0x82000c80,
+	0x0000000e, 0x02021800, 0x001005d8, 0x0c01f806,
+	0x0201f800, 0x00106c4b, 0x5c028000, 0x5c025800,
+	0x1c01f000, 0x00108e40, 0x00108db5, 0x00108dc3,
+	0x00108de5, 0x00108e11, 0x00108db3, 0x00108d7c,
+	0x00108d7c, 0x00108d7c, 0x00108db3, 0x00108db3,
+	0x00108db3, 0x00108db3, 0x00108dc3, 0x0201f800,
+	0x001005d8, 0x598c000d, 0x81300580, 0x04020004,
+	0x0201f800, 0x00106e8e, 0x04020038, 0x0201f800,
+	0x001068d3, 0x0400003b, 0x0201f800, 0x00106b6c,
+	0x04000032, 0x0201f800, 0x001005d8, 0x497a621d,
+	0x812e59c0, 0x02000800, 0x001005d8, 0x592c0204,
+	0x82000500, 0x000000ff, 0x82000580, 0x00000014,
+	0x04000003, 0x4a02621d, 0x00000003, 0x592c0a08,
+	0x0201f800, 0x00104e70, 0x0201f800, 0x0010959c,
+	0x0201f800, 0x000202da, 0x497a6008, 0x4a026403,
+	0x00000085, 0x4a026203, 0x00000009, 0x4a026406,
+	0x00000002, 0x4a026004, 0x8000404b, 0x0201f800,
+	0x00106c4b, 0x42000800, 0x8000404b, 0x0201f000,
+	0x00020721, 0x0401fef1, 0x04020004, 0x0201f800,
+	0x00106e62, 0x04020009, 0x0201f800, 0x001067ae,
+	0x040207d2, 0x59300c03, 0x82040580, 0x00000040,
+	0x04000008, 0x0401f7d2, 0x59300203, 0x82000c80,
+	0x0000000e, 0x02021800, 0x001005d8, 0x0c01f7ae,
+	0x0201f800, 0x00106c4b, 0x812e59c0, 0x04000013,
+	0x592c0a08, 0x0201f800, 0x00104e70, 0x0201f800,
+	0x0010959c, 0x0201f800, 0x000202da, 0x59300203,
+	0x82000580, 0x0000000d, 0x04000008, 0x0201f800,
+	0x00106c4b, 0x4d340000, 0x59326809, 0x0201f800,
+	0x001049b2, 0x5c026800, 0x0201f800, 0x00107911,
+	0x0401f030, 0x812e59c0, 0x02000800, 0x001005d8,
+	0x0201f800, 0x0010940a, 0x04020004, 0x0201f800,
+	0x00100e99, 0x0401f7aa, 0x0201f800, 0x00106c4b,
+	0x592c0208, 0x8400050c, 0x48025a08, 0x592c0406,
+	0x800000c2, 0x800008c4, 0x80040c00, 0x48066206,
+	0x42000000, 0x10000000, 0x41300800, 0x0201f800,
+	0x00100b94, 0x0400000d, 0x592c0208, 0x8c00051c,
+	0x04020006, 0x8400055c, 0x48025a08, 0x4a026206,
+	0x00000002, 0x0401f00f, 0x4d300000, 0x0201f800,
+	0x001012e5, 0x5c026000, 0x59300203, 0x82000580,
+	0x00000004, 0x04020007, 0x4d380000, 0x42027000,
+	0x00000048, 0x0201f800, 0x000207a1, 0x5c027000,
+	0x1c01f000, 0x42000000, 0x0010b86e, 0x0201f800,
+	0x0010aa47, 0x59300203, 0x82000c80, 0x0000000e,
+	0x02021800, 0x001005d8, 0x4803c857, 0x0c01f001,
+	0x00108e5a, 0x00108d85, 0x00108e5c, 0x00108e5a,
+	0x00108e5c, 0x00108e5c, 0x00108d7d, 0x00108e5a,
+	0x00108d79, 0x00108e5a, 0x00108e5a, 0x00108e5a,
+	0x00108e5a, 0x00108e5a, 0x0201f800, 0x001005d8,
+	0x4d340000, 0x4d2c0000, 0x59326809, 0x59340400,
+	0x82000500, 0x000000ff, 0x82000c80, 0x0000000c,
+	0x02021800, 0x001005d8, 0x59303403, 0x82180d80,
+	0x00000004, 0x04020004, 0x42000000, 0x00000001,
+	0x0401f006, 0x82180d80, 0x00000000, 0x04020003,
+	0x42000000, 0x00000001, 0x4803c857, 0x0c01f804,
+	0x5c025800, 0x5c026800, 0x1c01f000, 0x00108e83,
+	0x00108f22, 0x00108e85, 0x00108eba, 0x00108e85,
+	0x00108f3f, 0x00108e85, 0x00108e8f, 0x00108e83,
+	0x00108f3f, 0x00108e83, 0x00108e9e, 0x0201f800,
+	0x001005d8, 0x59300403, 0x82000d80, 0x00000016,
+	0x0400002e, 0x82000d80, 0x00000004, 0x0400002b,
+	0x82000d80, 0x00000002, 0x04000028, 0x0401fabf,
+	0x04000079, 0x59300403, 0x82000d80, 0x00000022,
+	0x040000ae, 0x82000d80, 0x00000039, 0x040000b3,
+	0x82000d80, 0x00000035, 0x040000b0, 0x82000d80,
+	0x0000001e, 0x0400001b, 0x0401f999, 0x04000007,
+	0x0201f800, 0x00109597, 0x04020004, 0x0201f800,
+	0x00104a14, 0x0401f011, 0x59300403, 0x82000d80,
+	0x00000001, 0x04020004, 0x0201f800, 0x001049e7,
+	0x0400000a, 0x4d3c0000, 0x417a7800, 0x0201f800,
+	0x0010203c, 0x5c027800, 0x42000000, 0x0010b864,
+	0x0201f800, 0x0010aa47, 0x0201f800, 0x0010801c,
+	0x0201f000, 0x00107911, 0x0401f97d, 0x04000004,
+	0x0201f800, 0x00109597, 0x040000a9, 0x59300c03,
+	0x82040580, 0x00000016, 0x04000056, 0x82040580,
+	0x00000002, 0x04020034, 0x59a80026, 0x8c000502,
+	0x04020013, 0x0201f800, 0x0010513b, 0x04020010,
+	0x0201f800, 0x00105151, 0x04020006, 0x42000000,
+	0x00000001, 0x0201f800, 0x00105113, 0x0401f094,
+	0x4a035033, 0x00000001, 0x4202d800, 0x00000001,
+	0x0201f800, 0x001050a2, 0x0401f08d, 0x59340403,
+	0x82000580, 0x000007fc, 0x04000008, 0x59a80026,
+	0x8c00050a, 0x04020084, 0x59340212, 0x82000500,
+	0x0000ff00, 0x04000082, 0x59340412, 0x82000500,
+	0x000000ff, 0x04000010, 0x80000040, 0x48026c12,
+	0x497a6008, 0x4a026406, 0x00000007, 0x4a026206,
+	0x00000398, 0x497a6205, 0x0201f800, 0x0002075a,
+	0x04000005, 0x49366009, 0x4a026406, 0x00000001,
+	0x0401f020, 0x59300403, 0x82000d80, 0x00000002,
+	0x0402000d, 0x59340403, 0x82000580, 0x000007fe,
+	0x04020009, 0x59a80026, 0x84000540, 0x48035026,
+	0x0201f800, 0x00104237, 0x0201f800, 0x0010801c,
+	0x0401f00c, 0x0201f800, 0x0010801c, 0x4d3c0000,
+	0x417a7800, 0x0201f800, 0x0010203c, 0x5c027800,
+	0x42000000, 0x0010b864, 0x0201f800, 0x0010aa47,
+	0x0201f800, 0x00102074, 0x0201f000, 0x00107911,
+	0x42000800, 0x00000003, 0x0201f800, 0x00104571,
+	0x4a026203, 0x00000001, 0x4a026403, 0x00000002,
+	0x0201f000, 0x0010672b, 0x0401f915, 0x04020793,
+	0x0201f800, 0x00102074, 0x4d3c0000, 0x417a7800,
+	0x0201f800, 0x0010203c, 0x5c027800, 0x42000000,
+	0x0010b864, 0x0201f800, 0x0010aa47, 0x42003000,
+	0x00000018, 0x41782800, 0x42002000, 0x00000000,
+	0x4d400000, 0x4d440000, 0x59368c03, 0x42028000,
+	0x00000029, 0x0201f800, 0x0010985e, 0x5c028800,
+	0x5c028000, 0x0201f000, 0x00107911, 0x0201f800,
+	0x00104a14, 0x0401f7c8, 0x42000000, 0x0010b86d,
+	0x0201f800, 0x0010aa47, 0x0201f800, 0x00107b76,
+	0x040207c1, 0x1c01f000, 0x4d380000, 0x59327403,
+	0x0201f800, 0x001093ba, 0x5c027000, 0x02020000,
+	0x0002077d, 0x836c0580, 0x00000003, 0x04000004,
+	0x4a026206, 0x00000002, 0x1c01f000, 0x59300403,
+	0x48026416, 0x4a02621d, 0x00000001, 0x4a026403,
+	0x00000085, 0x4a026203, 0x00000009, 0x4a026406,
+	0x00000002, 0x42000800, 0x8000004b, 0x0201f000,
+	0x00020721, 0x0201f800, 0x00102074, 0x0201f800,
+	0x0010801c, 0x4d3c0000, 0x417a7800, 0x0201f800,
+	0x0010203c, 0x5c027800, 0x42000000, 0x0010b864,
+	0x0201f800, 0x0010aa47, 0x497a6008, 0x4a026406,
+	0x00000007, 0x4a026206, 0x00000398, 0x497a6205,
+	0x1c01f000, 0x42000000, 0x0010b870, 0x0201f800,
+	0x0010aa47, 0x4d340000, 0x59326809, 0x59300203,
+	0x82000c80, 0x0000000e, 0x02021800, 0x001005d8,
+	0x4803c857, 0x0c01f803, 0x5c026800, 0x1c01f000,
+	0x00108f96, 0x00108d85, 0x00108f96, 0x00108f96,
+	0x00108f96, 0x00108f96, 0x00108f96, 0x00108f96,
+	0x00108f96, 0x00108d85, 0x00108f98, 0x00108d85,
+	0x00108fa0, 0x00108f96, 0x0201f800, 0x001005d8,
+	0x4a026403, 0x0000008b, 0x4a026203, 0x0000000b,
+	0x42000800, 0x8000404b, 0x0201f000, 0x00020721,
+	0x59300a1d, 0x4d3c0000, 0x417a7800, 0x0201f800,
+	0x0010203c, 0x5c027800, 0x42003000, 0x00000011,
+	0x0201f800, 0x0010a942, 0x42000000, 0x0010b864,
+	0x0201f800, 0x0010aa47, 0x41306800, 0x0201f800,
+	0x0002075a, 0x04000008, 0x49366009, 0x4d300000,
+	0x40366000, 0x0201f800, 0x00107911, 0x5c026000,
+	0x0401f002, 0x40366000, 0x497a6008, 0x4a026406,
+	0x00000001, 0x4a026403, 0x00000001, 0x0201f800,
+	0x00103b25, 0x04000011, 0x4a026406, 0x00000004,
+	0x4a026203, 0x00000007, 0x4a026420, 0x00000001,
+	0x42003000, 0x00000004, 0x4d400000, 0x42028000,
+	0x00000029, 0x41782800, 0x0201f800, 0x0010a43e,
+	0x5c028000, 0x1c01f000, 0x42000800, 0x0000000b,
+	0x0201f800, 0x00104571, 0x4a026203, 0x00000001,
+	0x0201f000, 0x0010672b, 0x42000000, 0x0010b876,
+	0x0201f800, 0x0010aa47, 0x59300203, 0x82000c80,
+	0x0000000e, 0x02021800, 0x001005d8, 0x4803c857,
+	0x0c01f001, 0x0010900b, 0x00108ff3, 0x00108ff7,
+	0x0010900c, 0x00108ff5, 0x00108ff3, 0x00108ff3,
+	0x00108ff3, 0x00108ff3, 0x00108ff3, 0x00108ff3,
+	0x00108ff3, 0x00108ff3, 0x00108ff3, 0x0201f800,
+	0x001005d8, 0x0201f800, 0x00100e99, 0x4d2c0000,
+	0x59325808, 0x4a025a06, 0x00000006, 0x0201f800,
+	0x000202da, 0x5c025800, 0x497a6008, 0x4a02621d,
+	0x0000000a, 0x4a026403, 0x00000085, 0x4a026203,
+	0x00000009, 0x4a026406, 0x00000002, 0x42000800,
+	0x8000404b, 0x0201f000, 0x00020721, 0x1c01f000,
+	0x0201f800, 0x00106c55, 0x4df00000, 0x0401fcc7,
+	0x04020004, 0x0201f800, 0x00106e62, 0x0402000c,
+	0x0201f800, 0x001067ae, 0x04020005, 0x5c03e000,
+	0x0201f800, 0x00106c4b, 0x0401f7dd, 0x0201f800,
+	0x00106b6c, 0x02020800, 0x001005d8, 0x5c03e000,
+	0x0201f800, 0x00106c4b, 0x59300203, 0x82000d80,
+	0x00000003, 0x02000800, 0x001005d8, 0x82000c80,
+	0x0000000e, 0x02021800, 0x001005d8, 0x0c01f7ba,
+	0x4803c856, 0x59a8000e, 0x59a80867, 0x80040400,
+	0x80080480, 0x04021004, 0x82000540, 0x00000001,
+	0x1c01f000, 0x80000580, 0x1c01f000, 0x4803c856,
+	0x4c080000, 0x59301008, 0x82081500, 0xfff00000,
+	0x5c001000, 0x1c01f000, 0x4803c856, 0x4d300000,
+	0x0201f800, 0x0002075a, 0x0400000a, 0x0401f82f,
+	0x4d380000, 0x42027000, 0x0000004b, 0x0201f800,
+	0x000207a1, 0x5c027000, 0x82000540, 0x00000001,
+	0x5c026000, 0x1c01f000, 0x4803c856, 0x4d300000,
+	0x0201f800, 0x00107942, 0x0400001b, 0x0401f81f,
+	0x4d300000, 0x0201f800, 0x00106c55, 0x4d3c0000,
+	0x417a7800, 0x0201f800, 0x00106ab4, 0x0201f800,
+	0x001067fd, 0x5c027800, 0x0201f800, 0x0010a2ff,
+	0x0201f800, 0x00106c4b, 0x5c026000, 0x8d3e7d3e,
+	0x0402000b, 0x4d380000, 0x42027000, 0x0000004c,
+	0x0201f800, 0x000207a1, 0x5c027000, 0x82000540,
+	0x00000001, 0x5c026000, 0x1c01f000, 0x0201f800,
+	0x0002077d, 0x0401f7fa, 0x592c0407, 0x494a6017,
+	0x494e6018, 0x49366009, 0x492e6008, 0x4a026406,
+	0x00000003, 0x800000c2, 0x800008c4, 0x80040400,
+	0x48026206, 0x1c01f000, 0x493bc857, 0x4d300000,
+	0x0201f800, 0x0002075a, 0x0400000d, 0x0401ffef,
+	0x4d400000, 0x42028000, 0x00000005, 0x0401f80d,
+	0x5c028000, 0x8d3e7d3e, 0x04020007, 0x0201f800,
+	0x000207a1, 0x82000540, 0x00000001, 0x5c026000,
+	0x1c01f000, 0x0201f800, 0x0002077d, 0x0401f7fa,
+	0x4803c856, 0x0201f800, 0x00106c55, 0x4d3c0000,
+	0x4d440000, 0x59368c03, 0x42027800, 0x00000001,
+	0x0201f800, 0x001069b6, 0x0201f800, 0x0010692e,
+	0x0201f800, 0x001067fd, 0x0201f800, 0x0010a2ff,
+	0x5c028800, 0x5c027800, 0x0201f000, 0x00106c4b,
+	0x4803c856, 0x4d300000, 0x0201f800, 0x0002075a,
+	0x0400000f, 0x481a601c, 0x48ee6021, 0x49366009,
+	0x4a026406, 0x00000001, 0x492e6008, 0x4d380000,
+	0x42027000, 0x0000001f, 0x0201f800, 0x000207a1,
+	0x5c027000, 0x82000540, 0x00000001, 0x5c026000,
+	0x1c01f000, 0x4803c856, 0x4d300000, 0x0201f800,
+	0x0002075a, 0x0400000e, 0x48ee6021, 0x49366009,
+	0x4a026406, 0x00000001, 0x492e6008, 0x4d380000,
+	0x42027000, 0x00000055, 0x0201f800, 0x000207a1,
+	0x5c027000, 0x82000540, 0x00000001, 0x5c026000,
+	0x1c01f000, 0x4803c856, 0x4d300000, 0x0201f800,
+	0x0002075a, 0x0400000f, 0x481a601c, 0x48ee6021,
+	0x49366009, 0x4a026406, 0x00000001, 0x492e6008,
+	0x4d380000, 0x42027000, 0x0000003d, 0x0201f800,
+	0x000207a1, 0x5c027000, 0x82000540, 0x00000001,
+	0x5c026000, 0x1c01f000, 0x4803c856, 0x4d300000,
+	0x0201f800, 0x00107942, 0x04000014, 0x49366009,
+	0x492fc857, 0x4933c857, 0x592c0404, 0x8c00051e,
+	0x04000003, 0x48efc857, 0x48ee6021, 0x4a026406,
+	0x00000001, 0x492e6008, 0x4d380000, 0x42027000,
+	0x00000000, 0x0201f800, 0x000207a1, 0x5c027000,
+	0x82000540, 0x00000001, 0x5c026000, 0x1c01f000,
+	0x4803c856, 0x4d300000, 0x0201f800, 0x0002075a,
+	0x0400000f, 0x48ee6021, 0x481a601c, 0x49366009,
+	0x4a026406, 0x00000001, 0x492e6008, 0x4d380000,
+	0x42027000, 0x00000044, 0x0201f800, 0x000207a1,
+	0x5c027000, 0x82000540, 0x00000001, 0x5c026000,
+	0x1c01f000, 0x4803c856, 0x4d300000, 0x0201f800,
+	0x0002075a, 0x0400000f, 0x481a601c, 0x48ee6021,
+	0x49366009, 0x4a026406, 0x00000001, 0x492e6008,
+	0x4d380000, 0x42027000, 0x00000049, 0x0201f800,
+	0x000207a1, 0x5c027000, 0x82000540, 0x00000001,
+	0x5c026000, 0x1c01f000, 0x59300009, 0x80001540,
+	0x02000800, 0x001005d8, 0x5808040b, 0x4803c856,
+	0x80000040, 0x04001002, 0x4800140b, 0x1c01f000,
+	0x4803c856, 0x59300403, 0x82000d80, 0x00000002,
+	0x04000015, 0x82000d80, 0x00000003, 0x04000012,
+	0x82000d80, 0x00000004, 0x0400000f, 0x82000d80,
+	0x00000008, 0x0400000c, 0x82000d80, 0x0000000a,
+	0x04000009, 0x599c0819, 0x8c040d0e, 0x04000004,
+	0x82000d80, 0x00000000, 0x04000003, 0x82000540,
+	0x00000001, 0x1c01f000, 0x4803c856, 0x4c000000,
+	0x4d2c0000, 0x59300406, 0x82000580, 0x00000004,
+	0x0400001d, 0x59300008, 0x80025d40, 0x800001c0,
+	0x04000019, 0x0201f800, 0x00109597, 0x04000014,
+	0x59300406, 0x82004580, 0x00000010, 0x04000010,
+	0x82004580, 0x00000011, 0x0400000d, 0x82004580,
+	0x00000003, 0x0400000c, 0x82004580, 0x00000002,
+	0x04000009, 0x82004580, 0x0000000a, 0x04000006,
+	0x592c0404, 0x8c00051e, 0x04000003, 0x80000580,
+	0x0401f003, 0x82000540, 0x00000001, 0x5c025800,
+	0x5c000000, 0x1c01f000, 0x4803c856, 0x4d300000,
+	0x0201f800, 0x00107942, 0x04000013, 0x49366009,
+	0x48ee6021, 0x4a026406, 0x00000001, 0x492e6008,
+	0x4d3c0000, 0x417a7800, 0x0201f800, 0x0010203c,
+	0x5c027800, 0x4d380000, 0x42027000, 0x00000028,
+	0x0201f800, 0x000207a1, 0x5c027000, 0x82000540,
+	0x00000001, 0x5c026000, 0x1c01f000, 0x4803c856,
+	0x83380580, 0x00000015, 0x0402000d, 0x59a80016,
+	0x82000580, 0x00000074, 0x04020009, 0x0201f800,
+	0x0010462a, 0x4a026203, 0x00000001, 0x4a026403,
+	0x00000029, 0x0201f000, 0x0010672b, 0x0201f800,
+	0x0010801c, 0x0201f000, 0x0002077d, 0x4803c856,
+	0x83380580, 0x00000016, 0x04020007, 0x42000800,
+	0x00000004, 0x0201f800, 0x00104571, 0x0201f000,
+	0x00107b38, 0x83380580, 0x00000015, 0x04020013,
+	0x59a80016, 0x82000580, 0x00000014, 0x0402000f,
+	0x0201f800, 0x0010468d, 0x0201f800, 0x0010846f,
+	0x0402000a, 0x59340404, 0x80000540, 0x04000007,
+	0x42000800, 0x00000006, 0x0201f800, 0x00104571,
+	0x0201f000, 0x00107b38, 0x0201f800, 0x0010801c,
+	0x0201f000, 0x0002077d, 0x4803c856, 0x592c0206,
+	0x82000580, 0x00000005, 0x04000002, 0x1c01f000,
+	0x4803c856, 0x592c0208, 0x8400054a, 0x48025a08,
+	0x1c01f000, 0x497a6205, 0x497a6008, 0x4a026203,
+	0x00000001, 0x4a026403, 0x00000050, 0x42000800,
+	0x80000043, 0x0201f000, 0x00020721, 0x4933c857,
+	0x4d340000, 0x59326809, 0x59340200, 0x8c00050e,
+	0x04000006, 0x59300406, 0x82000c80, 0x00000012,
+	0x04021004, 0x0c01f806, 0x5c026800, 0x1c01f000,
+	0x0201f800, 0x00108d7c, 0x0401f7fc, 0x00108d7c,
+	0x001091fd, 0x00109201, 0x00109204, 0x0010a49b,
+	0x0010a4b8, 0x0010a4bc, 0x00108d7c, 0x00108d7c,
+	0x00108d7c, 0x00108d7c, 0x00108d7c, 0x00108d7c,
+	0x00108d7c, 0x00108d7c, 0x00108d7c, 0x00108d7c,
+	0x00108d7c, 0x4803c856, 0x40000000, 0x40000000,
+	0x1c01f000, 0x40000000, 0x40000000, 0x1c01f000,
+	0x5930001c, 0x4803c857, 0x59300414, 0x4933c857,
+	0x4803c857, 0x8c000502, 0x04000005, 0x84000502,
+	0x84000540, 0x48026414, 0x1c01f000, 0x42000000,
+	0xd0000000, 0x41300800, 0x0201f800, 0x00100b94,
+	0x0401f80a, 0x04020008, 0x59a80037, 0x82000400,
+	0x0000000a, 0x48026205, 0x59300414, 0x84000542,
+	0x48026414, 0x1c01f000, 0x4933c857, 0x4d340000,
+	0x59326809, 0x59340200, 0x8c00050e, 0x02000800,
+	0x001005d8, 0x5930001c, 0x80000540, 0x0402002f,
+	0x59a80021, 0x80000540, 0x0402002a, 0x4d1c0000,
+	0x41323800, 0x0201f800, 0x0002075a, 0x04000023,
+	0x4932381c, 0x591c0414, 0x84000542, 0x48023c14,
+	0x49366009, 0x591c0406, 0x82000580, 0x00000003,
+	0x04000006, 0x591c0202, 0x48026419, 0x591c0402,
+	0x48026219, 0x0401f005, 0x591c0202, 0x48026219,
+	0x591c0402, 0x48026419, 0x491e601e, 0x4a026406,
+	0x00000001, 0x4a026403, 0x00000035, 0x4a026203,
+	0x00000001, 0x42000800, 0x80000040, 0x0201f800,
+	0x00020721, 0x411e6000, 0x5c023800, 0x80000580,
+	0x5c026800, 0x1c01f000, 0x411e6000, 0x5c023800,
+	0x59a80039, 0x48026205, 0x82000540, 0x00000001,
+	0x0401f7f8, 0x4933c857, 0x4d2c0000, 0x4932381c,
+	0x4a026202, 0x0000ffff, 0x591e5808, 0x591c0007,
+	0x8c00051e, 0x04000005, 0x8400051e, 0x48023807,
+	0x497a5c09, 0x0401f014, 0x592c0408, 0x8c000518,
+	0x04000011, 0x84000518, 0x48025c08, 0x4a025c09,
+	0x00000001, 0x0401fb2f, 0x497a5c09, 0x592c0408,
+	0x8c000512, 0x04000008, 0x4d2c0000, 0x84000512,
+	0x48025c08, 0x592e5809, 0x0201f800, 0x001007fd,
+	0x5c025800, 0x59a80039, 0x48026205, 0x591c0214,
+	0x48026216, 0x82000d80, 0x00000001, 0x04000008,
+	0x4a023a03, 0x00000002, 0x82000580, 0x00000005,
+	0x04000008, 0x497a6015, 0x0401f01e, 0x591c0007,
+	0x84000540, 0x48023807, 0x4a023a03, 0x00000004,
+	0x591c0414, 0x4803c857, 0x8400051c, 0x84000554,
+	0x48023c14, 0x592c000f, 0x40001000, 0x591c0816,
+	0x80040480, 0x040217f0, 0x591c0016, 0x82000500,
+	0xfffffffc, 0x48026015, 0x48023816, 0x591c0a14,
+	0x4807c857, 0x82040d80, 0x00000005, 0x04020005,
+	0x480bc857, 0x4803c857, 0x4a023812, 0xffffffff,
+	0x591c0402, 0x48026419, 0x591c0202, 0x48026219,
+	0x591e6809, 0x49366009, 0x4a026406, 0x00000001,
+	0x4a026403, 0x00000039, 0x4a026203, 0x00000001,
+	0x42000800, 0x80000040, 0x0201f800, 0x00020721,
+	0x5c025800, 0x1c01f000, 0x4933c857, 0x59300414,
+	0x8c000514, 0x04000015, 0x8c00051c, 0x04020012,
+	0x59300016, 0x80100480, 0x04001006, 0x04000005,
+	0x59300414, 0x84000514, 0x8400055c, 0x0401f009,
+	0x48126016, 0x48126012, 0x40100000, 0x592c180f,
+	0x800c0480, 0x48026011, 0x59300414, 0x84000514,
+	0x48026414, 0x1c01f000, 0x4933c857, 0x8c00051c,
+	0x04020006, 0x59300012, 0x48026016, 0x59300414,
+	0x8400055c, 0x48026414, 0x1c01f000, 0x59300c03,
+	0x4933c857, 0x4807c857, 0x82040480, 0x00000034,
+	0x04001006, 0x82040480, 0x0000003c, 0x04021003,
+	0x80000580, 0x1c01f000, 0x82000540, 0x00000001,
+	0x0401f7fd, 0x41780800, 0x59a81035, 0x42000000,
+	0x00000032, 0x0201f800, 0x001066a0, 0x800811c0,
+	0x04020003, 0x42001000, 0x00000014, 0x480b5037,
+	0x59a81036, 0x480b502d, 0x41780800, 0x42000000,
+	0x00000064, 0x0201f800, 0x001066a0, 0x800811c0,
+	0x04020003, 0x42001000, 0x00000014, 0x480b5038,
+	0x82081400, 0x0000000a, 0x480b5039, 0x42000800,
+	0x00000001, 0x0201f800, 0x00106c78, 0x42000000,
+	0x30000000, 0x40080800, 0x0201f800, 0x00100b68,
+	0x42000800, 0x00000003, 0x59a81010, 0x0201f800,
+	0x00106c78, 0x0201f000, 0x00104906, 0x4a035037,
+	0x00000028, 0x4a035038, 0x00000014, 0x4a03502d,
+	0x000007d0, 0x42001000, 0x0000001e, 0x480b5039,
+	0x42000800, 0x00000001, 0x0201f800, 0x00106c78,
+	0x42000000, 0x30000000, 0x40080800, 0x0201f800,
+	0x00100b68, 0x42000800, 0x00000003, 0x59a81010,
+	0x0201f000, 0x00106c78, 0x4933c857, 0x4d2c0000,
+	0x59300403, 0x82000580, 0x0000003e, 0x04020005,
+	0x59325817, 0x812e59c0, 0x02020800, 0x001007f4,
+	0x5c025800, 0x1c01f000, 0x4937c857, 0x4d300000,
+	0x0201f800, 0x0002075a, 0x04000011, 0x49366009,
+	0x4a026406, 0x00000001, 0x492e6008, 0x42000800,
+	0x00000009, 0x0201f800, 0x00104571, 0x4d380000,
+	0x42027000, 0x00000033, 0x0201f800, 0x000207a1,
+	0x5c027000, 0x82000540, 0x00000001, 0x5c026000,
+	0x1c01f000, 0x4933c857, 0x4d2c0000, 0x4c580000,
+	0x4d3c0000, 0x59325808, 0x83380580, 0x00000015,
+	0x04020022, 0x59a8b016, 0x82580c80, 0x00000019,
+	0x04001003, 0x4200b000, 0x00000018, 0x8058b104,
+	0x0401fa07, 0x80000580, 0x0401fa17, 0x832cac00,
+	0x00000009, 0x83cca400, 0x00000006, 0x0201f800,
+	0x0010ab17, 0x42027800, 0x00000001, 0x592c100a,
+	0x8c081518, 0x04020006, 0x59a80010, 0x592c100d,
+	0x80080580, 0x04020006, 0x417a7800, 0x59301009,
+	0x58081403, 0x0201f800, 0x001020a1, 0x0201f800,
+	0x00107b38, 0x0401f008, 0x4200b000, 0x00000002,
+	0x0401fa09, 0x0201f800, 0x0010801c, 0x0201f800,
+	0x0002077d, 0x5c027800, 0x5c00b000, 0x5c025800,
+	0x1c01f000, 0x4933c856, 0x49366009, 0x4a026406,
+	0x00000001, 0x492e6008, 0x4d380000, 0x42027000,
+	0x0000004d, 0x0201f800, 0x000207a1, 0x5c027000,
+	0x82000540, 0x00000001, 0x1c01f000, 0x4803c856,
+	0x4d2c0000, 0x83380580, 0x00000015, 0x04020027,
+	0x59a80816, 0x59325808, 0x5930040b, 0x800000c4,
+	0x80040580, 0x04020021, 0x4c500000, 0x4c540000,
+	0x4c580000, 0x83cca400, 0x00000006, 0x4050a800,
+	0x5930b40b, 0x0201f800, 0x0010ab28, 0x83cca400,
+	0x00000006, 0x592cb205, 0x832cac00, 0x00000006,
+	0x0201f800, 0x0010ab17, 0x592e5801, 0x812e59c0,
+	0x040207f9, 0x5931d821, 0x58ef400b, 0x58ee580d,
+	0x4a025a04, 0x00000103, 0x58ec0009, 0x0801f800,
+	0x59300402, 0x5c00b000, 0x5c00a800, 0x5c00a000,
+	0x5c025800, 0x1c01f000, 0x0201f800, 0x0010801c,
+	0x5c025800, 0x1c01f000, 0x4933c857, 0x83380580,
+	0x00000035, 0x04000005, 0x59301419, 0x0401f851,
+	0x04000027, 0x0401f006, 0x4d300000, 0x5932601e,
+	0x0401f856, 0x5c026000, 0x04000020, 0x591c0c06,
+	0x82040580, 0x00000003, 0x04000004, 0x82040580,
+	0x00000006, 0x0402001c, 0x591c0c02, 0x59300419,
+	0x80040580, 0x04000009, 0x59300219, 0x80040580,
+	0x04020015, 0x591c0a02, 0x59300419, 0x80040580,
+	0x04020011, 0x0401f009, 0x59300a19, 0x82040580,
+	0x0000ffff, 0x04000005, 0x591c0202, 0x59300a19,
+	0x80040580, 0x04020008, 0x591c0009, 0x59300809,
+	0x80040580, 0x1c01f000, 0x417a3800, 0x82000540,
+	0x00000001, 0x1c01f000, 0x4803c856, 0x59b800e4,
+	0x8c000538, 0x02020800, 0x001005d8, 0x42000800,
+	0x0000012c, 0x4a0370e4, 0x20000000, 0x59b800e4,
+	0x80040840, 0x02000800, 0x001005d8, 0x8c00053c,
+	0x040207f9, 0x4a0370e4, 0x30000000, 0x40000000,
+	0x40000000, 0x40000000, 0x59b800e4, 0x8c00053c,
+	0x040207f1, 0x1c01f000, 0x4803c856, 0x4a0370e4,
+	0x20000000, 0x40000000, 0x59b800e4, 0x8c000538,
+	0x040207fb, 0x1c01f000, 0x59300807, 0x8c040d1e,
+	0x592c0c08, 0x04020002, 0x8c040d18, 0x1c01f000,
+	0x0401fc1c, 0x04000008, 0x42000800, 0x00000024,
+	0x0201f800, 0x00106681, 0x82063c00, 0x0010d1c0,
+	0x491fc857, 0x1c01f000, 0x83300480, 0x0010d1c0,
+	0x0400100a, 0x59a8000b, 0x81300480, 0x04021007,
+	0x59301402, 0x0401ffef, 0x04000007, 0x411c0000,
+	0x81300580, 0x04000003, 0x81780500, 0x0401f002,
+	0x81300540, 0x1c01f000, 0x4947c857, 0x4d300000,
+	0x0201f800, 0x00020245, 0x0402000a, 0x42026000,
+	0x0010bde9, 0x49366009, 0x492e6008, 0x0201f800,
+	0x0010203c, 0x80000580, 0x5c026000, 0x1c01f000,
+	0x82000540, 0x00000001, 0x0401f7fc, 0x4933c857,
+	0x0201f800, 0x00109037, 0x02000800, 0x001005d8,
+	0x4d2c0000, 0x4d340000, 0x4d440000, 0x4c580000,
+	0x59325808, 0x59326809, 0x49425a06, 0x0201f800,
+	0x00105755, 0x592e8c06, 0x592c4207, 0x82200500,
+	0x0000000f, 0x0c01f806, 0x5c00b000, 0x5c028800,
+	0x5c026800, 0x5c025800, 0x1c01f000, 0x00109466,
+	0x00109488, 0x0010948f, 0x00109493, 0x0010949c,
+	0x00109463, 0x00109463, 0x00109463, 0x001094a0,
+	0x001094ac, 0x001094ac, 0x00109463, 0x00109463,
+	0x00109463, 0x00109463, 0x00109463, 0x4803c857,
+	0x0201f800, 0x001005d8, 0x814281c0, 0x04020012,
+	0x41785800, 0x592c0404, 0x8c00051c, 0x04020002,
+	0x59345c05, 0x442c2800, 0x59340008, 0x48002802,
+	0x59340009, 0x48002801, 0x59340006, 0x48002804,
+	0x59340007, 0x48002803, 0x4200b000, 0x0000000b,
+	0x0401f037, 0x592c0207, 0x8c00051e, 0x4200b000,
+	0x00000002, 0x04020032, 0x8204b540, 0x00000000,
+	0x0400002f, 0x44042800, 0x59326809, 0x59340400,
+	0x48002801, 0x4200b000, 0x00000002, 0x0401f028,
+	0x814281c0, 0x04020030, 0x59345c05, 0x442c2800,
+	0x4200b000, 0x00000001, 0x0401f021, 0x8340b540,
+	0x00000000, 0x0400001e, 0x0401f027, 0x814281c0,
+	0x04020025, 0x59340200, 0x44002800, 0x59340001,
+	0x48002801, 0x4200b000, 0x00000002, 0x0401f014,
+	0x8340b540, 0x00000000, 0x0402001b, 0x0401f010,
+	0x8340b540, 0x00000000, 0x0400000d, 0x0201f800,
+	0x00104a1f, 0x04000014, 0x8c20450e, 0x04000002,
+	0x497a6009, 0x4178b000, 0x497a5a06, 0x0401f004,
+	0x8340b540, 0x00000000, 0x0402000b, 0x592c0404,
+	0x8400051c, 0x48025c04, 0x592c0207, 0x8400051e,
+	0x48025a07, 0x0401f8aa, 0x497a6008, 0x0201f000,
+	0x000202da, 0x592c0207, 0x8c00051e, 0x4200b000,
+	0x00000002, 0x040207f2, 0x8204b540, 0x00000000,
+	0x040007ef, 0x44042800, 0x4200b000, 0x00000001,
+	0x0401f7eb, 0x4937c857, 0x4d300000, 0x0201f800,
+	0x0002075a, 0x04000011, 0x49366009, 0x4a026406,
+	0x00000001, 0x492e6008, 0x42000800, 0x0000000b,
+	0x0201f800, 0x00104571, 0x4d380000, 0x42027000,
+	0x00000043, 0x0201f800, 0x000207a1, 0x5c027000,
+	0x82000540, 0x00000001, 0x5c026000, 0x1c01f000,
+	0x4937c857, 0x4d2c0000, 0x59325808, 0x83380580,
+	0x00000015, 0x04020025, 0x59a80016, 0x82000580,
+	0x00000004, 0x04020021, 0x59a80010, 0x592c1009,
+	0x80080580, 0x04020010, 0x4d440000, 0x592e8c06,
+	0x592c0207, 0x4803c856, 0x82000500, 0x00000080,
+	0x84000548, 0x4d3c0000, 0x42027800, 0x00001000,
+	0x0201f800, 0x001049bb, 0x5c027800, 0x5c028800,
+	0x0401f004, 0x4803c856, 0x0201f800, 0x00104a1f,
+	0x0201f800, 0x00109037, 0x04000017, 0x4d400000,
+	0x42028000, 0x00000000, 0x41780800, 0x0401ff38,
+	0x5c028000, 0x0401f00e, 0x0201f800, 0x00104a1f,
+	0x040207f4, 0x0201f800, 0x00109037, 0x0400000a,
+	0x4c580000, 0x4200b000, 0x00000002, 0x0401f86e,
+	0x5c00b000, 0x0201f800, 0x0010801c, 0x0201f800,
+	0x0002077d, 0x5c025800, 0x1c01f000, 0x4937c857,
+	0x4d300000, 0x0201f800, 0x0002075a, 0x04000012,
+	0x49366009, 0x4a026406, 0x00000001, 0x4d3c0000,
+	0x4d380000, 0x417a7800, 0x0201f800, 0x00104567,
+	0x492e6008, 0x42027000, 0x00000004, 0x0201f800,
+	0x000207a1, 0x5c027000, 0x5c027800, 0x82000540,
+	0x00000001, 0x5c026000, 0x1c01f000, 0x4937c857,
+	0x4d300000, 0x0201f800, 0x00107942, 0x0400000d,
+	0x49366009, 0x4a026406, 0x00000001, 0x492e6008,
+	0x4d380000, 0x42027000, 0x00000051, 0x0201f800,
+	0x000207a1, 0x5c027000, 0x82000540, 0x00000001,
+	0x5c026000, 0x1c01f000, 0x4933c857, 0x4c580000,
+	0x59325808, 0x83383580, 0x00000015, 0x04020011,
+	0x592c0008, 0x82000500, 0x00ffffff, 0x0402000a,
+	0x0201f800, 0x00105755, 0x59cc0000, 0x82000500,
+	0x00ffffff, 0x44002800, 0x4200b000, 0x00000001,
+	0x0401f80b, 0x0201f800, 0x00107b38, 0x0401f006,
+	0x4200b000, 0x00000002, 0x0401f823, 0x0201f800,
+	0x0010801c, 0x5c00b000, 0x1c01f000, 0x492fc857,
+	0x4c580000, 0x4c000000, 0x8058b1c0, 0x0400000b,
+	0x82580500, 0xfffffff0, 0x02020800, 0x001005d8,
+	0x8058b0d0, 0x592c0408, 0x82000500, 0xfffff0ff,
+	0x80580540, 0x48025c08, 0x5c000000, 0x5c00b000,
+	0x1c01f000, 0x492fc857, 0x4c000000, 0x4c040000,
+	0x800000d8, 0x592c0c08, 0x82040d00, 0xffff0fff,
+	0x80040540, 0x48025c08, 0x5c000800, 0x5c000000,
+	0x1c01f000, 0x4933c857, 0x4d2c0000, 0x59325808,
+	0x592c0207, 0x8400055e, 0x48025a07, 0x4c500000,
+	0x4c540000, 0x4c580000, 0x0401ffd9, 0x0201f800,
+	0x00105755, 0x46002800, 0x00000018, 0x80142800,
+	0x8058b040, 0x83cca400, 0x00000007, 0x4014a800,
+	0x0201f800, 0x0010ab17, 0x5c00b000, 0x5c00a800,
+	0x5c00a000, 0x5c025800, 0x1c01f000, 0x59325808,
+	0x592c0204, 0x82000580, 0x00000152, 0x1c01f000,
+	0x5930001f, 0x80000540, 0x02020800, 0x00100d56,
+	0x1c01f000, 0x4d2c0000, 0x59325808, 0x59300203,
+	0x4933c857, 0x492fc857, 0x493bc857, 0x4803c857,
+	0x82003480, 0x0000000e, 0x02021800, 0x001005d8,
+	0x0c01f803, 0x5c025800, 0x1c01f000, 0x001095bd,
+	0x001095c8, 0x00109603, 0x001095bd, 0x001095bd,
+	0x001095bd, 0x001095bd, 0x001095bd, 0x001095bf,
+	0x001095bd, 0x001095bd, 0x001095bd, 0x001095bd,
+	0x001095bd, 0x0201f800, 0x001005d8, 0x83383480,
+	0x00000056, 0x02021800, 0x001005d8, 0x493a6403,
+	0x4a026203, 0x00000001, 0x0201f000, 0x0010672b,
+	0x83380580, 0x00000013, 0x0402000f, 0x592c000c,
+	0x800001c0, 0x04000006, 0x4a026203, 0x00000002,
+	0x59a80037, 0x48026206, 0x1c01f000, 0x4a025a06,
+	0x00000000, 0x0201f800, 0x000202da, 0x0201f000,
+	0x0002077d, 0x83380580, 0x00000027, 0x0400001a,
+	0x83380580, 0x00000014, 0x04000012, 0x83380580,
+	0x00000015, 0x04000005, 0x83380580, 0x00000016,
+	0x02020800, 0x001005d8, 0x0201f800, 0x00106f60,
+	0x02020000, 0x00107974, 0x59300203, 0x82000580,
+	0x00000002, 0x02020800, 0x001005d8, 0x0401f014,
+	0x0201f800, 0x00106bbf, 0x4a02580e, 0x00000011,
+	0x0401f005, 0x0201f800, 0x00106bbf, 0x4a02580e,
+	0x00000010, 0x4a025a06, 0x00000031, 0x4a02580d,
+	0x00000004, 0x0201f800, 0x000202da, 0x0201f800,
+	0x00104c19, 0x0201f000, 0x00107911, 0x59341400,
+	0x82081d00, 0x000000ff, 0x59300c03, 0x480bc857,
+	0x4807c857, 0x82040580, 0x00000053, 0x0400002e,
+	0x82040580, 0x00000002, 0x04000016, 0x82040580,
+	0x00000001, 0x04000017, 0x82040580, 0x00000003,
+	0x0400001c, 0x82040580, 0x00000005, 0x0400001d,
+	0x82040580, 0x00000033, 0x0400001a, 0x82040580,
+	0x00000000, 0x0400001b, 0x82040580, 0x00000004,
+	0x02020800, 0x001005d8, 0x0401f8a1, 0x0401f016,
+	0x820c0580, 0x00000003, 0x0400084c, 0x0401f012,
+	0x820c0580, 0x0000000b, 0x0402000f, 0x42000800,
+	0x00000007, 0x0201f800, 0x00104571, 0x0401f00a,
+	0x820c0580, 0x00000005, 0x04000864, 0x0401f006,
+	0x820c0580, 0x00000009, 0x04000889, 0x0401f002,
+	0x0401f893, 0x4a026403, 0x00000052, 0x59a81016,
+	0x592c040b, 0x8c000500, 0x04000003, 0x42001000,
+	0x00000008, 0x592c040b, 0x8c000516, 0x04000003,
+	0x82081400, 0x00000018, 0x592c000c, 0x497a580d,
+	0x497a580e, 0x80080c80, 0x04000009, 0x04001005,
+	0x4a025a06, 0x00000007, 0x40001000, 0x0401f006,
+	0x4a025a06, 0x00000015, 0x0401f003, 0x4a025a06,
+	0x00000000, 0x480a580c, 0x82081400, 0x00000003,
+	0x80081104, 0x0201f800, 0x00107ab5, 0x04000010,
+	0x592c1001, 0x480a600b, 0x58080800, 0x82080400,
+	0x00000002, 0x592c1011, 0x592c1812, 0x42003000,
+	0x00000000, 0x42002000, 0x00101200, 0x0201f800,
+	0x00107c32, 0x04000002, 0x1c01f000, 0x4a025a06,
+	0x0000002c, 0x497a580c, 0x0201f800, 0x000202da,
+	0x0201f000, 0x0002077d, 0x83380580, 0x00000015,
+	0x0402000a, 0x59a80005, 0x8c000514, 0x0402000b,
+	0x0201f800, 0x0010462a, 0x42000800, 0x00000004,
+	0x0201f000, 0x00104571, 0x42000800, 0x00000007,
+	0x0201f000, 0x00104571, 0x0201f800, 0x0010513b,
+	0x42001000, 0x00000010, 0x04020009, 0x59340002,
+	0x82000500, 0x00ff0000, 0x82000580, 0x00ff0000,
+	0x040007ec, 0x42001000, 0x00000008, 0x0201f800,
+	0x00104c6d, 0x040007e7, 0x592c040b, 0x84000540,
+	0x48025c0b, 0x0401f7e9, 0x83380580, 0x00000015,
+	0x0402000f, 0x59a80005, 0x8c000514, 0x04020010,
+	0x0201f800, 0x0010468d, 0x4d3c0000, 0x417a7800,
+	0x0201f800, 0x00104567, 0x5c027800, 0x42000800,
+	0x00000006, 0x0201f000, 0x00104571, 0x42000800,
+	0x00000004, 0x0201f000, 0x00104571, 0x0201f800,
+	0x0010513b, 0x42001000, 0x00000010, 0x04020009,
+	0x59340002, 0x82000500, 0x00ff0000, 0x82000580,
+	0x00ff0000, 0x040007e7, 0x42001000, 0x00000008,
+	0x0201f800, 0x00104c6d, 0x040007e2, 0x592c040b,
+	0x84000540, 0x48025c0b, 0x0401f7e9, 0x42000800,
+	0x00000004, 0x0201f000, 0x00104571, 0x83380580,
+	0x00000015, 0x04020005, 0x0201f800, 0x0010a2c8,
+	0x02000800, 0x001048c1, 0x1c01f000, 0x83380580,
+	0x00000015, 0x0402001d, 0x4c580000, 0x83cc1400,
+	0x00000008, 0x4200b000, 0x00000002, 0x83341c00,
+	0x00000006, 0x0201f800, 0x0010855a, 0x04020012,
+	0x83cc1400, 0x0000000a, 0x4200b000, 0x00000002,
+	0x83341c00, 0x00000008, 0x0201f800, 0x0010855a,
+	0x04020009, 0x59342200, 0x59cc1007, 0x800811c0,
+	0x04000003, 0x480a6801, 0x84102542, 0x8410251a,
+	0x48126a00, 0x5c00b000, 0x1c01f000, 0x42000000,
+	0x0010b87b, 0x0201f800, 0x0010aa47, 0x0201f800,
+	0x00106c55, 0x59300203, 0x4933c857, 0x4803c857,
+	0x82000c80, 0x0000000e, 0x02021800, 0x001005d8,
+	0x0c01f803, 0x0201f000, 0x00106c4b, 0x0010970b,
+	0x0010971a, 0x0010970c, 0x00109709, 0x00109709,
+	0x00109709, 0x00109709, 0x00109709, 0x00109709,
+	0x00109709, 0x00109709, 0x00109709, 0x00109709,
+	0x00109709, 0x0201f800, 0x001005d8, 0x1c01f000,
+	0x59300403, 0x82000580, 0x00000052, 0x02000000,
+	0x00108d85, 0x0201f800, 0x00104c19, 0x59325808,
+	0x4a025a06, 0x00000006, 0x0201f800, 0x000202da,
+	0x0201f000, 0x00107911, 0x59301804, 0x840c0520,
+	0x48026004, 0x598c000d, 0x81300580, 0x04020010,
+	0x8c0c1d20, 0x04020010, 0x42001000, 0x0010b7f6,
+	0x50081000, 0x58080002, 0x82000580, 0x00000100,
+	0x0400000e, 0x5808000c, 0x81300580, 0x02020800,
+	0x001005d8, 0x4978100c, 0x0401f003, 0x8c0c1d20,
+	0x040207dc, 0x0201f800, 0x001068d3, 0x040007d9,
+	0x0201f800, 0x001005d8, 0x0201f800, 0x00106e8e,
+	0x040007f9, 0x59300203, 0x82000c80, 0x0000000e,
+	0x02021800, 0x001005d8, 0x0c01f7bd, 0x4933c857,
+	0x4c500000, 0x4c540000, 0x4c580000, 0x592c0c07,
+	0x4806580a, 0x59cc0809, 0x48065807, 0x59cc0a08,
+	0x4806580b, 0x59c80817, 0x82040500, 0x000003ff,
+	0x800010c4, 0x8c040d14, 0x04000005, 0x59cc0002,
+	0x82000500, 0x00000003, 0x80081480, 0x82080480,
+	0x000000f1, 0x02021800, 0x001005d8, 0x480a621a,
+	0x412c0800, 0x0201f800, 0x001007d3, 0x02000800,
+	0x001005d8, 0x492c0809, 0x58040408, 0x84000552,
+	0x84000540, 0x48000c08, 0x82081400, 0x00000003,
+	0x80081104, 0x83cca400, 0x00000006, 0x832cac00,
+	0x00000004, 0x42000800, 0x00000010, 0x82080480,
+	0x00000010, 0x04021003, 0x40080800, 0x80000580,
+	0x4004b000, 0x4c000000, 0x0201f800, 0x0010ab28,
+	0x5c000000, 0x800001c0, 0x0400000d, 0x412c1000,
+	0x4c000000, 0x0201f800, 0x001007d3, 0x02000800,
+	0x001005d8, 0x492c1001, 0x832cac00, 0x00000004,
+	0x5c000000, 0x40001000, 0x0401f7e9, 0x5c00b000,
+	0x5c00a800, 0x5c00a000, 0x1c01f000, 0x4933c857,
+	0x4d2c0000, 0x4c380000, 0x59325808, 0x5930021a,
+	0x48025a08, 0x59301011, 0x800811c0, 0x04020008,
+	0x4a025a06, 0x00000000, 0x592c000b, 0x82000500,
+	0x00000c00, 0x0400000b, 0x0401f00b, 0x8c08153e,
+	0x04000006, 0x4a025a06, 0x00000007, 0x80081080,
+	0x80081000, 0x0401f003, 0x4a025a06, 0x00000015,
+	0x480a5807, 0x42000000, 0x0010bed9, 0x50007000,
+	0x5838000b, 0x80000540, 0x04020008, 0x4930700c,
+	0x4930700b, 0x58380002, 0x82000580, 0x00000000,
+	0x04020809, 0x0401f005, 0x82001400, 0x00000000,
+	0x45301000, 0x4930700b, 0x5c007000, 0x5c025800,
+	0x1c01f000, 0x4933c857, 0x592c0009, 0x40001000,
+	0x4800700a, 0x82080400, 0x00000004, 0x48007003,
+	0x592c000d, 0x592c100e, 0x48007007, 0x48087008,
+	0x592c000a, 0x592c1208, 0x80080c80, 0x04001002,
+	0x40001000, 0x82081400, 0x00000003, 0x80081104,
+	0x82080480, 0x00000010, 0x04021003, 0x80000580,
+	0x0401f003, 0x42001000, 0x00000010, 0x4800700d,
+	0x48087004, 0x800810c4, 0x48087005, 0x40381000,
+	0x0201f800, 0x00100858, 0x1c01f000, 0x4d2c0000,
+	0x0201f800, 0x001007d3, 0x02000800, 0x001005d8,
+	0x42000800, 0x0010bed9, 0x452c0800, 0x497a580b,
+	0x497a580c, 0x497a580d, 0x4a025809, 0x001097ea,
+	0x4a025802, 0x00000100, 0x4a025801, 0x00000000,
+	0x5c025800, 0x1c01f000, 0x4833c857, 0x4d300000,
+	0x4d2c0000, 0x4c5c0000, 0x4030b800, 0x585c000a,
+	0x80025d40, 0x04020004, 0x585c000c, 0x4c000000,
+	0x0401f044, 0x585c0002, 0x82000580, 0x00000100,
+	0x04020022, 0x592c0801, 0x4c040000, 0x0201f800,
+	0x001007f4, 0x5c000800, 0x800409c0, 0x0400001c,
+	0x4804b80a, 0x585c100d, 0x800811c0, 0x04020005,
+	0x40065800, 0x0201f800, 0x001007fd, 0x0401f014,
+	0x82080480, 0x00000010, 0x04021003, 0x80000580,
+	0x0401f003, 0x42001000, 0x00000010, 0x4800b80d,
+	0x4808b804, 0x800810c4, 0x4808b805, 0x82040400,
+	0x00000004, 0x4800b803, 0x405c1000, 0x0201f800,
+	0x00100858, 0x0401f025, 0x0401f828, 0x585c000c,
+	0x80026540, 0x59300000, 0x80000d40, 0x04020002,
+	0x4800b80b, 0x4800b80c, 0x497a6000, 0x4c000000,
+	0x4978b80a, 0x59325808, 0x4a025a04, 0x00000103,
+	0x59300402, 0x48025c06, 0x592c100b, 0x4c080000,
+	0x0201f800, 0x000202c1, 0x0201f800, 0x0010912a,
+	0x5c001000, 0x8c081518, 0x04000004, 0x0201f800,
+	0x001091d1, 0x0401f003, 0x0201f800, 0x0002077d,
+	0x405c7000, 0x5c000000, 0x80026540, 0x04000003,
+	0x59325808, 0x0401ff78, 0x5c00b800, 0x5c025800,
+	0x5c026000, 0x1c01f000, 0x483bc857, 0x5838000a,
+	0x40025800, 0x0201f800, 0x001007fd, 0x5838000c,
+	0x80026540, 0x59300008, 0x80025d40, 0x4a025a06,
+	0x00000002, 0x1c01f000, 0x4803c857, 0x4d1c0000,
+	0x497a601c, 0x41323800, 0x40026000, 0x4d3c0000,
+	0x42027800, 0x00000005, 0x0401f83c, 0x5c027800,
+	0x411e6000, 0x59300414, 0x84000502, 0x48026414,
+	0x5c023800, 0x1c01f000, 0x481bc857, 0x4933c857,
+	0x4c5c0000, 0x4c600000, 0x4010b800, 0x4014c000,
+	0x0201f800, 0x0010a942, 0x0201f800, 0x00103b25,
+	0x04000008, 0x40602800, 0x405c3000, 0x0201f800,
+	0x0010a446, 0x82000540, 0x00000001, 0x0401f002,
+	0x80000580, 0x5c00c000, 0x5c00b800, 0x1c01f000,
+	0x4803c856, 0x4d300000, 0x42026000, 0x0010d1c0,
+	0x59a8000e, 0x81640580, 0x04000016, 0x59300c06,
+	0x82040580, 0x00000001, 0x04000009, 0x82040580,
+	0x00000004, 0x04000006, 0x82040580, 0x00000010,
+	0x02000800, 0x00108cf9, 0x0401f005, 0x4807c857,
+	0x0201f800, 0x001092d7, 0x04020808, 0x83326400,
+	0x00000024, 0x41580000, 0x81300480, 0x040017e9,
+	0x5c026000, 0x1c01f000, 0x4933c857, 0x59300403,
+	0x4803c857, 0x0201f800, 0x00106c55, 0x4df00000,
+	0x59300406, 0x4803c857, 0x82000d80, 0x00000002,
+	0x04000018, 0x82000d80, 0x00000001, 0x04000009,
+	0x82000d80, 0x00000004, 0x04000006, 0x4933c856,
+	0x5c03e000, 0x02000800, 0x00106c4b, 0x0401f03c,
+	0x59300203, 0x82000d80, 0x00000001, 0x04000018,
+	0x82000d80, 0x00000002, 0x04000026, 0x82000d80,
+	0x00000005, 0x04000023, 0x0201f800, 0x001005d8,
+	0x59300203, 0x82000d80, 0x00000009, 0x0400000c,
+	0x82000d80, 0x0000000b, 0x04000009, 0x82000d80,
+	0x0000000a, 0x04000017, 0x82000d80, 0x0000000c,
+	0x04000014, 0x0201f800, 0x001005d8, 0x598c000d,
+	0x81300580, 0x04020004, 0x0201f800, 0x00106e8e,
+	0x0402000c, 0x59300004, 0x4803c857, 0x8c000520,
+	0x04000004, 0x84000520, 0x48026004, 0x0401f005,
+	0x0201f800, 0x001068d3, 0x02020800, 0x001005d8,
+	0x5c03e000, 0x02000800, 0x00106c4b, 0x59300406,
+	0x82000d80, 0x00000002, 0x04000009, 0x0201f800,
+	0x00104c19, 0x0201f800, 0x0010914e, 0x02000800,
+	0x0010801c, 0x8d3e7d00, 0x04000003, 0x0201f000,
+	0x00107911, 0x4a02621d, 0x00000001, 0x4a026403,
+	0x00000085, 0x4a026203, 0x00000009, 0x4a026406,
+	0x00000002, 0x42000800, 0x8000004b, 0x0201f000,
+	0x00020721, 0x4933c857, 0x59368c03, 0x4c180000,
+	0x59300203, 0x82003480, 0x0000000e, 0x02021800,
+	0x001005d8, 0x0c01f803, 0x5c003000, 0x1c01f000,
+	0x0010990a, 0x00109dcf, 0x00109edb, 0x0010990a,
+	0x0010990a, 0x0010990a, 0x0010990a, 0x0010990a,
+	0x0010992d, 0x0010990a, 0x0010990a, 0x0010990a,
+	0x0010990a, 0x0010990a, 0x0201f800, 0x001005d8,
+	0x4933c857, 0x42028800, 0x0000ffff, 0x813669c0,
+	0x04000002, 0x59368c03, 0x4c180000, 0x59300203,
+	0x82003480, 0x0000000e, 0x02021800, 0x001005d8,
+	0x0c01f803, 0x5c003000, 0x1c01f000, 0x00109929,
+	0x0010a180, 0x00109929, 0x00109929, 0x00109929,
+	0x00109929, 0x00109929, 0x0010a952, 0x0010a0ed,
+	0x0010a52c, 0x0010a562, 0x0010a52c, 0x0010a562,
+	0x00109929, 0x0201f800, 0x001005d8, 0x0201f800,
+	0x001005d8, 0x83383480, 0x00000051, 0x02021800,
+	0x001005d8, 0x41380000, 0x493bc857, 0x4d1c0000,
+	0x4d400000, 0x0c01f804, 0x5c028000, 0x5c023800,
+	0x1c01f000, 0x0010998a, 0x00109b69, 0x0010998a,
+	0x0010998a, 0x0010998a, 0x00109b74, 0x0010998a,
+	0x0010998a, 0x0010998a, 0x0010998a, 0x0010998a,
+	0x0010998a, 0x0010998a, 0x0010998a, 0x0010998a,
+	0x0010998a, 0x0010998a, 0x0010998a, 0x0010998a,
+	0x0010998a, 0x0010998a, 0x0010998a, 0x0010998a,
+	0x001099ac, 0x001099f5, 0x00109a0c, 0x00109a62,
+	0x00109ac6, 0x00109b04, 0x00109b34, 0x0010998a,
+	0x0010998a, 0x00109b7c, 0x0010998a, 0x0010998a,
+	0x00109b8a, 0x00109b93, 0x0010998a, 0x0010998a,
+	0x0010998a, 0x0010998a, 0x0010998a, 0x00109c15,
+	0x0010998a, 0x0010998a, 0x00109a9a, 0x0010998a,
+	0x0010998a, 0x00109bec, 0x0010998a, 0x0010998a,
+	0x0010998a, 0x00109c23, 0x0010998a, 0x0010998a,
+	0x0010998a, 0x00109c6c, 0x0010998a, 0x0010998a,
+	0x0010998a, 0x0010998a, 0x0010998a, 0x0010998a,
+	0x00109cb9, 0x0010998a, 0x00109ce5, 0x00109cf0,
+	0x0010998a, 0x0010998a, 0x0010998c, 0x00109cfb,
+	0x0010998a, 0x0010998a, 0x0010998a, 0x0010999b,
+	0x0010998a, 0x0010998a, 0x0010998a, 0x00109d02,
+	0x00109d0a, 0x00109d28, 0x0201f800, 0x001005d8,
+	0x4933c857, 0x0201f800, 0x0010a592, 0x040203a4,
+	0x0201f800, 0x0010210a, 0x040203a1, 0x59cc0407,
+	0x4802601c, 0x4a026403, 0x00000045, 0x4a026203,
+	0x00000001, 0x0201f000, 0x0010672b, 0x4933c857,
+	0x0201f800, 0x0010a592, 0x04020395, 0x0201f800,
+	0x0010210a, 0x04020392, 0x0401fbce, 0x040201a0,
+	0x59cc0007, 0x4802601c, 0x4a026403, 0x0000004a,
+	0x4a026203, 0x00000001, 0x0201f000, 0x0010672b,
+	0x4933c857, 0x0201f800, 0x0010210a, 0x04020009,
+	0x0201f800, 0x001048ec, 0x04020006, 0x82000500,
+	0x00000009, 0x82000580, 0x00000008, 0x04020008,
+	0x4a026403, 0x00000009, 0x4a02641a, 0x00000009,
+	0x4a02621a, 0x00000000, 0x0401f1b2, 0x0201f800,
+	0x001048c1, 0x0201f800, 0x00104a09, 0x04000021,
+	0x0201f800, 0x001049ed, 0x0400001e, 0x0201f800,
+	0x0010a252, 0x04020025, 0x42028000, 0x00000029,
+	0x4d3c0000, 0x417a7800, 0x0201f800, 0x0010203c,
+	0x5c027800, 0x0201f800, 0x0010462a, 0x836c0580,
+	0x00000002, 0x04020004, 0x59a8001b, 0x80000000,
+	0x4803501b, 0x4a026403, 0x00000008, 0x42003000,
+	0x00000003, 0x0201f800, 0x00103b25, 0x04000191,
+	0x4a026203, 0x00000007, 0x41782800, 0x0401f180,
+	0x0201f800, 0x0010a3da, 0x040207e1, 0x4a026403,
+	0x00000009, 0x4a02641a, 0x0000000e, 0x4a02621a,
+	0x00001900, 0x0401f183, 0x4a026403, 0x00000009,
+	0x4a02641a, 0x00000003, 0x4a02621a, 0x00000f00,
+	0x0401f17c, 0x4933c857, 0x0201f800, 0x0010210a,
+	0x0402033b, 0x0201f800, 0x001048ec, 0x04020338,
+	0x493a6403, 0x0201f800, 0x0010a22d, 0x04020006,
+	0x42003000, 0x00000005, 0x4a026403, 0x00000006,
+	0x0401f7d9, 0x4a026403, 0x00000007, 0x4a02641a,
+	0x00000009, 0x4a02621a, 0x00000000, 0x0401f165,
+	0x4933c857, 0x0201f800, 0x001048ec, 0x04020324,
+	0x0201f800, 0x0010a592, 0x02000800, 0x0010210a,
+	0x0402031f, 0x0201f800, 0x00104a09, 0x04020005,
+	0x42027800, 0x00000001, 0x0201f800, 0x00104567,
+	0x0201f800, 0x001049fc, 0x0402002b, 0x59cc0206,
+	0x82003500, 0x00000003, 0x0402002e, 0x82003480,
+	0x00000014, 0x0400102b, 0x5934300a, 0x84183516,
+	0x82000580, 0x00000014, 0x04020002, 0x84183556,
+	0x481a680a, 0x59cc0406, 0x82000500, 0x00000003,
+	0x04020020, 0x0201f800, 0x0010a29f, 0x04020028,
+	0x0201f800, 0x001049e7, 0x0402000c, 0x417a7800,
+	0x0201f800, 0x001020a1, 0x42003000, 0x00000006,
+	0x0201f800, 0x0010a93a, 0x42000000, 0x0010b865,
+	0x0201f800, 0x0010aa47, 0x0201f800, 0x0010468d,
+	0x4a026403, 0x0000000a, 0x42003000, 0x00000020,
+	0x0401f795, 0x4a026403, 0x0000000b, 0x4a02641a,
+	0x00000009, 0x4a02621a, 0x00001e00, 0x0401f121,
+	0x42000000, 0x0010b860, 0x0201f800, 0x0010aa47,
+	0x4a026403, 0x0000000b, 0x4a02641a, 0x00000007,
+	0x4a02621a, 0x00000000, 0x0401f116, 0x4a026403,
+	0x0000000b, 0x4a02641a, 0x00000003, 0x4a02621a,
+	0x00000000, 0x0401f10f, 0x4933c857, 0x0201f800,
+	0x001048ec, 0x040202ce, 0x0201f800, 0x0010a592,
+	0x040202cb, 0x0201f800, 0x0010210a, 0x040202c8,
+	0x59cc0206, 0x82003500, 0x00000003, 0x0402001d,
+	0x82003480, 0x00000014, 0x0400101a, 0x59cc0406,
+	0x82000500, 0x00000003, 0x04020016, 0x59340400,
+	0x82000580, 0x00000707, 0x04000019, 0x417a7800,
+	0x0201f800, 0x001020a1, 0x42003000, 0x0000000a,
+	0x0201f800, 0x0010a93a, 0x42000000, 0x0010b862,
+	0x0201f800, 0x0010aa47, 0x4a026403, 0x0000000c,
+	0x41782800, 0x42003000, 0x00000021, 0x0401f752,
+	0x4a026403, 0x0000000d, 0x4a02641a, 0x00000007,
+	0x4a02621a, 0x00000000, 0x0401f0de, 0x4a026403,
+	0x0000000d, 0x4a02641a, 0x00000009, 0x4a02621a,
+	0x00001e00, 0x0401f0d7, 0x4933c857, 0x0201f800,
+	0x001048ec, 0x04020296, 0x0201f800, 0x0010a592,
+	0x04020293, 0x0201f800, 0x0010210a, 0x04020290,
+	0x0401facc, 0x0402001a, 0x493a6403, 0x4c5c0000,
+	0x0401fad2, 0x0402000e, 0x4a026403, 0x0000002e,
+	0x405c2800, 0x42003000, 0x00000024, 0x0201f800,
+	0x00103b25, 0x0400000c, 0x4a026203, 0x00000007,
+	0x405c2800, 0x5c00b800, 0x0401f0ad, 0x4a026403,
+	0x0000000d, 0x4a02641a, 0x00000007, 0x4a02621a,
+	0x00000000, 0x5c00b800, 0x0401f0b2, 0x4a026403,
+	0x0000000d, 0x4a02641a, 0x00000009, 0x4a02621a,
+	0x00001e00, 0x0401f0ab, 0x4933c857, 0x0201f800,
+	0x001048ec, 0x040206ef, 0x59a80026, 0x82000500,
+	0x00000009, 0x82000580, 0x00000008, 0x040006e9,
+	0x0201f800, 0x001049fc, 0x0402002d, 0x0201f800,
+	0x0010a2a7, 0x04020007, 0x4a026403, 0x0000000e,
+	0x41782800, 0x42003000, 0x00000052, 0x0401f702,
+	0x4933c857, 0x42003000, 0x00000003, 0x0201f800,
+	0x0010a942, 0x4d3c0000, 0x417a7800, 0x0201f800,
+	0x0010203c, 0x5c027800, 0x42000000, 0x0010b864,
+	0x0201f800, 0x0010aa47, 0x59340200, 0x84000558,
+	0x48026a00, 0x42000800, 0x0000000b, 0x0201f800,
+	0x00104571, 0x0201f800, 0x00103b25, 0x04000076,
+	0x42003000, 0x00000007, 0x0401f062, 0x4933c857,
+	0x4a026403, 0x0000000f, 0x4a02641a, 0x00000003,
+	0x4a02621a, 0x00001e00, 0x0401f072, 0x59340400,
+	0x82000580, 0x00000703, 0x040007f5, 0x0401f040,
+	0x4933c857, 0x0201f800, 0x001048ec, 0x0402022c,
+	0x59a80026, 0x82000500, 0x00000009, 0x82000580,
+	0x00000008, 0x04000226, 0x0201f800, 0x001049f3,
+	0x0402002f, 0x0201f800, 0x0010a2c8, 0x02000800,
+	0x0010a252, 0x04020007, 0x4a026403, 0x00000010,
+	0x41782800, 0x42003000, 0x00000050, 0x0401f6c2,
+	0x4d3c0000, 0x417a7800, 0x0201f800, 0x0010203c,
+	0x5c027800, 0x42003000, 0x00000003, 0x0201f800,
+	0x0010a942, 0x42000000, 0x0010b864, 0x0201f800,
+	0x0010aa47, 0x59340200, 0x84000558, 0x48026a00,
+	0x0401f7c5, 0x4a026403, 0x00000011, 0x4a02641a,
+	0x00000003, 0x4a02621a, 0x00001e00, 0x0401f03d,
+	0x4933c857, 0x0201f800, 0x0010210a, 0x02000800,
+	0x0010a592, 0x040201fa, 0x0401fa36, 0x04020008,
+	0x4a026403, 0x00000012, 0x0401f032, 0x59340400,
+	0x82000580, 0x00000703, 0x040007eb, 0x4d3c0000,
+	0x417a7800, 0x42028000, 0x00000029, 0x0201f800,
+	0x0010203c, 0x5c027800, 0x42003000, 0x00000017,
+	0x0201f800, 0x0010a942, 0x42000000, 0x0010b864,
+	0x0201f800, 0x0010aa47, 0x0201f800, 0x00103b25,
+	0x04000015, 0x42003000, 0x00000006, 0x41782800,
+	0x42028000, 0x00000029, 0x4933c857, 0x4a026403,
+	0x00000001, 0x4a026203, 0x00000007, 0x0201f800,
+	0x0010a974, 0x0201f000, 0x0010a43e, 0x42028000,
+	0x00000046, 0x0201f800, 0x0010a974, 0x0201f000,
+	0x0010a43e, 0x4933c857, 0x4a026403, 0x00000001,
+	0x42000800, 0x0000000b, 0x0201f800, 0x00104571,
+	0x4a026203, 0x00000001, 0x0201f000, 0x0010672b,
+	0x4933c857, 0x42000800, 0x00000009, 0x0201f800,
+	0x00104571, 0x4a026403, 0x00000005, 0x0401f7f5,
+	0x0201f800, 0x0010a592, 0x040201b5, 0x0201f800,
+	0x0010210a, 0x040201b2, 0x0401f9ee, 0x040207c0,
+	0x4a026403, 0x00000020, 0x4a026203, 0x00000001,
+	0x0201f000, 0x0010672b, 0x0201f800, 0x0010210a,
+	0x040201a7, 0x4a026403, 0x00000023, 0x4a026203,
+	0x00000001, 0x0201f000, 0x0010672b, 0x0201f800,
+	0x0010a592, 0x02000800, 0x0010210a, 0x0402019c,
+	0x0401f9d8, 0x040207aa, 0x40300800, 0x59a81010,
+	0x59cc0007, 0x82000500, 0x00ffffff, 0x80080580,
+	0x04000019, 0x59cc1408, 0x0201f800, 0x0010902c,
+	0x0400002d, 0x59cc0c08, 0x4d300000, 0x0201f800,
+	0x00105dd7, 0x41323800, 0x5c026000, 0x04000026,
+	0x591c0202, 0x82000580, 0x0000ffff, 0x04000005,
+	0x59cc1208, 0x591c0202, 0x80080580, 0x0402001e,
+	0x591c0406, 0x82000580, 0x00000007, 0x0402001a,
+	0x0401f02c, 0x59cc1208, 0x82080580, 0x0000ffff,
+	0x0400000c, 0x0201f800, 0x00109410, 0x04000012,
+	0x59cc1408, 0x591c0202, 0x80080580, 0x0402000e,
+	0x591c0009, 0x81340580, 0x04000016, 0x0401f00a,
+	0x59cc1408, 0x417a7800, 0x0201f800, 0x0010a405,
+	0x04020010, 0x59cc1208, 0x82080580, 0x0000ffff,
+	0x04000019, 0x4a026403, 0x00000026, 0x4a02621a,
+	0x00001700, 0x59cc1204, 0x82081580, 0x0000ffff,
+	0x04020798, 0x4a026403, 0x00000025, 0x0401f795,
+	0x591c0406, 0x82000580, 0x00000007, 0x040207f2,
+	0x591c0403, 0x82000580, 0x00000024, 0x04020006,
+	0x4d300000, 0x411e6000, 0x0201f800, 0x0002077d,
+	0x5c026000, 0x4a026403, 0x00000025, 0x0401f785,
+	0x4933c857, 0x4d3c0000, 0x42027800, 0x00000001,
+	0x0201f800, 0x00104567, 0x5c027800, 0x4c580000,
+	0x4200b000, 0x00000002, 0x83a81c00, 0x00000002,
+	0x83cc1400, 0x0000000b, 0x0201f800, 0x0010855a,
+	0x5c00b000, 0x04000004, 0x4a026403, 0x00000031,
+	0x0401f770, 0x0201f800, 0x00107911, 0x0201f800,
+	0x0010513b, 0x0402000f, 0x0201f800, 0x00105149,
+	0x04020008, 0x4a035033, 0x00000001, 0x4202d800,
+	0x00000001, 0x0201f800, 0x001050a2, 0x0401f005,
+	0x42000000, 0x00000001, 0x0201f800, 0x00105113,
+	0x1c01f000, 0x0201f800, 0x0010210a, 0x0402011c,
+	0x0401f958, 0x0402072a, 0x493a6403, 0x0401f996,
+	0x04020004, 0x4a026403, 0x0000002b, 0x0401f751,
+	0x4a026403, 0x0000002c, 0x0401f74e, 0x4933c857,
+	0x0201f800, 0x0010210a, 0x0402010d, 0x0201f800,
+	0x001049e7, 0x04020740, 0x0201f800, 0x001048d9,
+	0x0400003c, 0x59cc0408, 0x48026419, 0x59cc0208,
+	0x48026219, 0x59cc0807, 0x59340002, 0x82000500,
+	0x00ffffff, 0x80040580, 0x04000012, 0x59a80010,
+	0x80040580, 0x04020021, 0x59cc1408, 0x0201f800,
+	0x00109410, 0x04000023, 0x0201f800, 0x0010a4ca,
+	0x04000020, 0x0201f800, 0x0010a921, 0x0400001d,
+	0x491e601e, 0x4a026403, 0x00000036, 0x0401f0e6,
+	0x59cc1208, 0x82080580, 0x0000ffff, 0x04000009,
+	0x0201f800, 0x00109410, 0x04000012, 0x591c0202,
+	0x59cc0c08, 0x80040580, 0x0402000e, 0x0401f7eb,
+	0x59cc1408, 0x41327800, 0x0201f800, 0x0010a405,
+	0x04000008, 0x0401f7e5, 0x4803c856, 0x4a02641a,
+	0x00000009, 0x4a02621a, 0x00001500, 0x0401f006,
+	0x4803c856, 0x4a02641a, 0x00000003, 0x4a02621a,
+	0x00001700, 0x4a026403, 0x00000037, 0x0401f0c6,
+	0x4803c856, 0x4a026403, 0x00000012, 0x0401f0c2,
+	0x4933c857, 0x0201f800, 0x0010210a, 0x040200c4,
+	0x0201f800, 0x001049e7, 0x040206f7, 0x0201f800,
+	0x001048d9, 0x0400003e, 0x59cc0407, 0x48026419,
+	0x59cc1207, 0x480a6219, 0x82080580, 0x0000ffff,
+	0x04000005, 0x0201f800, 0x00109410, 0x0400002c,
+	0x0401f006, 0x59cc1407, 0x41327800, 0x0201f800,
+	0x0010a405, 0x04000026, 0x59cc0c07, 0x591c0202,
+	0x80040580, 0x04020022, 0x4d300000, 0x411e6000,
+	0x0201f800, 0x00108bd7, 0x5c026000, 0x59cc0c09,
+	0x82040d00, 0x0000ff00, 0x840409c0, 0x0201f800,
+	0x0010a921, 0x04000016, 0x82040580, 0x00000001,
+	0x0400000a, 0x82040580, 0x00000005, 0x04000004,
+	0x82040580, 0x00000007, 0x04020007, 0x591c0008,
+	0x80000540, 0x04000004, 0x59cc2808, 0x0201f000,
+	0x0010a4de, 0x4803c856, 0x4a02641a, 0x00000009,
+	0x4a02621a, 0x00002a00, 0x0401f006, 0x4803c856,
+	0x4a02641a, 0x00000003, 0x4a02621a, 0x00000300,
+	0x4a026403, 0x0000003b, 0x0401f07b, 0x4803c856,
+	0x4a02641a, 0x0000000b, 0x4a02621a, 0x00000000,
+	0x0401f7f8, 0x4c080000, 0x0201f800, 0x001048ec,
+	0x04000026, 0x0201f800, 0x001048c1, 0x0201f800,
+	0x0010a601, 0x0402001e, 0x59a80026, 0x82000540,
+	0x00000003, 0x48035026, 0x59a8001d, 0x800000d0,
+	0x59a80810, 0x82040d00, 0x000000ff, 0x80041540,
+	0x480b5010, 0x42000800, 0x00000003, 0x0201f800,
+	0x00106c78, 0x497b5028, 0x0201f800, 0x00103b25,
+	0x04000003, 0x4a032804, 0x000007d0, 0x8c00050a,
+	0x0402000a, 0x0201f800, 0x0002077d, 0x0201f800,
+	0x00101e45, 0x5c001000, 0x1c01f000, 0x0201f800,
+	0x0010a623, 0x0401f7fc, 0x5c001000, 0x0201f000,
+	0x0002077d, 0x0201f800, 0x0010210a, 0x0402004c,
+	0x0201f800, 0x0010a628, 0x4a026403, 0x00000047,
+	0x4a026203, 0x00000001, 0x0201f000, 0x0010672b,
+	0x0201f800, 0x0010210a, 0x04020041, 0x0201f800,
+	0x0010a628, 0x4a026403, 0x00000047, 0x4a026203,
+	0x00000001, 0x0201f000, 0x0010672b, 0x0201f800,
+	0x0010210a, 0x04020036, 0x0201f800, 0x0010a628,
+	0x0201f000, 0x0002077d, 0x0401f834, 0x04000030,
+	0x4a026403, 0x0000004e, 0x4a026203, 0x00000001,
+	0x0201f000, 0x0010672b, 0x4a026403, 0x0000004f,
+	0x497a601c, 0x59cc0a06, 0x82040d00, 0x000000ff,
+	0x800409c0, 0x0400065f, 0x82040580, 0x00000001,
+	0x04020005, 0x59cc0808, 0x59a80005, 0x80040580,
+	0x04000658, 0x82040580, 0x00000002, 0x0402000a,
+	0x83cc1400, 0x0000000b, 0x4200b000, 0x00000002,
+	0x83341c00, 0x00000006, 0x0201f800, 0x0010855a,
+	0x0400064c, 0x4a02601c, 0x00000001, 0x0401f649,
+	0x4a026403, 0x00000050, 0x59cc0207, 0x4802601c,
+	0x0401f644, 0x4a026203, 0x00000001, 0x42000800,
+	0x80000040, 0x0201f000, 0x00020721, 0x4803c857,
+	0x0201f000, 0x0002077d, 0x4d2c0000, 0x4c500000,
+	0x4c580000, 0x4c540000, 0x59a80016, 0x82000c80,
+	0x00000829, 0x04021029, 0x0201f800, 0x001007d3,
+	0x04000026, 0x492e6008, 0x59a80016, 0x80000104,
+	0x48025802, 0x83cca400, 0x00000006, 0x82000c80,
+	0x0000000b, 0x04001013, 0x4a025811, 0x0000000b,
+	0x4200b000, 0x0000000b, 0x832c0400, 0x00000005,
+	0x4000a800, 0x0201f800, 0x0010ab17, 0x412c7000,
+	0x0201f800, 0x001007d3, 0x04000010, 0x492c7001,
+	0x40040000, 0x800409c0, 0x04000009, 0x0401f7ec,
+	0x48025811, 0x4000b000, 0x832c0400, 0x00000005,
+	0x4000a800, 0x0201f800, 0x0010ab17, 0x82000540,
+	0x00000001, 0x0401f006, 0x497b5016, 0x59325808,
+	0x0201f800, 0x001007fd, 0x80000580, 0x5c00a800,
+	0x5c00b000, 0x5c00a000, 0x5c025800, 0x1c01f000,
+	0x4d340000, 0x59326809, 0x59343400, 0x4933c857,
+	0x4937c857, 0x481bc857, 0x0201f800, 0x001049f3,
+	0x5c026800, 0x1c01f000, 0x4933c857, 0x4c5c0000,
+	0x4d3c0000, 0x0401f840, 0x0402002c, 0x59cc0207,
+	0x82000d00, 0x0000ff00, 0x900411c0, 0x59cc000a,
+	0x82000500, 0x00ffffff, 0x80081540, 0x480a601c,
+	0x8c040d18, 0x0400000e, 0x42003000, 0x00000008,
+	0x0201f800, 0x0010a932, 0x42000000, 0x0010b863,
+	0x0201f800, 0x0010aa47, 0x4200b800, 0x00000002,
+	0x42027800, 0x00000001, 0x0401f011, 0x4178b800,
+	0x8c040d1a, 0x04000011, 0x59cc000a, 0x0201f800,
+	0x00105c9a, 0x0402000d, 0x42003000, 0x00000009,
+	0x0201f800, 0x0010a93a, 0x42000000, 0x0010b863,
+	0x0201f800, 0x0010aa47, 0x417a7800, 0x0201f800,
+	0x001020a1, 0x0401f004, 0x82000540, 0x00000001,
+	0x0401f002, 0x80000580, 0x5c027800, 0x5c00b800,
+	0x1c01f000, 0x4933c857, 0x59cc0206, 0x82000480,
+	0x00000010, 0x04021006, 0x4a02621a, 0x00000000,
+	0x82000540, 0x00000001, 0x0401f002, 0x80000580,
+	0x1c01f000, 0x4933c857, 0x4a02621a, 0x00000000,
+	0x59cc0407, 0x82000500, 0x0000ff00, 0x82000580,
+	0x00000800, 0x04020009, 0x59cc0006, 0x82000500,
+	0x00ff0000, 0x82000d80, 0x00140000, 0x04000003,
+	0x82000d80, 0x00100000, 0x1c01f000, 0x4933c857,
+	0x59300403, 0x82003480, 0x00000051, 0x02021800,
+	0x001005d8, 0x83383580, 0x00000013, 0x04020003,
+	0x4803c857, 0x0c01f012, 0x83383580, 0x00000027,
+	0x04000005, 0x83383580, 0x00000014, 0x02020800,
+	0x001005d8, 0x0201f800, 0x001048c1, 0x42000800,
+	0x00000007, 0x0201f800, 0x00104571, 0x0201f800,
+	0x00106bbf, 0x0201f000, 0x00107911, 0x00109e3c,
+	0x00109e45, 0x00109e3c, 0x00109e3c, 0x00109e3c,
+	0x00109e45, 0x00109e50, 0x00109ecd, 0x00109e95,
+	0x00109ecd, 0x00109ead, 0x00109ecd, 0x00109ebe,
+	0x00109ecd, 0x00109ec6, 0x00109ecd, 0x00109ec6,
+	0x00109ecd, 0x00109ecd, 0x00109e3c, 0x00109e3c,
+	0x00109e3c, 0x00109e3c, 0x00109e3c, 0x00109e3c,
+	0x00109e3c, 0x00109e3c, 0x00109e3c, 0x00109e3c,
+	0x00109e3c, 0x00109e45, 0x00109e3c, 0x00109ecd,
+	0x00109e3c, 0x00109e3c, 0x00109ecd, 0x00109e3c,
+	0x00109eca, 0x00109ecd, 0x00109e3c, 0x00109e3c,
+	0x00109e3c, 0x00109e3c, 0x00109ecd, 0x00109ecd,
+	0x00109e3c, 0x00109ec3, 0x00109ecd, 0x00109e3c,
+	0x00109e4a, 0x00109e3c, 0x00109e3c, 0x00109e3c,
+	0x00109e3c, 0x00109ec9, 0x00109ecd, 0x00109e3c,
+	0x00109e3c, 0x00109ecd, 0x00109ecd, 0x00109e3c,
+	0x00109e3c, 0x00109e3c, 0x00109e3c, 0x00109e3c,
+	0x00109e3c, 0x00109e3c, 0x00109e3c, 0x00109e3c,
+	0x00109e3e, 0x00109e3c, 0x00109e3e, 0x00109e3c,
+	0x00109e3c, 0x00109e3e, 0x00109e3c, 0x00109e3c,
+	0x00109e3c, 0x00109e3e, 0x00109e3e, 0x00109e3e,
+	0x0201f800, 0x001005d8, 0x4d2c0000, 0x59325808,
+	0x0201f800, 0x001007fd, 0x5c025800, 0x0201f000,
+	0x0002077d, 0x59a80037, 0x48026206, 0x4a026203,
+	0x00000002, 0x1c01f000, 0x4d3c0000, 0x417a7800,
+	0x0201f800, 0x00104567, 0x5c027800, 0x0401f07e,
+	0x42000800, 0x00000007, 0x0201f800, 0x00104571,
+	0x59a80026, 0x8c000508, 0x04000012, 0x59326809,
+	0x4c580000, 0x4200b000, 0x00000002, 0x83a81c00,
+	0x00000002, 0x83341400, 0x00000006, 0x0201f800,
+	0x0010855a, 0x80000540, 0x5c00b000, 0x0402006a,
+	0x59340200, 0x8400051a, 0x48026a00, 0x0401f01b,
+	0x599c0017, 0x8c00050a, 0x04020063, 0x4d3c0000,
+	0x417a7800, 0x0201f800, 0x00104567, 0x5c027800,
+	0x42000800, 0x00000007, 0x0201f800, 0x00104571,
+	0x59340212, 0x82000500, 0x0000ff00, 0x04000056,
+	0x599c0019, 0x8c00050e, 0x04020053, 0x416c0000,
+	0x82000580, 0x00000002, 0x04020004, 0x59a8001b,
+	0x80000000, 0x4803501b, 0x42000800, 0x00000003,
+	0x0201f800, 0x00104571, 0x4a026406, 0x00000001,
+	0x4a026203, 0x00000001, 0x4a026403, 0x00000002,
+	0x0201f800, 0x0010672b, 0x4ce80000, 0x4201d000,
+	0x00000001, 0x0201f800, 0x00105fae, 0x5c01d000,
+	0x1c01f000, 0x0201f800, 0x001049f3, 0x04000036,
+	0x0201f800, 0x0010645e, 0x42000800, 0x00000004,
+	0x0201f800, 0x00104571, 0x0201f800, 0x0010a96a,
+	0x0402002d, 0x42000800, 0x00000005, 0x0201f800,
+	0x00104571, 0x4a026406, 0x00000001, 0x4a026203,
+	0x00000001, 0x4a026403, 0x00000003, 0x0201f000,
+	0x0010672b, 0x42000800, 0x00000006, 0x0401f820,
+	0x59303009, 0x599c0017, 0x8c00050a, 0x0402001a,
+	0x59a80026, 0x8c000508, 0x04000017, 0x0201f800,
+	0x001049e7, 0x04000014, 0x59a8001b, 0x80000000,
+	0x4803501b, 0x0401f7c5, 0x42000800, 0x00000004,
+	0x0201f800, 0x00104571, 0x0401f792, 0x42000800,
+	0x00000004, 0x0401f006, 0x0201f800, 0x001048c1,
+	0x0401f005, 0x0401f004, 0x0401f003, 0x0201f800,
+	0x00104571, 0x0201f000, 0x0002077d, 0x4933c857,
+	0x4807c857, 0x0201f800, 0x00104571, 0x4d3c0000,
+	0x417a7800, 0x0201f800, 0x00104567, 0x5c027800,
+	0x0201f800, 0x00102074, 0x1c01f000, 0x4933c857,
+	0x59340400, 0x80000110, 0x82003480, 0x0000000c,
+	0x02021800, 0x001005d8, 0x83383580, 0x00000015,
+	0x04020002, 0x0c01f006, 0x83383580, 0x00000016,
+	0x02020800, 0x001005d8, 0x0c01f00d, 0x001080b8,
+	0x001080b8, 0x001080b8, 0x001080b8, 0x001080b8,
+	0x001080b8, 0x00109f30, 0x00109f03, 0x001080b8,
+	0x001080b8, 0x001080b8, 0x001080b8, 0x001080b8,
+	0x001080b8, 0x001080b8, 0x001080b8, 0x001080b8,
+	0x001080b8, 0x00109f30, 0x00109f37, 0x001080b8,
+	0x001080b8, 0x001080b8, 0x001080b8, 0x4933c857,
+	0x599c0017, 0x8c00050a, 0x0402001b, 0x813669c0,
+	0x04000019, 0x59340212, 0x82000500, 0x0000ff00,
+	0x04000015, 0x599c0019, 0x8c00050e, 0x04020012,
+	0x4d3c0000, 0x417a7800, 0x0201f800, 0x00104567,
+	0x5c027800, 0x42000800, 0x00000003, 0x0201f800,
+	0x00104571, 0x4a026406, 0x00000001, 0x4a026203,
+	0x00000001, 0x4a026403, 0x00000002, 0x0201f000,
+	0x0010672b, 0x59cc0001, 0x0201f800, 0x00105c9a,
+	0x0402000b, 0x0201f800, 0x00020245, 0x02020000,
+	0x0002077d, 0x59345002, 0x0201f800, 0x001042b4,
+	0x482a6802, 0x0201f000, 0x0002077d, 0x1c01f000,
+	0x4933c857, 0x59303403, 0x82183580, 0x0000001e,
+	0x02000000, 0x0002077d, 0x1c01f000, 0x4933c857,
+	0x0201f800, 0x001083df, 0x02020000, 0x0002077d,
+	0x4a026203, 0x00000001, 0x4a026403, 0x00000001,
+	0x0201f000, 0x0010672b, 0x493bc857, 0x83380580,
+	0x00000051, 0x0402000b, 0x0201f800, 0x00106f60,
+	0x02020000, 0x00107974, 0x59300203, 0x82000580,
+	0x00000002, 0x0400006d, 0x0201f800, 0x001005d8,
+	0x83380580, 0x00000027, 0x04000014, 0x83380580,
+	0x00000048, 0x04000006, 0x83380580, 0x00000014,
+	0x0400000e, 0x02020800, 0x001005d8, 0x0201f800,
+	0x00106f60, 0x02020000, 0x00107974, 0x59300203,
+	0x82000580, 0x00000004, 0x02000000, 0x0002086e,
+	0x0201f800, 0x001005d8, 0x59300403, 0x82000c80,
+	0x00000044, 0x02021800, 0x001005d8, 0x82000480,
+	0x00000040, 0x02001800, 0x001005d8, 0x40027000,
+	0x4803c857, 0x0c01f001, 0x00109f76, 0x00109f78,
+	0x00109f78, 0x00109f93, 0x0201f800, 0x001005d8,
+	0x0201f800, 0x00106bbf, 0x59325808, 0x812e59c0,
+	0x04000016, 0x832c0500, 0x00ff0000, 0x04000013,
+	0x4a026203, 0x00000002, 0x59326809, 0x59340200,
+	0x8c00050e, 0x0402000d, 0x42028000, 0x00000004,
+	0x0201f800, 0x0010a3ef, 0x497a6008, 0x59300206,
+	0x80000540, 0x04020003, 0x59a80038, 0x48026206,
+	0x4a026203, 0x00000007, 0x1c01f000, 0x0201f800,
+	0x00106bbf, 0x0201f800, 0x00109037, 0x02000000,
+	0x00107911, 0x59325808, 0x0201f800, 0x001007f4,
+	0x0201f000, 0x00107911, 0x0201f800, 0x001005d8,
+	0x59325808, 0x592c040a, 0x8c000502, 0x04000007,
+	0x4a026203, 0x00000007, 0x42027000, 0x00000043,
+	0x0201f000, 0x000207a1, 0x4a026203, 0x00000004,
+	0x1c01f000, 0x0201f800, 0x0010a597, 0x02000000,
+	0x0002086c, 0x1c01f000, 0x4a026203, 0x00000001,
+	0x4a026403, 0x00000041, 0x42027800, 0x80002042,
+	0x0201f000, 0x00020721, 0x83380580, 0x00000051,
+	0x04000006, 0x83380580, 0x00000041, 0x02020800,
+	0x001005d8, 0x1c01f000, 0x0201f800, 0x000206fd,
+	0x0201f800, 0x0010a5df, 0x0201f000, 0x0002077d,
+	0x83380480, 0x00000050, 0x02021800, 0x001005d8,
+	0x83380480, 0x00000049, 0x02001800, 0x001005d8,
+	0x0c01f001, 0x00109fda, 0x00109ffb, 0x00109fd8,
+	0x00109fd8, 0x00109fd8, 0x00109fd8, 0x00109ffb,
+	0x0201f800, 0x001005d8, 0x59325808, 0x592c040a,
+	0x8c00051e, 0x0400000d, 0x82000d00, 0x000000c0,
+	0x82040d80, 0x00000080, 0x0400000d, 0x59300804,
+	0x8c040d18, 0x0402000a, 0x42027000, 0x00000041,
+	0x0201f000, 0x0002088d, 0x4a026203, 0x00000007,
+	0x497a6206, 0x0201f000, 0x000206fd, 0x59325808,
+	0x592c0c0a, 0x8c040d1a, 0x04020005, 0x0201f800,
+	0x000206fd, 0x0201f000, 0x0002077d, 0x0201f800,
+	0x0010a597, 0x040007fa, 0x1c01f000, 0x0201f800,
+	0x00106b8a, 0x59325808, 0x59326809, 0x59340200,
+	0x8c00050e, 0x0400000e, 0x592c040a, 0x82000500,
+	0x000000c0, 0x82000580, 0x00000080, 0x04000005,
+	0x592c000f, 0x59301815, 0x800c1c80, 0x480e6015,
+	0x4a026203, 0x00000002, 0x0401f00d, 0x42028000,
+	0x00000004, 0x0401fbde, 0x59300206, 0x80000540,
+	0x04020004, 0x59a80038, 0x800000c2, 0x48026206,
+	0x497a6008, 0x4a026203, 0x00000007, 0x1c01f000,
+	0x4a026203, 0x00000007, 0x497a6206, 0x0201f000,
+	0x000206fd, 0x4a026203, 0x00000007, 0x497a6206,
+	0x0201f000, 0x000206f8, 0x59300414, 0x8c00051c,
+	0x02020000, 0x0002087e, 0x59325808, 0x592c200f,
+	0x40080000, 0x80102480, 0x59300015, 0x80102400,
+	0x48126015, 0x0201f000, 0x0002087e, 0x8c040d0e,
+	0x0402000a, 0x4a026203, 0x00000006, 0x0401f823,
+	0x5930001f, 0x80000540, 0x02020800, 0x00100d7c,
+	0x0201f000, 0x000206f8, 0x4a026203, 0x00000002,
+	0x1c01f000, 0x42000800, 0x00000001, 0x0201f800,
+	0x00100d7c, 0x82040580, 0x00000001, 0x02000000,
+	0x00020885, 0x0401f7d8, 0x59300414, 0x8c00051c,
+	0x04000006, 0x0201f800, 0x00100b63, 0x02000000,
+	0x00020877, 0x1c01f000, 0x59300011, 0x80000540,
+	0x04020005, 0x0201f800, 0x00100b63, 0x02000000,
+	0x00020877, 0x1c01f000, 0x492fc857, 0x480bc857,
+	0x8c08153e, 0x04000006, 0x80081080, 0x80081000,
+	0x42000800, 0x00000009, 0x0401f003, 0x42000800,
+	0x00000015, 0x480a580b, 0x1c01f000, 0x83380580,
+	0x00000013, 0x04000005, 0x83380580, 0x00000014,
+	0x02020800, 0x001005d8, 0x59300414, 0x8c000516,
+	0x02000800, 0x001005d8, 0x1c01f000, 0x0201f800,
+	0x001005d8, 0x59300008, 0x80000540, 0x02020800,
+	0x001005d8, 0x1c01f000, 0x59300414, 0x8c000516,
+	0x02000800, 0x001005d8, 0x1c01f000, 0x4a026203,
+	0x00000004, 0x493a6403, 0x42000800, 0x80002001,
+	0x0201f000, 0x00020721, 0x4a026203, 0x00000003,
+	0x493a6403, 0x0201f800, 0x000200c9, 0x59325808,
+	0x592c040a, 0x8c00051e, 0x04000012, 0x82000500,
+	0x000000c0, 0x82000580, 0x00000080, 0x04000011,
+	0x59300414, 0x8c000512, 0x0402000a, 0x8c000510,
+	0x04020008, 0x592c040c, 0x80000540, 0x04020005,
+	0x82080d40, 0x80003065, 0x0201f000, 0x00106721,
+	0x82080d40, 0x80002065, 0x0201f000, 0x00106721,
+	0x82080d40, 0x80002042, 0x0201f000, 0x00106721,
+	0x4933c857, 0x493bc857, 0x83380480, 0x00000044,
+	0x02021800, 0x001005d8, 0x83380480, 0x00000041,
+	0x02001800, 0x001005d8, 0x0c01f001, 0x0010a0b6,
+	0x0010a0c6, 0x0010a0db, 0x59325808, 0x592c040a,
+	0x8c00051e, 0x0400001d, 0x82001d00, 0x000000c0,
+	0x820c1d80, 0x000000c0, 0x04000018, 0x4a026203,
+	0x00000001, 0x493a6403, 0x42000800, 0x80002042,
+	0x0201f000, 0x00020721, 0x59325808, 0x592c040a,
+	0x8c00051e, 0x0400000d, 0x82001d00, 0x000000c0,
+	0x820c1d80, 0x000000c0, 0x04000008, 0x4a026203,
+	0x00000001, 0x493a6403, 0x42000800, 0x80002001,
+	0x0201f000, 0x00020721, 0x497a6008, 0x497a6206,
+	0x42028000, 0x00000004, 0x0401f315, 0x59325808,
+	0x592c040a, 0x8c00051e, 0x040007f8, 0x82001d00,
+	0x000000c0, 0x820c1d80, 0x000000c0, 0x040007f3,
+	0x4a026203, 0x00000003, 0x493a6403, 0x0201f800,
+	0x000200c9, 0x82080d40, 0x80002065, 0x0201f000,
+	0x00106721, 0x4933c857, 0x493bc857, 0x83380580,
+	0x00000085, 0x04000006, 0x83380580, 0x00000088,
+	0x0400000a, 0x0201f800, 0x001005d8, 0x4a026203,
+	0x00000009, 0x493a6403, 0x42000800, 0x8000004b,
+	0x0201f000, 0x00020721, 0x4d1c0000, 0x813669c0,
+	0x04000004, 0x0201f800, 0x0010a592, 0x04020044,
+	0x59cc1404, 0x0401f846, 0x04000018, 0x591c0406,
+	0x82000500, 0x0000001f, 0x82002580, 0x00000006,
+	0x04000007, 0x82002580, 0x00000004, 0x0400002e,
+	0x82002580, 0x00000011, 0x0402000c, 0x497a3a05,
+	0x42002000, 0x00000054, 0x0201f800, 0x00107a4a,
+	0x4a026203, 0x00000007, 0x493a6403, 0x0201f800,
+	0x0010a974, 0x0401f02c, 0x0201f800, 0x00103b25,
+	0x04000004, 0x42023800, 0xffffffff, 0x0401f7f1,
+	0x813669c0, 0x04020009, 0x59cc0001, 0x0201f800,
+	0x00105c9a, 0x0402001e, 0x0201f800, 0x001045a6,
+	0x0402001b, 0x49366009, 0x4a026403, 0x00000087,
+	0x59cc1204, 0x82081580, 0x0000ffff, 0x04020003,
+	0x4a026403, 0x00000086, 0x4a026203, 0x00000001,
+	0x42000800, 0x80000040, 0x0201f800, 0x00020721,
+	0x0401f00d, 0x591c0203, 0x82000580, 0x00000007,
+	0x040207de, 0x4d300000, 0x411e6000, 0x0201f800,
+	0x00107911, 0x5c026000, 0x0401f7d8, 0x0201f800,
+	0x00107911, 0x5c023800, 0x1c01f000, 0x4933c857,
+	0x480bc857, 0x42002800, 0x0010d1c0, 0x41300000,
+	0x80140580, 0x04000017, 0x58140203, 0x82000580,
+	0x00000000, 0x04000013, 0x58140202, 0x80080580,
+	0x04020010, 0x58141c06, 0x820c0580, 0x00000005,
+	0x0400000c, 0x820c0580, 0x00000009, 0x0400001d,
+	0x59302009, 0x58140009, 0x800001c0, 0x0400000b,
+	0x801021c0, 0x04000003, 0x80100580, 0x04000010,
+	0x82142c00, 0x00000024, 0x41540000, 0x80140480,
+	0x0402100e, 0x0401f7e2, 0x5814001e, 0x801021c0,
+	0x04000005, 0x58102002, 0x82102500, 0x00ffffff,
+	0x0401f7f2, 0x5810201e, 0x0401f7f0, 0x40163800,
+	0x81300540, 0x0401f002, 0x80000580, 0x1c01f000,
+	0x58141807, 0x8c0c1d10, 0x040207ea, 0x0401f7e1,
+	0x4933c857, 0x493bc857, 0x83380580, 0x00000013,
+	0x0402000e, 0x59300403, 0x82000c80, 0x00000085,
+	0x02001800, 0x001005d8, 0x82000c80, 0x00000093,
+	0x02021800, 0x001005d8, 0x82000480, 0x00000085,
+	0x4803c857, 0x0c01f018, 0x83380580, 0x00000027,
+	0x04000005, 0x83380580, 0x00000014, 0x02020000,
+	0x00107974, 0x0201f800, 0x00106bbf, 0x59325808,
+	0x812e59c0, 0x02000000, 0x00107911, 0x4a025a06,
+	0x00000031, 0x4a025811, 0x00000004, 0x4a025812,
+	0x000000ff, 0x0201f800, 0x000202da, 0x0201f000,
+	0x00107911, 0x0010a1b7, 0x0010a1be, 0x0010a1be,
+	0x0010a1b7, 0x0010a1b7, 0x0010a1b7, 0x0010a1b7,
+	0x0010a1b7, 0x0010a1b7, 0x0010a1b7, 0x0010a1b7,
+	0x0010a1b7, 0x0010a1b7, 0x0010a1b9, 0x0201f800,
+	0x001005d8, 0x59325808, 0x4a025a06, 0x00000000,
+	0x0201f800, 0x000202da, 0x0201f000, 0x00107911,
+	0x4933c857, 0x42000000, 0x0010b873, 0x0201f800,
+	0x0010aa47, 0x0201f800, 0x0010a5df, 0x497a6205,
+	0x42028000, 0x0000000b, 0x0401f807, 0x4a026406,
+	0x00000006, 0x4a026203, 0x00000007, 0x497a6206,
+	0x1c01f000, 0x4933c857, 0x4943c857, 0x59300406,
+	0x82000580, 0x00000007, 0x04020002, 0x1c01f000,
+	0x0201f800, 0x00106c55, 0x4df00000, 0x0201f800,
+	0x00108ce5, 0x82000c80, 0x0000000e, 0x02021800,
+	0x001005d8, 0x0c01f001, 0x0010a205, 0x0010a209,
+	0x0010a1f0, 0x0010a217, 0x0010a22a, 0x0010a1f0,
+	0x0010a1f0, 0x0010a1f0, 0x0010a1f0, 0x0010a1f0,
+	0x0010a1f0, 0x0010a1f0, 0x0010a1f0, 0x0010a1f0,
+	0x4d400000, 0x5930001f, 0x80000540, 0x04000005,
+	0x41400800, 0x0201f800, 0x00100d7c, 0x40068000,
+	0x4d2c0000, 0x59325808, 0x0201f800, 0x00109037,
+	0x040209f3, 0x4c5c0000, 0x5930b809, 0x0201f800,
+	0x00107911, 0x485e6009, 0x5c00b800, 0x5c025800,
+	0x5c028000, 0x5c03e000, 0x02000000, 0x00106c4b,
+	0x1c01f000, 0x598c000d, 0x81300580, 0x04020004,
+	0x0201f800, 0x00106e8e, 0x04020016, 0x0201f800,
+	0x001068d3, 0x040007df, 0x0201f800, 0x00106b6c,
+	0x04000010, 0x0201f800, 0x001005d8, 0x0201f800,
+	0x00108cd6, 0x04020004, 0x0201f800, 0x00106e62,
+	0x04020008, 0x0201f800, 0x001067ae, 0x040007d1,
+	0x0201f800, 0x00106b6c, 0x02020800, 0x001005d8,
+	0x59300203, 0x82000c80, 0x0000000e, 0x02021800,
+	0x001005d8, 0x0c01f7b9, 0x0201f800, 0x00100e99,
+	0x0401f7c4, 0x4933c857, 0x4d440000, 0x4d340000,
+	0x59cc0007, 0x0201f800, 0x00105c9a, 0x02000800,
+	0x00020245, 0x0402001a, 0x59300009, 0x4c000000,
+	0x49366009, 0x42003000, 0x0000000b, 0x0201f800,
+	0x0010a942, 0x42000000, 0x0010b861, 0x0201f800,
+	0x0010aa47, 0x4d3c0000, 0x4d400000, 0x42028000,
+	0x00000029, 0x417a7800, 0x0201f800, 0x0010203c,
+	0x5c028000, 0x5c027800, 0x5c000000, 0x48026009,
+	0x59cc0007, 0x48026802, 0x80000580, 0x5c026800,
+	0x5c028800, 0x1c01f000, 0x4933c857, 0x4c040000,
+	0x59a80016, 0x82000580, 0x00000074, 0x04020040,
+	0x59cc0a08, 0x82040480, 0x00000100, 0x04001033,
+	0x59cc0c08, 0x82040500, 0x00008000, 0x04000035,
+	0x59a80032, 0x80000540, 0x04020009, 0x59301009,
+	0x58080212, 0x82000500, 0x0000ff00, 0x04000004,
+	0x82040500, 0x00000800, 0x0400002a, 0x59cc0c09,
+	0x80040840, 0x04001024, 0x59a80826, 0x8c040d06,
+	0x04000004, 0x59cc0c0f, 0x8c040d1e, 0x04020012,
+	0x59cc0a17, 0x800409c0, 0x04020012, 0x59cc0a18,
+	0x82040480, 0x00000100, 0x04001014, 0x59cc0c18,
+	0x800409c0, 0x0402000e, 0x59cc0c19, 0x80040840,
+	0x04001011, 0x59cc0c1a, 0x80040840, 0x04001011,
+	0x0401f018, 0x4a02621a, 0x00000100, 0x0401f012,
+	0x4a02621a, 0x00000300, 0x0401f00f, 0x4a02621a,
+	0x00000500, 0x0401f00c, 0x4a02621a, 0x00000700,
+	0x0401f009, 0x4a02621a, 0x00000900, 0x0401f006,
+	0x4a02621a, 0x00000f00, 0x0401f003, 0x4a02621a,
+	0x00002d00, 0x82000540, 0x00000001, 0x0401f002,
+	0x80000580, 0x5c000800, 0x1c01f000, 0x59cc0407,
+	0x4803c857, 0x82000580, 0x00000800, 0x04000003,
+	0x4a02621a, 0x00000000, 0x1c01f000, 0x4933c857,
+	0x4c040000, 0x4c080000, 0x4c0c0000, 0x4c580000,
+	0x59cc000c, 0x0201f800, 0x00105c9a, 0x02000800,
+	0x00020245, 0x04020012, 0x83cc1400, 0x00000008,
+	0x4200b000, 0x00000002, 0x83341c00, 0x00000006,
+	0x0201f800, 0x0010855a, 0x04020009, 0x83cc1400,
+	0x0000000a, 0x4200b000, 0x00000002, 0x83341c00,
+	0x00000008, 0x0201f800, 0x0010855a, 0x5c00b000,
+	0x5c001800, 0x5c001000, 0x5c000800, 0x1c01f000,
+	0x4933c857, 0x4c000000, 0x4c040000, 0x4c080000,
+	0x4c0c0000, 0x4c580000, 0x59cc0001, 0x0201f800,
+	0x00105c9a, 0x02000800, 0x00020245, 0x04020014,
+	0x83cc1400, 0x0000000b, 0x4200b000, 0x00000002,
+	0x83341c00, 0x00000006, 0x0201f800, 0x0010855a,
+	0x0402000c, 0x83cc1400, 0x0000000d, 0x4200b000,
+	0x00000002, 0x83341c00, 0x00000008, 0x0201f800,
+	0x0010855a, 0x04000014, 0x4933c856, 0x4933c856,
+	0x4933c857, 0x59340009, 0x4803c857, 0x5934000e,
+	0x4803c857, 0x59340008, 0x4803c857, 0x5934000d,
+	0x4803c857, 0x59340007, 0x4803c857, 0x5934000c,
+	0x4803c857, 0x59340006, 0x4803c857, 0x5934000b,
+	0x4803c857, 0x5c00b000, 0x5c001800, 0x5c001000,
+	0x5c000800, 0x5c000000, 0x1c01f000, 0x4933c857,
+	0x4947c857, 0x4943c857, 0x4c600000, 0x0201f800,
+	0x00106c55, 0x4df00000, 0x4d2c0000, 0x4d300000,
+	0x4d340000, 0x4130c000, 0x42026000, 0x0010d1c0,
+	0x59a8000e, 0x8060c1c0, 0x04000005, 0x82601580,
+	0x0010bde9, 0x04000002, 0x80000040, 0x81640480,
+	0x040210be, 0x40600000, 0x81300580, 0x040000b6,
+	0x0401f97a, 0x040200b4, 0x59326809, 0x59300406,
+	0x82000c80, 0x00000012, 0x02021800, 0x001005d8,
+	0x0c01f001, 0x0010a3cd, 0x0010a338, 0x0010a351,
+	0x0010a35c, 0x0010a335, 0x0010a34c, 0x0010a387,
+	0x0010a3cd, 0x0010a333, 0x0010a39a, 0x0010a3ae,
+	0x0010a333, 0x0010a333, 0x0010a333, 0x0010a333,
+	0x0010a3cd, 0x0010a3c4, 0x0010a3bc, 0x0201f800,
+	0x001005d8, 0x59300420, 0x8c000500, 0x04020096,
+	0x59300403, 0x82000580, 0x00000043, 0x04000092,
+	0x0201f800, 0x00109134, 0x04000007, 0x0201f800,
+	0x0010914e, 0x0402008a, 0x0201f800, 0x0010801c,
+	0x0401f087, 0x0201f800, 0x00102074, 0x0201f800,
+	0x0010914e, 0x02000800, 0x0010801c, 0x0401f080,
+	0x8d3e7d18, 0x04000004, 0x59300420, 0x8c000500,
+	0x0402007d, 0x59325808, 0x0201f800, 0x00109037,
+	0x04000077, 0x49425a06, 0x497a5c09, 0x0201f800,
+	0x000202da, 0x0201f800, 0x0010912a, 0x0401f070,
+	0x8d3e7d00, 0x04000007, 0x59300017, 0x81480580,
+	0x0402006d, 0x59300018, 0x814c0580, 0x0402006a,
+	0x59300203, 0x82000580, 0x00000004, 0x02000800,
+	0x00100e99, 0x59325808, 0x0201f800, 0x00109037,
+	0x0400005f, 0x4a025a04, 0x00000103, 0x59300004,
+	0x8400055c, 0x48026004, 0x592c0408, 0x8c000512,
+	0x04000007, 0x4d2c0000, 0x592c0009, 0x40025800,
+	0x0201f800, 0x001007fd, 0x5c025800, 0x49425a06,
+	0x497a5c09, 0x0401fb16, 0x0201f800, 0x0010959c,
+	0x0201f800, 0x001091c6, 0x0201f800, 0x000202da,
+	0x0201f800, 0x0010912a, 0x0401f045, 0x8d3e7d18,
+	0x04000045, 0x59300203, 0x82000580, 0x00000004,
+	0x02000800, 0x00100e99, 0x59325808, 0x0201f800,
+	0x00109037, 0x0400003a, 0x49425a06, 0x497a5c09,
+	0x0401faff, 0x0201f800, 0x0010959c, 0x0201f800,
+	0x000202da, 0x0401f032, 0x0201f800, 0x001062d5,
+	0x04000031, 0x59300203, 0x82000580, 0x00000004,
+	0x0400002d, 0x59300203, 0x82000580, 0x00000003,
+	0x04020029, 0x0201f800, 0x00106b8a, 0x59325808,
+	0x0201f800, 0x00109037, 0x04000021, 0x0201f800,
+	0x000202da, 0x0401f01e, 0x59300203, 0x82000580,
+	0x00000004, 0x02000800, 0x00100e99, 0x59325808,
+	0x0201f800, 0x00109037, 0x04000015, 0x49425a06,
+	0x497a5c09, 0x0201f800, 0x000202da, 0x0401f010,
+	0x833c0500, 0x00001800, 0x0400000f, 0x8d3e7d16,
+	0x0402000d, 0x59325817, 0x0201f800, 0x001007fd,
+	0x59325808, 0x0201f800, 0x00109037, 0x04000004,
+	0x49425a06, 0x0201f800, 0x000202da, 0x0201f800,
+	0x00107911, 0x83326400, 0x00000024, 0x41580000,
+	0x81300480, 0x0400173b, 0x5c026800, 0x5c026000,
+	0x5c025800, 0x5c03e000, 0x02000800, 0x00106c4b,
+	0x5c00c000, 0x1c01f000, 0x5c000000, 0x4c000000,
+	0x4803c857, 0x4d3c0000, 0x42027800, 0x00000001,
+	0x0201f800, 0x00104567, 0x5c027800, 0x4c580000,
+	0x4200b000, 0x00000002, 0x83a81c00, 0x00000002,
+	0x83cc1400, 0x0000000b, 0x0201f800, 0x0010855a,
+	0x5c00b000, 0x80000540, 0x1c01f000, 0x492fc857,
+	0x4943c857, 0x59a8000c, 0x812c0480, 0x04001011,
+	0x59a8000d, 0x812c0480, 0x0402100e, 0x592c0000,
+	0x80005d40, 0x04000008, 0x497a5800, 0x49425a06,
+	0x4c2c0000, 0x0201f800, 0x000202da, 0x5c025800,
+	0x0401f7f7, 0x49425a06, 0x0201f000, 0x000202da,
+	0x1c01f000, 0x493fc857, 0x4933c857, 0x480bc857,
+	0x0201f800, 0x00103b25, 0x0400002e, 0x41502800,
+	0x813e79c0, 0x04020006, 0x59a80066, 0x80000000,
+	0x59a8086a, 0x80040580, 0x04000026, 0x41300000,
+	0x80140580, 0x0400001a, 0x58140203, 0x82000580,
+	0x00000000, 0x04000016, 0x58140202, 0x80080580,
+	0x04020013, 0x58141c06, 0x820c0580, 0x00000005,
+	0x0400000f, 0x820c0580, 0x00000009, 0x04000017,
+	0x59300009, 0x58142009, 0x801021c0, 0x04020006,
+	0x5814201e, 0x59301809, 0x580c0002, 0x82000500,
+	0x00ffffff, 0x80100580, 0x04000007, 0x82142c00,
+	0x00000024, 0x41540000, 0x80140480, 0x04021005,
+	0x0401f7df, 0x40163800, 0x81300540, 0x0401f002,
+	0x80000580, 0x1c01f000, 0x58141807, 0x8c0c1d10,
+	0x040207f3, 0x0401f7e7, 0x42002000, 0x0000ffff,
+	0x59301009, 0x800811c0, 0x04000002, 0x58082403,
+	0x41301000, 0x0401f007, 0x41781000, 0x41442000,
+	0x0401f004, 0x41781000, 0x42002000, 0x0000ffff,
+	0x5c000000, 0x4c000000, 0x4803c857, 0x480bc857,
+	0x4813c857, 0x492fc857, 0x4943c857, 0x4d2c0000,
+	0x0201f800, 0x001007e4, 0x02000800, 0x001005d8,
+	0x4a025a04, 0x0000010d, 0x800811c0, 0x04000017,
+	0x83400580, 0x00000029, 0x04020010, 0x82180580,
+	0x00000002, 0x0400000a, 0x82180580, 0x00000003,
+	0x04000007, 0x82180580, 0x00000008, 0x04000004,
+	0x82180580, 0x00000009, 0x04020004, 0x4a025809,
+	0xffffffff, 0x0401f002, 0x480a5809, 0x58080202,
+	0x48025c13, 0x0401f005, 0x4a025809, 0xffffffff,
+	0x4a025c13, 0x0000ffff, 0x49425a08, 0x48125a06,
+	0x82100580, 0x0000ffff, 0x0400000e, 0x4d440000,
+	0x4d340000, 0x40128800, 0x0201f800, 0x00020245,
+	0x02020800, 0x001005d8, 0x59340002, 0x82000500,
+	0x00ffffff, 0x48025812, 0x5c026800, 0x5c028800,
+	0x497a5800, 0x497a5c04, 0x83400580, 0x00000046,
+	0x04020002, 0x48165a07, 0x481a5c08, 0x0401fbed,
+	0x5c025800, 0x1c01f000, 0x59300809, 0x800409c0,
+	0x04000004, 0x58040403, 0x81440580, 0x1c01f000,
+	0x82000540, 0x00000001, 0x0401f7fd, 0x4933c857,
+	0x4c040000, 0x59300403, 0x82000d80, 0x0000001e,
+	0x04020016, 0x800000d0, 0x59300a16, 0x82040d00,
+	0x000000ff, 0x80040540, 0x4803c857, 0x48026416,
+	0x4a026403, 0x00000085, 0x4a026203, 0x00000009,
+	0x4a026406, 0x00000005, 0x4a02621d, 0x00000004,
+	0x59a80038, 0x48026206, 0x42000800, 0x8000004b,
+	0x0201f800, 0x00020721, 0x5c000800, 0x1c01f000,
+	0x4933c857, 0x40000000, 0x40000000, 0x1c01f000,
+	0x59300414, 0x4933c857, 0x4803c857, 0x8c000518,
+	0x04000009, 0x8c000512, 0x02020000, 0x0010921e,
+	0x0401f91b, 0x0201f800, 0x000206fd, 0x0201f800,
+	0x0002077d, 0x1c01f000, 0x591c0406, 0x4803c857,
+	0x82000c80, 0x00000009, 0x0402100b, 0x0c01f001,
+	0x0010a4d9, 0x0010a4d9, 0x0010a4d9, 0x0010a4db,
+	0x0010a4d9, 0x0010a4db, 0x0010a4db, 0x0010a4d9,
+	0x0010a4db, 0x80000580, 0x1c01f000, 0x82000540,
+	0x00000001, 0x1c01f000, 0x591c0406, 0x82000500,
+	0x0000001f, 0x82000580, 0x00000006, 0x0400000e,
+	0x4803c857, 0x4a026403, 0x0000003b, 0x4a02641a,
+	0x00000009, 0x4a02621a, 0x00002a00, 0x4a026203,
+	0x00000001, 0x42000800, 0x80000040, 0x0201f000,
+	0x00020721, 0x4803c856, 0x4c040000, 0x4c140000,
+	0x4d300000, 0x411e6000, 0x0401f8e9, 0x497a6205,
+	0x59300414, 0x4803c857, 0x82000500, 0xffffadff,
+	0x48026414, 0x497a6405, 0x5c026000, 0x0201f800,
+	0x001007e4, 0x02000800, 0x001005d8, 0x5c002800,
+	0x5c000800, 0x4a025a04, 0x0000010d, 0x497a5800,
+	0x497a5c04, 0x4a025a08, 0x00000045, 0x491e5809,
+	0x59300402, 0x48025c07, 0x59300419, 0x48025c0b,
+	0x591c0414, 0x84000556, 0x48023c14, 0x591c1809,
+	0x580c0403, 0x48025a06, 0x4816580a, 0x48065a0b,
+	0x0401f99d, 0x4d400000, 0x42028000, 0x00000045,
+	0x591c0202, 0x4c000000, 0x4d300000, 0x411e6000,
+	0x0401fcb1, 0x5c026000, 0x5c000000, 0x48023a02,
+	0x5c028000, 0x4a023c06, 0x00000006, 0x4a023a03,
+	0x00000007, 0x497a3a06, 0x497a3a05, 0x1c01f000,
+	0x4933c857, 0x83380580, 0x00000013, 0x0402000b,
+	0x59300403, 0x4803c857, 0x82000d80, 0x00000085,
+	0x0400002b, 0x82000d80, 0x0000008b, 0x04000028,
+	0x0201f800, 0x001005d8, 0x83380580, 0x00000027,
+	0x0402000c, 0x0201f800, 0x00106bbf, 0x4d2c0000,
+	0x4d400000, 0x59325808, 0x42028000, 0x00000004,
+	0x0401feab, 0x5c028000, 0x5c025800, 0x1c01f000,
+	0x83380580, 0x00000014, 0x040007f3, 0x83380580,
+	0x00000089, 0x04000005, 0x83380580, 0x0000008a,
+	0x02020000, 0x00107974, 0x0201f800, 0x00106f60,
+	0x02020000, 0x00107974, 0x59300a03, 0x82040580,
+	0x0000000a, 0x04000009, 0x82040580, 0x0000000c,
+	0x04000006, 0x0201f800, 0x001005d8, 0x4a026203,
+	0x0000000a, 0x1c01f000, 0x83380480, 0x00000093,
+	0x0402100c, 0x83380480, 0x00000085, 0x04001009,
+	0x83380580, 0x00000089, 0x0400000a, 0x83380580,
+	0x0000008a, 0x04000022, 0x0201f800, 0x001005d8,
+	0x493bc857, 0x4933c857, 0x0201f000, 0x00107974,
+	0x4933c857, 0x4c340000, 0x41306800, 0x0201f800,
+	0x0002075a, 0x04000011, 0x4a026203, 0x00000001,
+	0x4a026403, 0x0000001e, 0x59cc0c07, 0x48066419,
+	0x59cc0a07, 0x48066219, 0x58340809, 0x48066009,
+	0x4a026406, 0x00000004, 0x42000800, 0x80000040,
+	0x0201f800, 0x00020721, 0x40366000, 0x0201f800,
+	0x0002077d, 0x5c006800, 0x1c01f000, 0x4933c857,
+	0x0201f000, 0x0002077d, 0x4933c857, 0x59300809,
+	0x58040200, 0x8c00051a, 0x1c01f000, 0x0201f800,
+	0x001048df, 0x0400001e, 0x4a026203, 0x00000002,
+	0x59300414, 0x84000558, 0x48026414, 0x8c000512,
+	0x04000004, 0x59a80039, 0x48026205, 0x0401f007,
+	0x59a80839, 0x59a80037, 0x80040400, 0x82000400,
+	0x0000000a, 0x48026205, 0x59300009, 0x82000c00,
+	0x00000011, 0x50040000, 0x80000540, 0x04000004,
+	0x82000c00, 0x00000000, 0x0401f7fb, 0x45300800,
+	0x497a6000, 0x82000540, 0x00000001, 0x1c01f000,
+	0x82100500, 0xfffffeef, 0x04020020, 0x4d2c0000,
+	0x4937c857, 0x59340811, 0x83341400, 0x00000011,
+	0x800409c0, 0x0400000e, 0x40040000, 0x81300580,
+	0x04000005, 0x58040800, 0x82041400, 0x00000000,
+	0x0401f7f8, 0x59300800, 0x497a6000, 0x44041000,
+	0x0201f800, 0x000206fd, 0x0401f002, 0x4933c857,
+	0x592c0000, 0x80000540, 0x02020800, 0x001005d8,
+	0x5c025800, 0x492e6008, 0x0201f800, 0x000206fd,
+	0x0201f000, 0x0002077d, 0x492fc857, 0x4a025a06,
+	0x00000006, 0x0201f000, 0x000202da, 0x4c340000,
+	0x59300009, 0x800001c0, 0x04000010, 0x82006c00,
+	0x00000011, 0x50340000, 0x80000540, 0x04000009,
+	0x81300580, 0x04000005, 0x50340000, 0x82006c00,
+	0x00000000, 0x0401f7f8, 0x59300000, 0x44006800,
+	0x5c006800, 0x1c01f000, 0x59300c06, 0x82040580,
+	0x00000005, 0x040007fb, 0x82040580, 0x00000011,
+	0x040007f8, 0x82040580, 0x00000006, 0x040007f5,
+	0x82040580, 0x00000001, 0x040007f2, 0x0201f800,
+	0x001005d8, 0x4933c857, 0x4c080000, 0x4c0c0000,
+	0x4c580000, 0x59a8101d, 0x59cc1807, 0x820c1d00,
+	0x00ffffff, 0x800c0110, 0x80083580, 0x04020014,
+	0x83cc1400, 0x00000008, 0x4200b000, 0x00000002,
+	0x59300009, 0x82001c00, 0x00000006, 0x0201f800,
+	0x0010855a, 0x0402000a, 0x83cc1400, 0x0000000a,
+	0x4200b000, 0x00000002, 0x59300009, 0x82001c00,
+	0x00000008, 0x0201f800, 0x0010855a, 0x5c00b000,
+	0x5c001800, 0x5c001000, 0x1c01f000, 0x4933c856,
+	0x0201f800, 0x0010421b, 0x0201f000, 0x00101e45,
+	0x493bc857, 0x4d2c0000, 0x0201f800, 0x001007e4,
+	0x02000800, 0x001005d8, 0x832cac00, 0x00000005,
+	0x4c580000, 0x4c540000, 0x4200b000, 0x00000006,
+	0x4578a800, 0x8054a800, 0x8058b040, 0x040207fd,
+	0x83380580, 0x00000046, 0x04020004, 0x4a025a04,
+	0x00000144, 0x0401f008, 0x4a025a04, 0x00000146,
+	0x83380580, 0x00000041, 0x04000003, 0x4a025a06,
+	0x00000001, 0x59cc0007, 0x82000500, 0xff000000,
+	0x80000110, 0x59cc1008, 0x82081500, 0xff000000,
+	0x80081540, 0x480a580a, 0x83380580, 0x00000046,
+	0x04020006, 0x59cc0007, 0x82000500, 0x00ffffff,
+	0x4802580b, 0x0401f005, 0x59cc0008, 0x82000500,
+	0x00ffffff, 0x4802580b, 0x83380580, 0x00000046,
+	0x04020004, 0x83cc1400, 0x00000009, 0x0401f003,
+	0x83cc1400, 0x0000000d, 0x50080000, 0x9c0001c0,
+	0x4802580c, 0x80081000, 0x50080000, 0x9c0001c0,
+	0x4802580d, 0x83380580, 0x00000046, 0x04020008,
+	0x59cc000b, 0x9c0001c0, 0x4802580e, 0x59cc000c,
+	0x9c0001c0, 0x4802580f, 0x0401f007, 0x59cc000f,
+	0x9c0001c0, 0x4802580e, 0x59cc0010, 0x9c0001c0,
+	0x4802580f, 0x83380580, 0x00000046, 0x04020004,
+	0x83cc1400, 0x00000011, 0x0401f003, 0x83cc1400,
+	0x00000015, 0x412c3000, 0x82183400, 0x00000010,
+	0x4200b000, 0x00000004, 0x50080000, 0x9c0001c0,
+	0x44003000, 0x80081000, 0x80183000, 0x8058b040,
+	0x040207fa, 0x5c00a800, 0x5c00b000, 0x0201f800,
+	0x000202da, 0x5c025800, 0x1c01f000, 0x4933c857,
+	0x492fc857, 0x59300809, 0x58040200, 0x8c00051e,
+	0x04000004, 0x592c0208, 0x84000558, 0x48025a08,
+	0x1c01f000, 0x59e0180f, 0x599c0413, 0x800c1000,
+	0x80080580, 0x04020002, 0x41781000, 0x59e00010,
+	0x59e00810, 0x80040d80, 0x040207fd, 0x80080580,
+	0x0400000b, 0x4c080000, 0x599c0814, 0x599c1015,
+	0x800c00cc, 0x80040c00, 0x82081440, 0x00000000,
+	0x5c001800, 0x82000540, 0x00000001, 0x4803c857,
+	0x1c01f000, 0x492fc857, 0x42007000, 0x0010b7f8,
+	0x58380807, 0x800409c0, 0x04020005, 0x492c7008,
+	0x492c7007, 0x0201f000, 0x00100875, 0x492c0800,
+	0x492c7007, 0x1c01f000, 0x59300203, 0x4933c857,
+	0x4937c857, 0x493bc857, 0x4803c857, 0x82003480,
+	0x0000000e, 0x02021800, 0x001005d8, 0x0c01f001,
+	0x0010a6da, 0x0010a82c, 0x0010a6da, 0x0010a6da,
+	0x0010a6da, 0x0010a6da, 0x0010a6da, 0x0010a791,
+	0x0010a6dc, 0x0010a6da, 0x0010a6da, 0x0010a6da,
+	0x0010a6da, 0x0010a6da, 0x0201f800, 0x001005d8,
+	0x83380580, 0x0000004c, 0x02020800, 0x001005d8,
+	0x0201f800, 0x001048ec, 0x04020020, 0x59a80826,
+	0x82040500, 0x00000009, 0x82000580, 0x00000008,
+	0x0400001a, 0x8c040d12, 0x0400003d, 0x59cc0806,
+	0x82040d00, 0xff000000, 0x82040580, 0x03000000,
+	0x0400001f, 0x82040580, 0x50000000, 0x04000005,
+	0x82040580, 0x52000000, 0x02020000, 0x0002077d,
+	0x813669c0, 0x04000006, 0x4d3c0000, 0x417a7800,
+	0x0201f800, 0x0010203c, 0x5c027800, 0x4a026403,
+	0x00000001, 0x0401f014, 0x59cc0806, 0x82040d00,
+	0xff000000, 0x82040580, 0x03000000, 0x04000008,
+	0x82040580, 0x50000000, 0x04000005, 0x82040580,
+	0x52000000, 0x02020000, 0x0002077d, 0x4a026403,
+	0x00000009, 0x4a02641a, 0x00000009, 0x4a02621a,
+	0x00000000, 0x813669c0, 0x0402000b, 0x59cc0001,
+	0x0201f800, 0x00105c9a, 0x02020000, 0x0002077d,
+	0x0201f800, 0x001045a6, 0x02020000, 0x0002077d,
+	0x49366009, 0x4a026406, 0x00000004, 0x4a026203,
+	0x00000001, 0x0201f000, 0x0010672b, 0x0201f800,
+	0x00103b25, 0x04000023, 0x59cc0806, 0x4807c857,
+	0x82040d00, 0xff000000, 0x82040580, 0x03000000,
+	0x04000033, 0x82040580, 0x20000000, 0x04000041,
+	0x82040580, 0x21000000, 0x04000052, 0x82040580,
+	0x24000000, 0x0400004f, 0x82040580, 0x50000000,
+	0x0400004c, 0x82040580, 0x52000000, 0x04000049,
+	0x82040580, 0x05000000, 0x0402000d, 0x59cc0806,
+	0x82040d00, 0xff000000, 0x9c0431c0, 0x42028000,
+	0x00000046, 0x42002800, 0x00000001, 0x0401fcf3,
+	0x0401f93c, 0x02000800, 0x001005d8, 0x42002000,
+	0x00000051, 0x0201f800, 0x00107a4a, 0x59cc0000,
+	0x82000500, 0x00ffffff, 0x82000580, 0x00ffffff,
+	0x04000005, 0x4a026203, 0x00000007, 0x493a6403,
+	0x1c01f000, 0x59325817, 0x812e59c0, 0x02020800,
+	0x001007fd, 0x0201f000, 0x0002077d, 0x813669c0,
+	0x040007df, 0x59340400, 0x82000500, 0x000000ff,
+	0x82000580, 0x00000003, 0x040207d9, 0x0401fc6f,
+	0x040207d7, 0x4a026403, 0x00000009, 0x4a02641a,
+	0x0000000e, 0x4a02621a, 0x00001900, 0x0401f7a2,
+	0x813669c0, 0x0400000c, 0x59340c00, 0x82040500,
+	0x000000ff, 0x82000580, 0x00000009, 0x04000794,
+	0x82040500, 0x0000ff00, 0x82000580, 0x00000700,
+	0x040207c3, 0x4a026403, 0x00000009, 0x4a02641a,
+	0x00000009, 0x4a02621a, 0x00001e00, 0x0401f78e,
+	0x813669c0, 0x040007f8, 0x59340c00, 0x82040500,
+	0x0000ff00, 0x82000580, 0x00000700, 0x040007f2,
+	0x0401f7b3, 0x4d2c0000, 0x4c580000, 0x4c500000,
+	0x4c540000, 0x41385000, 0x83380580, 0x00000054,
+	0x02020800, 0x001005d8, 0x59325808, 0x592c0c0b,
+	0x82040d00, 0x0000e000, 0x82040580, 0x00002000,
+	0x04020076, 0x59300817, 0x800409c0, 0x04000014,
+	0x58041404, 0x41cca800, 0x8204a400, 0x00000005,
+	0x82080480, 0x00000010, 0x04021004, 0x4008b000,
+	0x0401fb6b, 0x0401f00a, 0x40001000, 0x4200b000,
+	0x0000000f, 0x0401fb66, 0x58040801, 0x800409c0,
+	0x040207f2, 0x0201f800, 0x001005d8, 0x813669c0,
+	0x0400005e, 0x59344c00, 0x592c0c09, 0x4807c857,
+	0x4827c857, 0x82040d00, 0x000000ff, 0x82040580,
+	0x00000003, 0x0400002a, 0x82040580, 0x00000005,
+	0x04000032, 0x82040580, 0x00000020, 0x04000036,
+	0x82040580, 0x00000052, 0x04000042, 0x82040580,
+	0x00000050, 0x04000042, 0x82040580, 0x00000021,
+	0x04000004, 0x82040580, 0x00000024, 0x04020043,
+	0x82240500, 0x0000ff00, 0x82000580, 0x00000007,
+	0x04000008, 0x42000800, 0x00000009, 0x0201f800,
+	0x00104571, 0x42005000, 0x0000000c, 0x0401f037,
+	0x4a025a06, 0x00000031, 0x4a02580d, 0x00000009,
+	0x59340400, 0x4802580e, 0x0201f800, 0x000202da,
+	0x0201f800, 0x00107911, 0x0401f03d, 0x0201f800,
+	0x001042b4, 0x0201f800, 0x0010462a, 0x42000800,
+	0x00000003, 0x0201f800, 0x00104571, 0x42005000,
+	0x00000008, 0x0401f021, 0x59cc0007, 0x0201f800,
+	0x00105eec, 0x0402001d, 0x0201f800, 0x001042b4,
+	0x0401f01a, 0x82240500, 0x0000ff00, 0x82000580,
+	0x00000007, 0x040007df, 0x82240500, 0x000000ff,
+	0x82000580, 0x00000009, 0x040007da, 0x0201f800,
+	0x0010468d, 0x42005000, 0x0000000a, 0x0401f00b,
+	0x42005000, 0x0000000e, 0x0401f003, 0x42005000,
+	0x00000010, 0x82240500, 0x0000ff00, 0x82000580,
+	0x00000007, 0x040007cb, 0x482a6403, 0x4a026203,
+	0x00000001, 0x592c000d, 0x48026011, 0x497a6013,
+	0x59a80038, 0x48026206, 0x417a7800, 0x0201f800,
+	0x0010672b, 0x59325817, 0x812e59c0, 0x04000004,
+	0x0201f800, 0x001007fd, 0x497a6017, 0x5c00a800,
+	0x5c00a000, 0x5c00b000, 0x5c025800, 0x1c01f000,
+	0x4d2c0000, 0x59325808, 0x83380580, 0x00000013,
+	0x04020029, 0x59300c03, 0x82040580, 0x00000054,
+	0x0400001e, 0x82040580, 0x00000010, 0x04000018,
+	0x82040580, 0x0000000e, 0x04000015, 0x82040580,
+	0x00000008, 0x0400000d, 0x82040580, 0x0000000c,
+	0x0400000a, 0x82040580, 0x0000000a, 0x02020800,
+	0x001005d8, 0x42000800, 0x00000006, 0x0201f800,
+	0x00104571, 0x0401f009, 0x42000800, 0x00000004,
+	0x0201f800, 0x00104571, 0x0401f004, 0x59340200,
+	0x8400051a, 0x48026a00, 0x4a025a06, 0x00000000,
+	0x0201f800, 0x000202da, 0x0201f800, 0x0002077d,
+	0x0401f022, 0x83380580, 0x00000027, 0x0400000e,
+	0x83380580, 0x00000014, 0x02020800, 0x001005d8,
+	0x0201f800, 0x00106bbf, 0x42028000, 0x00000031,
+	0x42000800, 0x00000004, 0x42001000, 0x000000ff,
+	0x0401f009, 0x0201f800, 0x00106bbf, 0x42028000,
+	0x00000031, 0x42000800, 0x00000004, 0x42001000,
+	0x00000010, 0x49425a06, 0x4806580d, 0x480a580e,
+	0x0201f800, 0x000202da, 0x0201f800, 0x00104c19,
+	0x0201f800, 0x00107911, 0x5c025800, 0x1c01f000,
+	0x42007000, 0x0010b7f8, 0x58380807, 0x800409c0,
+	0x04020005, 0x492c7008, 0x492c7007, 0x0201f000,
+	0x00100875, 0x492c0800, 0x492c7007, 0x1c01f000,
+	0x4d2c0000, 0x4c580000, 0x4c500000, 0x4c540000,
+	0x4933c857, 0x4937c857, 0x59cc0806, 0x4807c857,
+	0x82040d00, 0xff000000, 0x82040580, 0x03000000,
+	0x0400000d, 0x82040580, 0x05000000, 0x0400000a,
+	0x82040580, 0x21000000, 0x04000030, 0x82040580,
+	0x24000000, 0x0400002d, 0x82040580, 0x20000000,
+	0x0402002f, 0x0201f800, 0x001007e4, 0x0400002c,
+	0x492fc857, 0x492e6017, 0x59a8b016, 0x8258b400,
+	0x0000001b, 0x8258b500, 0xfffffffc, 0x8058b104,
+	0x485a5c04, 0x412c7800, 0x41cca000, 0x82580480,
+	0x00000010, 0x04021005, 0x832cac00, 0x00000005,
+	0x0401fa63, 0x0401f015, 0x40580800, 0x4200b000,
+	0x0000000f, 0x832cac00, 0x00000005, 0x0401fa5c,
+	0x8204b480, 0x0000000f, 0x0201f800, 0x001007e4,
+	0x04000004, 0x492c7801, 0x412c7800, 0x0401f7ec,
+	0x59325817, 0x0201f800, 0x001007fd, 0x497a6017,
+	0x80000580, 0x0401f006, 0x59340200, 0x84000554,
+	0x48026a00, 0x82000540, 0x00000001, 0x5c00a800,
+	0x5c00a000, 0x5c00b000, 0x5c025800, 0x1c01f000,
+	0x4933c857, 0x492fc857, 0x4d2c0000, 0x59300a03,
+	0x82040580, 0x00000007, 0x04000036, 0x82040580,
+	0x00000001, 0x02020800, 0x001005d8, 0x0201f800,
+	0x00106c55, 0x4df00000, 0x598c000d, 0x81300580,
+	0x04020016, 0x59300004, 0x8c000520, 0x04000004,
+	0x84000520, 0x48026004, 0x0401f016, 0x42001000,
+	0x0010b7f6, 0x50081000, 0x58080002, 0x82000580,
+	0x00000100, 0x04000006, 0x5808000c, 0x81300580,
+	0x02020800, 0x001005d8, 0x0401f00a, 0x0201f800,
+	0x00106e8e, 0x04020020, 0x59300004, 0x8c000520,
+	0x04000004, 0x84000520, 0x48026004, 0x0401f003,
+	0x0201f800, 0x001068d3, 0x5c03e000, 0x02000800,
+	0x00106c4b, 0x0201f800, 0x00109037, 0x02000800,
+	0x001005d8, 0x59325808, 0x4a025a06, 0x00000005,
+	0x0201f800, 0x000202da, 0x0201f800, 0x00104c19,
+	0x59325817, 0x812e59c0, 0x02020800, 0x001007fd,
+	0x0201f800, 0x00107911, 0x80000580, 0x5c025800,
+	0x1c01f000, 0x5c03e000, 0x02000800, 0x00106c4b,
+	0x59300406, 0x82000580, 0x00000011, 0x040007b8,
+	0x0401f7f7, 0x4c040000, 0x59340200, 0x4803c857,
+	0x8c00051c, 0x04000009, 0x59cc0805, 0x591c0019,
+	0x4803c857, 0x80040580, 0x04000004, 0x80000580,
+	0x4803c856, 0x0401f003, 0x82000540, 0x00000001,
+	0x5c000800, 0x1c01f000, 0x4c000000, 0x4c0c0000,
+	0x4c100000, 0x42001800, 0x0000ffff, 0x42002000,
+	0x00000004, 0x0401f010, 0x4c000000, 0x4c0c0000,
+	0x4c100000, 0x59302009, 0x58101c03, 0x42002000,
+	0x00000004, 0x0401f008, 0x4c000000, 0x4c0c0000,
+	0x4c100000, 0x59302009, 0x58101c03, 0x42002000,
+	0x00000007, 0x480fc857, 0x4813c857, 0x481bc857,
+	0x0201f800, 0x00103aae, 0x5c002000, 0x5c001800,
+	0x5c000000, 0x1c01f000, 0x83380580, 0x00000092,
+	0x02020800, 0x001005d8, 0x42000800, 0x80000040,
+	0x4a026203, 0x00000001, 0x493a6403, 0x0201f000,
+	0x00020721, 0x4d400000, 0x0201f800, 0x00103b25,
+	0x04000008, 0x59a80005, 0x84000544, 0x48035005,
+	0x42028000, 0x0000002a, 0x0201f800, 0x0010a449,
+	0x5c028000, 0x1c01f000, 0x59a80026, 0x8c000508,
+	0x04000005, 0x599c0017, 0x8c00050a, 0x04020002,
+	0x1c01f000, 0x82000540, 0x00000001, 0x1c01f000,
+	0x59300420, 0x84000540, 0x48026420, 0x1c01f000,
+	0x4817c857, 0x4c000000, 0x4c040000, 0x8c142d2a,
+	0x04000004, 0x598800b8, 0x80000000, 0x480310b8,
+	0x8c142d2e, 0x04000004, 0x598800b9, 0x80000000,
+	0x480310b9, 0x8c142d2c, 0x04000013, 0x40140000,
+	0x82000500, 0x00070000, 0x82000d80, 0x00030000,
+	0x0400000d, 0x82000d80, 0x00040000, 0x0400000a,
+	0x82000d80, 0x00050000, 0x04000007, 0x59880005,
+	0x80000000, 0x48031005, 0x598800ba, 0x80000000,
+	0x480310ba, 0x5c000800, 0x5c000000, 0x1c01f000,
+	0x4817c857, 0x4c000000, 0x4c040000, 0x8c142d2a,
+	0x04000004, 0x598800bb, 0x80000000, 0x480310bb,
+	0x8c142d2e, 0x04000004, 0x598800bc, 0x80000000,
+	0x480310bc, 0x8c142d2c, 0x04000013, 0x40140000,
+	0x82000500, 0x00070000, 0x82000d80, 0x00030000,
+	0x0400000d, 0x82000d80, 0x00040000, 0x0400000a,
+	0x82000d80, 0x00050000, 0x04000007, 0x59880005,
+	0x80000000, 0x48031005, 0x598800bd, 0x80000000,
+	0x480310bd, 0x5c000800, 0x5c000000, 0x1c01f000,
+	0x4c000000, 0x59880001, 0x80000000, 0x4803c857,
+	0x48031001, 0x5c000000, 0x1c01f000, 0x4c000000,
+	0x59880000, 0x80000000, 0x4803c857, 0x48031000,
+	0x5c000000, 0x1c01f000, 0x4c000000, 0x59880002,
+	0x80000000, 0x4803c857, 0x48031002, 0x5c000000,
+	0x1c01f000, 0x4807c857, 0x4c000000, 0x8c040d2c,
+	0x04000004, 0x598800a6, 0x80000000, 0x480310a6,
+	0x8c040d2a, 0x04000004, 0x598800a7, 0x80000000,
+	0x480310a7, 0x8c040d28, 0x04000004, 0x598800a8,
+	0x80000000, 0x480310a8, 0x8c040d26, 0x04000004,
+	0x598800a9, 0x80000000, 0x480310a9, 0x8c040d24,
+	0x04000004, 0x598800aa, 0x80000000, 0x480310aa,
+	0x8c040d22, 0x04000004, 0x598800ab, 0x80000000,
+	0x480310ab, 0x8c040d20, 0x04000004, 0x598800ac,
+	0x80000000, 0x480310ac, 0x5c000000, 0x1c01f000,
+	0x4807c857, 0x4c000000, 0x598800ad, 0x80000000,
+	0x480310ad, 0x5c000000, 0x1c01f000, 0x4807c857,
+	0x4c000000, 0x8c040d1c, 0x04000004, 0x598800ae,
+	0x80000000, 0x480310ae, 0x8c040d1a, 0x04000004,
+	0x598800af, 0x80000000, 0x480310af, 0x5c000000,
+	0x1c01f000, 0x4807c857, 0x4c000000, 0x8c040d18,
+	0x04000004, 0x598800b0, 0x80000000, 0x480310b0,
+	0x8c040d16, 0x04000004, 0x598800b1, 0x80000000,
+	0x480310b1, 0x8c040d14, 0x04000004, 0x598800b2,
+	0x80000000, 0x480310b2, 0x5c000000, 0x1c01f000,
+	0x4807c857, 0x4c000000, 0x8c040d10, 0x04000004,
+	0x598800b3, 0x80000000, 0x480310b3, 0x8c040d0c,
+	0x04000004, 0x598800b4, 0x80000000, 0x480310b4,
+	0x5c000000, 0x1c01f000, 0x4807c857, 0x4c000000,
+	0x8c040d08, 0x04000004, 0x598800b5, 0x80000000,
+	0x480310b5, 0x8c040d04, 0x04000004, 0x598800b6,
+	0x80000000, 0x480310b6, 0x5c000000, 0x1c01f000,
+	0x4807c856, 0x4c000000, 0x5988007f, 0x80000000,
+	0x4803107f, 0x5c000000, 0x1c01f000, 0x4803c857,
+	0x4c040000, 0x50000800, 0x80040800, 0x4807c857,
+	0x44040000, 0x5c000800, 0x1c01f000, 0x480fc857,
+	0x4c000000, 0x820c0580, 0x00000000, 0x04020004,
+	0x42000000, 0x0010b819, 0x0401f014, 0x820c0580,
+	0x00001001, 0x04020004, 0x42000000, 0x0010b81a,
+	0x0401f00e, 0x820c0580, 0x00001002, 0x04020004,
+	0x42000000, 0x0010b81b, 0x0401f008, 0x820c0c80,
+	0x0000201c, 0x02021800, 0x001005d8, 0x820c0500,
+	0x0000001f, 0x0c01f804, 0x0401ffdd, 0x5c000000,
+	0x1c01f000, 0x0010aa89, 0x0010aa8c, 0x0010aa8f,
+	0x0010aa92, 0x0010aa95, 0x0010aa98, 0x0010aa9b,
+	0x0010aa9e, 0x0010aaa1, 0x0010aaa4, 0x0010aaa7,
+	0x0010aaaa, 0x0010aaad, 0x0010aab0, 0x0010aab3,
+	0x0010aab6, 0x0010aab9, 0x0010aabc, 0x0010aabf,
+	0x0010aac2, 0x0010aac5, 0x0010aac8, 0x0010aacb,
+	0x0010aace, 0x0010aad1, 0x0010aad4, 0x0010aad7,
+	0x0010aada, 0x42000000, 0x0010b81c, 0x1c01f000,
+	0x42000000, 0x0010b81d, 0x1c01f000, 0x42000000,
+	0x0010b81e, 0x1c01f000, 0x42000000, 0x0010b81f,
+	0x1c01f000, 0x42000000, 0x0010b820, 0x1c01f000,
+	0x42000000, 0x0010b821, 0x1c01f000, 0x42000000,
+	0x0010b822, 0x1c01f000, 0x42000000, 0x0010b823,
+	0x1c01f000, 0x42000000, 0x0010b824, 0x1c01f000,
+	0x42000000, 0x0010b825, 0x1c01f000, 0x42000000,
+	0x0010b826, 0x1c01f000, 0x42000000, 0x0010b827,
+	0x1c01f000, 0x42000000, 0x0010b828, 0x1c01f000,
+	0x42000000, 0x0010b829, 0x1c01f000, 0x42000000,
+	0x0010b82a, 0x1c01f000, 0x42000000, 0x0010b82b,
+	0x1c01f000, 0x42000000, 0x0010b82c, 0x1c01f000,
+	0x42000000, 0x0010b82d, 0x1c01f000, 0x42000000,
+	0x0010b82e, 0x1c01f000, 0x42000000, 0x0010b82f,
+	0x1c01f000, 0x42000000, 0x0010b830, 0x1c01f000,
+	0x42000000, 0x0010b831, 0x1c01f000, 0x42000000,
+	0x0010b832, 0x1c01f000, 0x42000000, 0x0010b833,
+	0x1c01f000, 0x42000000, 0x0010b834, 0x1c01f000,
+	0x42000000, 0x0010b835, 0x1c01f000, 0x42000000,
+	0x0010b836, 0x1c01f000, 0x42000000, 0x0010b837,
+	0x1c01f000, 0x480fc857, 0x4c000000, 0x820c0580,
+	0x00000001, 0x04020004, 0x42000000, 0x0010b80e,
+	0x0401f012, 0x820c0580, 0x00000002, 0x04020004,
+	0x42000000, 0x0010b80f, 0x0401f00c, 0x820c0580,
+	0x00000003, 0x04020004, 0x42000000, 0x0010b810,
+	0x0401f006, 0x820c0580, 0x00000004, 0x04020004,
+	0x42000000, 0x0010b811, 0x0401ff51, 0x5c000000,
+	0x1c01f000, 0x4c000000, 0x59a80026, 0x4803c857,
+	0x8c000502, 0x04000010, 0x8c000506, 0x04000004,
+	0x42000000, 0x0010b841, 0x0401f012, 0x8c00050a,
+	0x04000004, 0x42000000, 0x0010b840, 0x0401f00d,
+	0x8c000508, 0x04000004, 0x42000000, 0x0010b843,
+	0x0401f008, 0x0201f800, 0x0010513b, 0x04000006,
+	0x8c000506, 0x04020004, 0x42000000, 0x0010b842,
+	0x0401ff33, 0x5c000000, 0x1c01f000, 0x8058b1c0,
+	0x02000800, 0x001005d8, 0x5450a800, 0x8050a000,
+	0x8054a800, 0x8058b040, 0x040207fc, 0x1c01f000,
+	0x8058b1c0, 0x02000800, 0x001005d8, 0x4450a800,
+	0x8054a800, 0x8058b040, 0x040207fd, 0x1c01f000,
+	0x8058b1c0, 0x02000800, 0x001005d8, 0x50500000,
+	0x9c0001c0, 0x4400a800, 0x8050a000, 0x8054a800,
+	0x8058b040, 0x040207fa, 0x1c01f000, 0x4c000000,
+	0x59a80008, 0x8c00051c, 0x5c000000, 0x1c01f000,
+	0x00000001, 0x00000002, 0x00000004, 0x00000008,
+	0x00000010, 0x00000020, 0x00000040, 0x00000080,
+	0x00000100, 0x00000200, 0x00000400, 0x00000800,
+	0x00001000, 0x00002000, 0x00004000, 0x00008000,
+	0x00010000, 0xa5f2b3ac
+};
+
+#ifdef UNIQUE_FW_NAME
+uint32_t fw2400_length01 = 0x0000ab4a ;
+#else
+uint32_t risc_code_length01 = 0x0000ab4a ;
+#endif
+
+
+#ifdef UNIQUE_FW_NAME
+uint32_t fw2400_addr02 = 0x0010e000  ;
+#else
+uint32_t risc_code_addr02 = 0x0010e000 ;
+#endif
+
+#ifdef UNIQUE_FW_NAME
+uint32_t fw2400_code02[] = {
+#else
+uint32_t risc_code02[] = {
+#endif
+	0x00000000, 0x00000000, 0x0010e000, 0x000014ff,
+	0x00000000, 0x00000000, 0x00020000, 0x000008c0,
+	0x836c0580, 0x00000003, 0x02020000, 0x001002e3,
+	0x42000000, 0x0010b4bb, 0x50000000, 0x800001c0,
+	0x04020956, 0x0401f923, 0x0401fbe3, 0x0401fb5c,
+	0x0201f800, 0x00020718, 0x0201f800, 0x0002057b,
+	0x0401f7f0, 0x59b800ea, 0x82000d00, 0xf0000038,
+	0x02020000, 0x00100a7a, 0x8c000510, 0x02000000,
+	0x00100a79, 0x59ba60e0, 0x81300182, 0x0402104e,
+	0x04002030, 0x8532653e, 0x59300406, 0x82000580,
+	0x00000003, 0x04020028, 0x59300203, 0x82000580,
+	0x00000004, 0x04020024, 0x59325808, 0x59300402,
+	0x4a025a04, 0x00000103, 0x900001c0, 0x48025806,
+	0x497a5807, 0x497a5c09, 0x5930001f, 0x80000540,
+	0x02020800, 0x00100d56, 0x59300004, 0x8c00053e,
+	0x04020010, 0x0401fa88, 0x59326809, 0x0201f800,
+	0x0002077d, 0x5934000f, 0x5934140b, 0x80081040,
+	0x04001002, 0x480a6c0b, 0x80000540, 0x04020a10,
+	0x59b800ea, 0x8c000510, 0x040207d7, 0x1c01f000,
+	0x0201f800, 0x00106f60, 0x040007ef, 0x0201f000,
+	0x00100a65, 0x42027000, 0x00000055, 0x0401f027,
+	0x83326500, 0x3fffffff, 0x59300406, 0x82000580,
+	0x00000003, 0x04020015, 0x59325808, 0x59326809,
+	0x59301402, 0x4a025a04, 0x00000103, 0x900811c0,
+	0x480a5806, 0x497a5c09, 0x497a5807, 0x0401fa62,
+	0x0201f800, 0x0002077d, 0x5934000f, 0x5934140b,
+	0x80081040, 0x04001002, 0x480a6c0b, 0x80000540,
+	0x040209eb, 0x0401f7db, 0x42027000, 0x00000054,
+	0x0401f00a, 0x83300500, 0x60000000, 0x02000000,
+	0x00100a68, 0x81326580, 0x8000013a, 0x82000400,
+	0x00100a80, 0x50027000, 0x59300c06, 0x82040580,
+	0x00000002, 0x02000000, 0x00100a65, 0x59300004,
+	0x8c00053e, 0x04020004, 0x0201f800, 0x000207a1,
+	0x0401f7c4, 0x0201f800, 0x00106f60, 0x040007fb,
+	0x0201f000, 0x00100a65, 0x59325808, 0x412c7000,
+	0x58380a04, 0x82040500, 0x0000000f, 0x82000c00,
+	0x001010bd, 0x50044000, 0x0c01f001, 0x00100dd9,
+	0x00100dd9, 0x0002009f, 0x00100dd9, 0x00100dd9,
+	0x00100dd9, 0x00100dd9, 0x00100dd9, 0x000200af,
+	0x00100ded, 0x00100dd9, 0x00100dd9, 0x00100ddb,
+	0x00100dd9, 0x00100dd9, 0x00100dd9, 0x5838040a,
+	0x8c000500, 0x02000800, 0x001005d8, 0x50200000,
+	0x80387c00, 0x583c1002, 0x583c2800, 0x583c2001,
+	0x58380a07, 0x5838300f, 0x59303807, 0x58384c08,
+	0x5838000d, 0x48026012, 0x0401f010, 0x5838020a,
+	0x8c000502, 0x02000000, 0x00100dd9, 0x50200000,
+	0x80387c00, 0x583c2800, 0x583c2001, 0x583c1002,
+	0x592c0a07, 0x592c4c08, 0x592c300f, 0x59303807,
+	0x497a6012, 0x497a6013, 0x4816600e, 0x4812600f,
+	0x480a6010, 0x481a6011, 0x80040840, 0x4806600d,
+	0x02020000, 0x00100e1a, 0x841c3d40, 0x481e6007,
+	0x1c01f000, 0x41787800, 0x59325808, 0x592c0c0a,
+	0x8c040d02, 0x02000000, 0x00100f8c, 0x592c000d,
+	0x592c100f, 0x592c0a04, 0x480a6011, 0x48026012,
+	0x48026013, 0x412c3000, 0x82040500, 0x0000000f,
+	0x82000400, 0x001010bd, 0x50003800, 0x501c0000,
+	0x401c1000, 0x592c1a07, 0x4802600a, 0x481a600b,
+	0x480a600c, 0x480e600d, 0x843c7d4a, 0x403c1000,
+	0x1c01f000, 0x41787800, 0x497a6012, 0x592c0a04,
+	0x412c3000, 0x592c1a07, 0x82040500, 0x0000000f,
+	0x82000400, 0x001010bd, 0x50004000, 0x50200000,
+	0x40201000, 0x4802600a, 0x481a600b, 0x480a600c,
+	0x480e600d, 0x80000580, 0x483e6004, 0x1c01f000,
+	0x4c000000, 0x4df00000, 0x0201f800, 0x00020729,
+	0x0401f005, 0x4c000000, 0x4df00000, 0x0401ff16,
+	0x0401f001, 0x5c03e000, 0x5c000000, 0x1801f000,
+	0x4203e000, 0xb0100000, 0x41fc0000, 0x82000500,
+	0x00000011, 0x0c01f001, 0x0002012a, 0x00020697,
+	0x0002012a, 0x0002012a, 0x0002012a, 0x0002012a,
+	0x0002012a, 0x0002012a, 0x0002012a, 0x0002012a,
+	0x0002012a, 0x0002012a, 0x0002012a, 0x0002012a,
+	0x0002012a, 0x0002012a, 0x0010115a, 0x0002012c,
+	0x0002012a, 0x0002012a, 0x0002012a, 0x0002012a,
+	0x0002012a, 0x0002012a, 0x0002012a, 0x0002012a,
+	0x0002012a, 0x0002012a, 0x0002012a, 0x0002012a,
+	0x0002012a, 0x0002012a, 0x0201f800, 0x001005d8,
+	0x0201f800, 0x00020697, 0x0201f000, 0x0010115a,
+	0x42000000, 0x0010b4c1, 0x50000000, 0x8c000504,
+	0x04000014, 0x42000000, 0x0010b4c1, 0x50000000,
+	0x8c000502, 0x04020002, 0x1c01f000, 0x4df00000,
+	0x4203e000, 0x50000000, 0x42034000, 0x0010b4a4,
+	0x59a0001d, 0x59a1d81e, 0x84000502, 0x4803401d,
+	0x58ec0009, 0x0801f800, 0x5c03e000, 0x1c01f000,
+	0x04027002, 0x04026002, 0x1c01f000, 0x4df00000,
+	0x4203e000, 0x50000000, 0x0201f800, 0x001007e4,
+	0x04000010, 0x412dd800, 0x48efc857, 0x0201f800,
+	0x00103b28, 0x42034000, 0x0010b4a4, 0x49a1d80b,
+	0x48ef401e, 0x59a0001d, 0x84000544, 0x4803401d,
+	0x0201f800, 0x00102214, 0x0201f800, 0x00102233,
+	0x5c03e000, 0x1c01f000, 0x4da00000, 0x4df00000,
+	0x4203e000, 0x50000000, 0x04006051, 0x40001000,
+	0x42034000, 0x0010b4a4, 0x59a01818, 0x800c19c0,
+	0x04020008, 0x59a0381b, 0x801c39c0, 0x02000800,
+	0x001005d8, 0x59a0041c, 0x801c3c00, 0x0401f00c,
+	0x59a00419, 0x82000400, 0x00000002, 0x48034419,
+	0x82000c80, 0x00000013, 0x04001003, 0x497b4419,
+	0x41780000, 0x59a03816, 0x801c3c00, 0x80081040,
+	0x480b4017, 0x581c0200, 0x4803c021, 0x581c0401,
+	0x4803c022, 0x581c0201, 0x4803c023, 0x581c0400,
+	0x4803c020, 0x900001c0, 0x82000540, 0x00000012,
+	0x4803c011, 0x59e00017, 0x8c000508, 0x04000003,
+	0x4a03c017, 0x00000002, 0x4203e000, 0x30000001,
+	0x800c19c0, 0x04000007, 0x800c1840, 0x480f4018,
+	0x0402001f, 0x497b4419, 0x497b4219, 0x0401f01c,
+	0x800811c0, 0x0402000b, 0x4d2c0000, 0x59a2581b,
+	0x0201f800, 0x001007f4, 0x5c025800, 0x497b401b,
+	0x497b401a, 0x497b441c, 0x497b421c, 0x0401f010,
+	0x59a0041c, 0x82000400, 0x00000002, 0x82000c80,
+	0x00000012, 0x4803441c, 0x04001009, 0x4d2c0000,
+	0x59a2581b, 0x592c3813, 0x481f401b, 0x497b441c,
+	0x0201f800, 0x001007f4, 0x5c025800, 0x5c03e000,
+	0x5c034000, 0x1c01f000, 0x59a80005, 0x82000500,
+	0x00000003, 0x02020000, 0x00104315, 0x59340400,
+	0x82000580, 0x00000606, 0x02020000, 0x001042e6,
+	0x5934000d, 0x80027d40, 0x02020000, 0x00104321,
+	0x0401f803, 0x80000580, 0x1c01f000, 0x5934000f,
+	0x59341203, 0x80080540, 0x0402006f, 0x5934020b,
+	0x5934140b, 0x80080480, 0x0402106b, 0x0201f800,
+	0x0002075a, 0x04000064, 0x80081000, 0x592c0406,
+	0x480a6c0b, 0x49366009, 0x492e6008, 0x4a026406,
+	0x00000003, 0x4a026403, 0x00000040, 0x800000c2,
+	0x800018c4, 0x800c0400, 0x48026206, 0x592c0808,
+	0x592c1809, 0x592c020a, 0x48066017, 0x480e6018,
+	0x8c000502, 0x04000030, 0x4a026203, 0x00000004,
+	0x592c0207, 0x80000040, 0x04020020, 0x59a80005,
+	0x8c000514, 0x42000000, 0x00000055, 0x04020003,
+	0x42000000, 0x00000033, 0x80000040, 0x040207ff,
+	0x592c0204, 0x82000500, 0x000000ff, 0x82000580,
+	0x00000018, 0x04020011, 0x592c180f, 0x59300007,
+	0x82000540, 0x00000091, 0x480e6011, 0x48026007,
+	0x42000000, 0x80000004, 0x48026004, 0x59bc00ea,
+	0x8c000516, 0x040207fe, 0x83300400, 0x20000000,
+	0x480378e1, 0x1c01f000, 0x0401fe78, 0x59300007,
+	0x8400054e, 0x48026007, 0x592c1a04, 0x820c1d00,
+	0x000000ff, 0x820c0580, 0x00000048, 0x04000017,
+	0x0401f7ec, 0x8c000500, 0x04020ecb, 0x4a026203,
+	0x00000002, 0x59a80805, 0x82040500, 0x00000600,
+	0x04020012, 0x42000000, 0x00000030, 0x80000040,
+	0x040207ff, 0x592c1a04, 0x820c1d00, 0x000000ff,
+	0x820c0580, 0x00000018, 0x040007da, 0x820c0580,
+	0x00000048, 0x040207d7, 0x42000800, 0x80000804,
+	0x0201f000, 0x00106721, 0x8c040d12, 0x42000000,
+	0x00000010, 0x040207ee, 0x42000000, 0x00000051,
+	0x0401f7eb, 0x800811c0, 0x04020003, 0x4a026a03,
+	0x00000001, 0x59340010, 0x492e6810, 0x80000d40,
+	0x04020003, 0x492e680f, 0x1c01f000, 0x492c0800,
+	0x1c01f000, 0x83440c80, 0x00000800, 0x04021009,
+	0x83440400, 0x0010ac00, 0x50000000, 0x80000540,
+	0x04000004, 0x40026800, 0x80000580, 0x1c01f000,
+	0x82000540, 0x00000001, 0x1c01f000, 0x59340203,
+	0x80000540, 0x0402004b, 0x4d300000, 0x4d2c0000,
+	0x5934000f, 0x80025d40, 0x04000044, 0x0201f800,
+	0x0002075a, 0x0400003f, 0x592c0000, 0x4802680f,
+	0x80000540, 0x04020002, 0x48026810, 0x592c2a04,
+	0x80081000, 0x480a6c0b, 0x49366009, 0x492e6008,
+	0x82142d00, 0x000000ff, 0x82140580, 0x00000012,
+	0x04000035, 0x4a026406, 0x00000003, 0x4a026403,
+	0x00000040, 0x592c0406, 0x800000c2, 0x800018c4,
+	0x800c0400, 0x48026206, 0x592c0808, 0x592c1809,
+	0x592c020a, 0x48066017, 0x480e6018, 0x8c000502,
+	0x02000000, 0x0010474d, 0x4a026203, 0x00000004,
+	0x592c0207, 0x80000040, 0x02020000, 0x00104740,
+	0x82140580, 0x00000018, 0x02020000, 0x00104740,
+	0x592c180f, 0x59300007, 0x82000540, 0x00000091,
+	0x480e6011, 0x48026007, 0x42000000, 0x80000004,
+	0x48026004, 0x59bc00ea, 0x8c000516, 0x040207fe,
+	0x83300400, 0x20000000, 0x480378e1, 0x5934020b,
+	0x5934140b, 0x80080480, 0x040017be, 0x0401f003,
+	0x4a026a03, 0x00000001, 0x5c025800, 0x5c026000,
+	0x1c01f000, 0x497a5800, 0x49325809, 0x4a026406,
+	0x00000006, 0x4a026203, 0x00000007, 0x0401f802,
+	0x0401f7ef, 0x59a80021, 0x800001c0, 0x02020000,
+	0x0010476f, 0x59a80005, 0x8c000504, 0x02020000,
+	0x0010476b, 0x59340200, 0x8c000518, 0x02020000,
+	0x00104767, 0x592c0a0c, 0x48066202, 0x4a025a06,
+	0x00000000, 0x8c000508, 0x02020000, 0x00104763,
+	0x4d3c0000, 0x417a7800, 0x0401fbdf, 0x5c027800,
+	0x1c01f000, 0x592c0404, 0x8c00051e, 0x02020000,
+	0x00104ce4, 0x59980022, 0x80000540, 0x04000017,
+	0x592c0a06, 0x592c0409, 0x80040540, 0x04020013,
+	0x0201f000, 0x00104cfa, 0x592c0404, 0x8c00051e,
+	0x02020000, 0x00104cf3, 0x59980022, 0x80000540,
+	0x0400000a, 0x82040580, 0x00000001, 0x04020007,
+	0x0201f000, 0x00104cfa, 0x592c0404, 0x8c00051e,
+	0x02020000, 0x00104dca, 0x59980026, 0x497a5800,
+	0x80000540, 0x02020000, 0x00104e1d, 0x59d80105,
+	0x82000d00, 0x00018780, 0x02020000, 0x00104edb,
+	0x80000106, 0x82000500, 0x00000003, 0x0c01f001,
+	0x000202f0, 0x00104e1d, 0x000202f6, 0x00020341,
+	0x592c0001, 0x492fb107, 0x80000d40, 0x02020000,
+	0x00104ddb, 0x1c01f000, 0x592c0001, 0x492fb107,
+	0x80000d40, 0x02020000, 0x00104de8, 0x59da5908,
+	0x835c0480, 0x00000020, 0x0400102c, 0x0402b034,
+	0x492fb007, 0x0400e7fa, 0x59d80105, 0x82000500,
+	0x00018780, 0x02020000, 0x00104edb, 0x0400601f,
+	0x59d8010a, 0x59d8090a, 0x80040580, 0x040207fd,
+	0x800408e0, 0x599c1017, 0x8c081508, 0x04020028,
+	0x82040d40, 0x00000013, 0x5998002b, 0x4807c011,
+	0x84000500, 0x4803302b, 0x59e00017, 0x8c000508,
+	0x04020004, 0x4203e000, 0x30000001, 0x1c01f000,
+	0x4a03c017, 0x00000003, 0x82040500, 0x000000ff,
+	0x82000580, 0x0000001d, 0x040207f7, 0x4a03c017,
+	0x0000000d, 0x0401f7f4, 0x5998082b, 0x84040d40,
+	0x4807302b, 0x1c01f000, 0x496a5800, 0x412ed000,
+	0x815eb800, 0x59c80000, 0x82000540, 0x00001200,
+	0x48039000, 0x0400e7ca, 0x0401f7d0, 0x0402f7f7,
+	0x492fa807, 0x0400e7c6, 0x0401f7cc, 0x59e0000f,
+	0x59e0100f, 0x80081580, 0x040207fd, 0x81281580,
+	0x040007d4, 0x40025000, 0x82040d40, 0x0000001d,
+	0x0401f7d2, 0x59d80908, 0x45680800, 0x4006d000,
+	0x815eb800, 0x0400e7fc, 0x59c80000, 0x82000540,
+	0x00001200, 0x48039000, 0x02006000, 0x00104df8,
+	0x59d8010a, 0x59d8090a, 0x80040d80, 0x040207fd,
+	0x900001c0, 0x82000540, 0x00000013, 0x4803c011,
+	0x5998002b, 0x84000500, 0x4803302b, 0x59e00017,
+	0x8c000508, 0x04000003, 0x4a03c017, 0x00000003,
+	0x4203e000, 0x30000001, 0x59d80105, 0x82000500,
+	0x00018780, 0x02020000, 0x00104edb, 0x0202d000,
+	0x00104dfd, 0x592c0001, 0x492fb107, 0x80000d40,
+	0x02020000, 0x00104e10, 0x1c01f000, 0x59980020,
+	0x0c01f001, 0x00020370, 0x00020371, 0x00104e88,
+	0x1c01f000, 0x4df00000, 0x4203e000, 0x50000000,
+	0x0402681e, 0x04006004, 0x599c0017, 0x8c000508,
+	0x04020865, 0x59980029, 0x80025d40, 0x0400000a,
+	0x0402d00b, 0x59980026, 0x80000040, 0x48033026,
+	0x592c0000, 0x492fb107, 0x48033029, 0x04020002,
+	0x48033028, 0x5c03e000, 0x1c01f000, 0x59d80105,
+	0x82000500, 0x00018780, 0x02020000, 0x00104edb,
+	0x42000000, 0x0010b855, 0x0201f800, 0x0010aa47,
+	0x5c03e000, 0x1c01f000, 0x5998002b, 0x8c000500,
+	0x0402003b, 0x0400e007, 0x59d80105, 0x82000500,
+	0x00018780, 0x02020000, 0x00104edb, 0x1c01f000,
+	0x59da5908, 0x835c0c80, 0x00000020, 0x04001003,
+	0x0400b029, 0x0400f02b, 0x496a5800, 0x412ed000,
+	0x815eb800, 0x59c80000, 0x82000540, 0x00001200,
+	0x48039000, 0x0400e7f3, 0x59d8010a, 0x59d8090a,
+	0x80040580, 0x040207fd, 0x800408e0, 0x599c1017,
+	0x8c081508, 0x04020022, 0x82040d40, 0x00000013,
+	0x4807c011, 0x59e00017, 0x8c000508, 0x0400000a,
+	0x4a03c017, 0x00000003, 0x82040500, 0x000000ff,
+	0x82000580, 0x0000001d, 0x04020003, 0x4a03c017,
+	0x0000000d, 0x4203e000, 0x30000001, 0x59d80105,
+	0x82000500, 0x00018780, 0x02020000, 0x00104edb,
+	0x1c01f000, 0x492fb007, 0x0400e7d2, 0x0401f7df,
+	0x492fa807, 0x0400e7cf, 0x0401f7dc, 0x84000500,
+	0x4803302b, 0x0400e7cb, 0x0401f7d8, 0x59e0000f,
+	0x59e0100f, 0x80081580, 0x040207fd, 0x81281580,
+	0x040007da, 0x40025000, 0x82040d40, 0x0000001d,
+	0x0401f7d8, 0x59e0000f, 0x59e0100f, 0x80080d80,
+	0x040207fd, 0x81280580, 0x04020002, 0x1c01f000,
+	0x400a5000, 0x900811c0, 0x82081540, 0x0000001c,
+	0x480bc011, 0x59e00017, 0x8c000508, 0x04000003,
+	0x4a03c017, 0x0000000c, 0x4203e000, 0x30000001,
+	0x1c01f000, 0x41700000, 0x0c01f001, 0x00105420,
+	0x000203fc, 0x00105420, 0x00105421, 0x0010541e,
+	0x0010541e, 0x0010541e, 0x0010541e, 0x001058b0,
+	0x04010037, 0x59980006, 0x80000540, 0x0402003c,
+	0x0402c01c, 0x4202f800, 0x00000010, 0x4df00000,
+	0x4203e000, 0x50000000, 0x49db3005, 0x59da5808,
+	0x592c0204, 0x497a5800, 0x497a5801, 0x82000500,
+	0x000000ff, 0x82000c80, 0x00000079, 0x04021036,
+	0x0c01f839, 0x5c03e000, 0x817ef840, 0x04000009,
+	0x836c0580, 0x00000003, 0x04020006, 0x83700580,
+	0x00000001, 0x04020010, 0x0401001b, 0x0400c7e8,
+	0x0400f94a, 0x0400b134, 0x59d40005, 0x82000500,
+	0x43018780, 0x02020000, 0x0010583f, 0x59d80005,
+	0x82000500, 0x43018780, 0x02020000, 0x00105846,
+	0x1c01f000, 0x83700580, 0x00000003, 0x02000800,
+	0x00105421, 0x83700580, 0x00000001, 0x040207ed,
+	0x04010005, 0x0400c7d2, 0x0401f7ea, 0x4202f800,
+	0x00000010, 0x4df00000, 0x4203e000, 0x50000000,
+	0x49d73005, 0x59d65808, 0x0401f7ce, 0x4df00000,
+	0x4203e000, 0x50000000, 0x40025800, 0x592c0204,
+	0x497b3005, 0x497b3006, 0x4202f800, 0x00000010,
+	0x0401f7c7, 0x0201f800, 0x00105491, 0x5c03e000,
+	0x0401f7d4, 0x00105491, 0x00105491, 0x00105491,
+	0x00105491, 0x00105527, 0x00105491, 0x00105491,
+	0x00105491, 0x00105491, 0x00105491, 0x001054a1,
+	0x00105491, 0x00105491, 0x00105491, 0x00105551,
+	0x00105491, 0x00105491, 0x00105491, 0x000204ef,
+	0x00105491, 0x001056b4, 0x00105491, 0x00105491,
+	0x00105491, 0x000204c2, 0x00105491, 0x00105491,
+	0x00105491, 0x00105491, 0x00105491, 0x00105491,
+	0x00105491, 0x00105491, 0x00105491, 0x00105491,
+	0x00105491, 0x00105491, 0x00105491, 0x00105491,
+	0x00105491, 0x00105491, 0x001054c9, 0x00105491,
+	0x00105491, 0x00105491, 0x00105491, 0x00105491,
+	0x00105491, 0x00105491, 0x00105491, 0x00105491,
+	0x001057d3, 0x00105491, 0x00105491, 0x00105491,
+	0x00105491, 0x00105491, 0x0010581e, 0x00105491,
+	0x001054bb, 0x00105491, 0x00105797, 0x00105491,
+	0x00105491, 0x00105491, 0x00105491, 0x00105491,
+	0x00105491, 0x00105491, 0x00105765, 0x00105491,
+	0x00105765, 0x00105872, 0x00105491, 0x00105491,
+	0x00105491, 0x00105491, 0x00105491, 0x00105491,
+	0x00105491, 0x00105491, 0x00105491, 0x00105725,
+	0x00105855, 0x00105491, 0x00105865, 0x00105491,
+	0x00105491, 0x00105491, 0x00105491, 0x00105491,
+	0x00105491, 0x00105491, 0x00105491, 0x00105491,
+	0x00105491, 0x00105491, 0x00105491, 0x00105491,
+	0x00105491, 0x00105491, 0x00105491, 0x00105491,
+	0x00105491, 0x00105491, 0x00105491, 0x00105491,
+	0x00105491, 0x00105491, 0x00105491, 0x00105491,
+	0x00105491, 0x00105491, 0x00105491, 0x00105491,
+	0x00105491, 0x00105491, 0x00105491, 0x00105491,
+	0x00105491, 0x00105491, 0x592c0204, 0x80000110,
+	0x02000000, 0x00105499, 0x80000040, 0x04000009,
+	0x48033002, 0x492f3003, 0x492f3004, 0x4a033008,
+	0x000204d0, 0x4202e000, 0x00000003, 0x1c01f000,
+	0x592c0406, 0x82000c80, 0x0000199a, 0x02021000,
+	0x001054a9, 0x59a80021, 0x80000540, 0x02020000,
+	0x001054d7, 0x592e8a06, 0x83440c80, 0x000007f0,
+	0x02021000, 0x001054a9, 0x83440400, 0x0010ac00,
+	0x50000000, 0x80026d40, 0x02000000, 0x001054db,
+	0x59340002, 0x592c0810, 0x80040580, 0x82000500,
+	0x00ffffff, 0x02020000, 0x001054a9, 0x0401fccf,
+	0x02020000, 0x001054de, 0x1c01f000, 0x592c0204,
+	0x80000110, 0x02000000, 0x00105499, 0x80000040,
+	0x0402000b, 0x592c040a, 0x8c000504, 0x04000010,
+	0x592c0207, 0x82000c80, 0x00001001, 0x02021000,
+	0x001054a9, 0x0201f000, 0x0010588a, 0x48033002,
+	0x492f3003, 0x492f3004, 0x4a033008, 0x00020507,
+	0x4202e000, 0x00000003, 0x1c01f000, 0x592c0406,
+	0x82000c80, 0x0000199a, 0x02021000, 0x001054a9,
+	0x592e8a06, 0x417a7800, 0x0401fd37, 0x02020000,
+	0x00105658, 0x59340002, 0x592c0808, 0x80040580,
+	0x82000500, 0x00ffffff, 0x02020000, 0x001054a9,
+	0x497a5808, 0x592e6009, 0x83300580, 0xffffffff,
+	0x02000000, 0x00105618, 0x83300480, 0x0010d1c0,
+	0x02001000, 0x00105675, 0x59a8000b, 0x81300480,
+	0x02021000, 0x00105675, 0x592c240a, 0x49366009,
+	0x8c10251c, 0x02020000, 0x00105606, 0x59a80068,
+	0x8c000510, 0x02020000, 0x0010568e, 0x59a80821,
+	0x800409c0, 0x02020000, 0x001055ec, 0x59a80805,
+	0x8c040d04, 0x02020000, 0x0010567f, 0x59340200,
+	0x8c000518, 0x02020000, 0x00105670, 0x59300c06,
+	0x82040580, 0x00000006, 0x02020000, 0x00105610,
+	0x59300414, 0x8c000516, 0x02020000, 0x0010567a,
+	0x8c102508, 0x02020000, 0x0010a5b8, 0x59300808,
+	0x4a025a06, 0x00000000, 0x800409c0, 0x02020000,
+	0x001055e7, 0x592c0a0c, 0x48066202, 0x492e6008,
+	0x0401f14d, 0x4df00000, 0x4203e000, 0x50000000,
+	0x0402b00b, 0x835c0480, 0x00000020, 0x0400100d,
+	0x815eb840, 0x416a5800, 0x592ed000, 0x492fb007,
+	0x497a5800, 0x497a5801, 0x0400b7f7, 0x59d80005,
+	0x82000500, 0x43018780, 0x02020000, 0x00105846,
+	0x5c03e000, 0x1c01f000, 0x4df00000, 0x4203e000,
+	0x50000000, 0x0402f00b, 0x835c0480, 0x00000020,
+	0x0400100d, 0x815eb840, 0x416a5800, 0x592ed000,
+	0x492fa807, 0x497a5800, 0x497a5801, 0x0400f7f7,
+	0x59d40005, 0x82000500, 0x43018780, 0x02020000,
+	0x0010583f, 0x5c03e000, 0x1c01f000, 0x4df00000,
+	0x4203e000, 0x50000000, 0x59940024, 0x80000540,
+	0x04000112, 0x4c000000, 0x42000000, 0x00001000,
+	0x50000000, 0x82000480, 0x24320001, 0x04020015,
+	0x42000800, 0x00000064, 0x80040840, 0x04000007,
+	0x4a030000, 0x00000001, 0x40000000, 0x59800000,
+	0x8c000500, 0x040007f9, 0x04000008, 0x42000800,
+	0x00007a01, 0x50040000, 0x8c000510, 0x04000003,
+	0x84000510, 0x44000800, 0x4a030000, 0x00000000,
+	0x59e00002, 0x8c00051e, 0x0402001b, 0x42000000,
+	0x00001000, 0x50000000, 0x82000480, 0x24320002,
+	0x04020015, 0x42000800, 0x00000064, 0x80040840,
+	0x04000007, 0x4a030000, 0x00000001, 0x40000000,
+	0x59800000, 0x8c000500, 0x040007f9, 0x04000008,
+	0x42000800, 0x00007a17, 0x50040000, 0x8c00050e,
+	0x04020003, 0x8400054e, 0x44000800, 0x4a030000,
+	0x00000000, 0x5c000000, 0x5994781a, 0x48032825,
+	0x803c0480, 0x04001004, 0x04000003, 0x4803281a,
+	0x0401f022, 0x41787800, 0x803c7800, 0x82000400,
+	0x000003e8, 0x040027fd, 0x4803281a, 0x59a80024,
+	0x803c1400, 0x480b5024, 0x803c0040, 0x04000002,
+	0x483fc857, 0x59e40852, 0x59a80025, 0x80040580,
+	0x04000004, 0x480bc857, 0x59e40052, 0x48035025,
+	0x59940026, 0x803c0400, 0x48032826, 0x0201f800,
+	0x00106021, 0x59940000, 0x82000580, 0x00000000,
+	0x04020006, 0x59940026, 0x48032827, 0x497b2826,
+	0x4a032800, 0x00000001, 0x4c0c0000, 0x59940007,
+	0x80000d40, 0x0400001d, 0x59941006, 0x59940025,
+	0x80081c80, 0x04001004, 0x04000003, 0x480f2806,
+	0x0401f016, 0x80040840, 0x48072807, 0x82040580,
+	0x000003e8, 0x04020007, 0x4c040000, 0x4c0c0000,
+	0x59940008, 0x0801f800, 0x5c001800, 0x5c000800,
+	0x800409c0, 0x04020004, 0x59940008, 0x0801f800,
+	0x0401f006, 0x400c0000, 0x820c1c00, 0x0000000a,
+	0x040027ed, 0x480f2806, 0x5c001800, 0x4d180000,
+	0x59c40008, 0x8c000534, 0x04020025, 0x417a3000,
+	0x83947c00, 0x00000009, 0x583c0001, 0x80000d40,
+	0x04020008, 0x823c7c00, 0x00000003, 0x811a3000,
+	0x83180580, 0x00000005, 0x040207f8, 0x0401f018,
+	0x583c1000, 0x59940025, 0x80080480, 0x04001005,
+	0x04000004, 0x48007800, 0x80000040, 0x04021010,
+	0x80040840, 0x48047801, 0x04000008, 0x82000400,
+	0x0000000a, 0x48007800, 0x040027fa, 0x82040500,
+	0x0000007f, 0x0401f7e8, 0x583c0002, 0x4c3c0000,
+	0x0801f800, 0x5c007800, 0x0401f7e3, 0x5c023000,
+	0x59940019, 0x80001540, 0x04000008, 0x04002007,
+	0x59940025, 0x80080480, 0x497b2819, 0x04001003,
+	0x04000002, 0x48032819, 0x59940004, 0x80000d40,
+	0x0400002a, 0x4c040000, 0x5994001c, 0x80000d40,
+	0x04000013, 0x5994101b, 0x59940025, 0x80080480,
+	0x04001005, 0x04000004, 0x4803281b, 0x80000040,
+	0x0402100b, 0x80040840, 0x4807281c, 0x04020004,
+	0x5994001d, 0x0801f800, 0x0401f005, 0x82000400,
+	0x0000000a, 0x4803281b, 0x040027f7, 0x5c000800,
+	0x59941003, 0x59940025, 0x80080480, 0x04001005,
+	0x04000004, 0x48032803, 0x80000040, 0x0402100b,
+	0x80040840, 0x48072804, 0x04020004, 0x59940005,
+	0x0801f800, 0x0401f005, 0x82000400, 0x0000000a,
+	0x48032803, 0x040027f7, 0x5994001f, 0x80000d40,
+	0x04000013, 0x5994101e, 0x59940025, 0x80080480,
+	0x04001005, 0x04000004, 0x4803281e, 0x80000040,
+	0x0402100b, 0x80040840, 0x4807281f, 0x04020004,
+	0x59940020, 0x0801f800, 0x0401f005, 0x82000400,
+	0x00000001, 0x4803281e, 0x040027f7, 0x59940022,
+	0x80000d40, 0x04000013, 0x59941021, 0x59940025,
+	0x80080480, 0x04001005, 0x04000004, 0x48032821,
+	0x80000040, 0x0402100b, 0x80040840, 0x48072822,
+	0x04020004, 0x59940023, 0x0801f800, 0x0401f005,
+	0x82000400, 0x0000000a, 0x48032821, 0x040027f7,
+	0x59940824, 0x59940025, 0x80040480, 0x02001800,
+	0x001005d8, 0x48032824, 0x59940000, 0x0c01f001,
+	0x00105fb5, 0x00105fb7, 0x00105fdd, 0x59940024,
+	0x80000000, 0x48032824, 0x4203e000, 0x70000000,
+	0x1c01f000, 0x592c0406, 0x800000c2, 0x800008c4,
+	0x80040c00, 0x592c040a, 0x48066206, 0x82000d00,
+	0x00000003, 0x02000000, 0x0010615e, 0x8c000500,
+	0x04020029, 0x8c00051e, 0x02000000, 0x00106139,
+	0x82000d00, 0x000000c0, 0x02020000, 0x0010612f,
+	0x82000d00, 0x00002020, 0x02020000, 0x0010612c,
+	0x813e79c0, 0x02020000, 0x0010612c, 0x592c0c0c,
+	0x800409c0, 0x02020000, 0x0010612c, 0x59300a03,
+	0x82040d80, 0x00000007, 0x02020000, 0x0010612c,
+	0x4a026203, 0x00000003, 0x4a026403, 0x00000043,
+	0x0201f800, 0x000200c9, 0x82080d40, 0x80003465,
+	0x48066004, 0x497a6000, 0x59bc00ea, 0x8c000516,
+	0x040207fe, 0x83300400, 0xa0000000, 0x480378e1,
+	0x1c01f000, 0x8c000502, 0x02020000, 0x00106181,
+	0x8c00051e, 0x0400000e, 0x82000d00, 0x000000c0,
+	0x04000005, 0x82040d80, 0x000000c0, 0x02020000,
+	0x00106186, 0x82000d00, 0x00002020, 0x82040d80,
+	0x00002020, 0x02000000, 0x0010614d, 0x592c0207,
+	0x80000040, 0x02020000, 0x00106157, 0x592c180d,
+	0x800c19c0, 0x02020000, 0x00106157, 0x592c180f,
+	0x59300007, 0x82000540, 0x00000011, 0x480e6011,
+	0x48026007, 0x4a026203, 0x00000004, 0x4a026403,
+	0x00000042, 0x42000800, 0x80002001, 0x0401f02a,
+	0x5c000000, 0x4c000000, 0x4803c857, 0x4807c857,
+	0x0401f003, 0x42000800, 0x00000001, 0x59325808,
+	0x832c0500, 0x00ff0000, 0x0400000d, 0x592c0000,
+	0x48065a06, 0x48026008, 0x592c040a, 0x8c000510,
+	0x04020008, 0x0201f800, 0x000202ce, 0x417a7800,
+	0x59300008, 0x80025d40, 0x0402078f, 0x1c01f000,
+	0x456a5800, 0x412ed000, 0x815eb800, 0x59c80000,
+	0x82000540, 0x00001200, 0x48039000, 0x0401f7f4,
+	0x59840000, 0x80000540, 0x04020002, 0x1c01f000,
+	0x59840003, 0x80000540, 0x02020000, 0x001061fe,
+	0x1c01f000, 0x48066004, 0x59bc00ea, 0x8c000516,
+	0x040207fe, 0x83300400, 0x40000000, 0x480378e1,
+	0x1c01f000, 0x59bc00ea, 0x82001500, 0xb0000018,
+	0x02020000, 0x00106c81, 0x8c000510, 0x0400002a,
+	0x59bc10e0, 0x82080500, 0xfffff000, 0x0402000a,
+	0x80080108, 0x820a3500, 0x0000000f, 0x4803c857,
+	0x1201f000, 0x00106c87, 0x84000510, 0x48026004,
+	0x0401f016, 0x840a653e, 0x59300004, 0x8c000520,
+	0x040007fa, 0x82000500, 0xfffefeff, 0x48026004,
+	0x8c08153e, 0x04020005, 0x42027000, 0x00000013,
+	0x0401f859, 0x0401f009, 0x59300004, 0x8c000514,
+	0x04000003, 0x0401ffb0, 0x0401f02f, 0x42027000,
+	0x00000049, 0x0401f850, 0x59bc00ea, 0x82001500,
+	0xb0000018, 0x02020000, 0x00106c81, 0x8c000510,
+	0x040207d8, 0x1c01f000, 0x83640480, 0x00000010,
+	0x0400101a, 0x41626000, 0x41580000, 0x59300a03,
+	0x82040d80, 0x00000000, 0x04000008, 0x83326400,
+	0x00000024, 0x81300c80, 0x040017f9, 0x42026000,
+	0x0010d1c0, 0x0401f7f6, 0x8166c840, 0x83300c00,
+	0x00000024, 0x80040480, 0x04021005, 0x4006c000,
+	0x4a026203, 0x00000008, 0x1c01f000, 0x837ac540,
+	0x0010d1c0, 0x0401f7fb, 0x42000000, 0x0010b854,
+	0x0201f800, 0x0010aa47, 0x4967c857, 0x80026580,
+	0x1c01f000, 0x83300480, 0x0010d1c0, 0x02001800,
+	0x001005d8, 0x41580000, 0x81300480, 0x0402100c,
+	0x04011000, 0x457a6000, 0x4a026202, 0x0000ffff,
+	0x83300400, 0x00000003, 0x4803c840, 0x4a03c842,
+	0x00000021, 0x8166c800, 0x1c01f000, 0x41540000,
+	0x81300480, 0x02021800, 0x001005d8, 0x04011000,
+	0x457a6000, 0x4a026202, 0x0000ffff, 0x83300400,
+	0x00000003, 0x4803c840, 0x4a03c842, 0x00000021,
+	0x59a80066, 0x49335065, 0x80000000, 0x48035066,
+	0x1c01f000, 0x4d340000, 0x59326809, 0x59300406,
+	0x82000500, 0x0000001f, 0x0c01f803, 0x5c026800,
+	0x1c01f000, 0x00107966, 0x00107979, 0x00107993,
+	0x000207c9, 0x001098f1, 0x0010990c, 0x0002083e,
+	0x00107966, 0x00107979, 0x001064ee, 0x001079ac,
+	0x00107966, 0x00107966, 0x00107966, 0x00107966,
+	0x00107966, 0x001095a1, 0x0010a6c2, 0x00107966,
+	0x00107966, 0x00107966, 0x00107966, 0x00107966,
+	0x00107966, 0x00107966, 0x00107966, 0x00107966,
+	0x00107966, 0x00107966, 0x00107966, 0x00107966,
+	0x00107966, 0x59300203, 0x82000c80, 0x0000000e,
+	0x02021800, 0x001005d8, 0x0c01f001, 0x001079aa,
+	0x00108592, 0x000207dd, 0x00108720, 0x001087b9,
+	0x001079aa, 0x001079aa, 0x001079aa, 0x00108577,
+	0x001079aa, 0x001079aa, 0x001079aa, 0x001079aa,
+	0x00108985, 0x83380480, 0x00000058, 0x04021007,
+	0x83380480, 0x00000040, 0x04001004, 0x4d2c0000,
+	0x0c01f803, 0x5c025800, 0x1c01f000, 0x0010861b,
+	0x0010861b, 0x0010861b, 0x0010861b, 0x0010861b,
+	0x0010861d, 0x001086bd, 0x0010861b, 0x0010861b,
+	0x0010861b, 0x0010861b, 0x0010861b, 0x0010861b,
+	0x0010861b, 0x0010861b, 0x0010861b, 0x0010861b,
+	0x0010861b, 0x0010861b, 0x001086c1, 0x000207ff,
+	0x0010861b, 0x001086c0, 0x001086c2, 0x59325808,
+	0x59300811, 0x59301402, 0x59340200, 0x8c00050e,
+	0x0402001c, 0x0401f826, 0x04000005, 0x4a025a04,
+	0x00000103, 0x497a5c09, 0x0401f009, 0x4a025a04,
+	0x00000103, 0x4a025a06, 0x00000000, 0x497a5c09,
+	0x800409c0, 0x02020800, 0x00108785, 0x48065807,
+	0x480a5c06, 0x0201f800, 0x000202c1, 0x5934000f,
+	0x5934140b, 0x80081040, 0x04001002, 0x480a6c0b,
+	0x80000540, 0x02020800, 0x00020253, 0x0401f75e,
+	0x592c020a, 0x8c000502, 0x040007e9, 0x800409c0,
+	0x040007e7, 0x592c0208, 0x8c00050e, 0x040207e4,
+	0x4933c857, 0x0201f000, 0x0010920f, 0x592c020a,
+	0x8c000500, 0x04000010, 0x59300015, 0x592c380f,
+	0x801c3c80, 0x0400000c, 0x4a025a06, 0x00000015,
+	0x8c1c3d3e, 0x04000005, 0x4a025a06, 0x00000007,
+	0x801c3880, 0x801c3800, 0x481fc857, 0x821c0d40,
+	0x00000000, 0x1c01f000, 0x59300203, 0x82003480,
+	0x0000000e, 0x02021800, 0x001005d8, 0x0c01f001,
+	0x0010992b, 0x00020852, 0x00109fba, 0x00109fc8,
+	0x0002086e, 0x0010992b, 0x0010a0a8, 0x0002088d,
+	0x0010992b, 0x0010992b, 0x0010992b, 0x0010992b,
+	0x0010992b, 0x0010992b, 0x83380580, 0x00000013,
+	0x02020000, 0x00109f42, 0x59300403, 0x82027480,
+	0x00000044, 0x02021800, 0x001005d8, 0x82000480,
+	0x00000040, 0x02001800, 0x001005d8, 0x0c01f001,
+	0x00109f9e, 0x00020864, 0x00109fa0, 0x00109fb2,
+	0x59325808, 0x832c0500, 0x00ff0000, 0x04000005,
+	0x592c0c0a, 0x8c040d1a, 0x02020000, 0x00109fad,
+	0x0401fe91, 0x0401f710, 0x83380580, 0x00000048,
+	0x04000007, 0x83380580, 0x00000053, 0x02000000,
+	0x0010a04a, 0x0201f800, 0x001005d8, 0x5930001f,
+	0x59301011, 0x59300809, 0x58040a00, 0x8c040d0e,
+	0x02020000, 0x0010a026, 0x800811c0, 0x02020000,
+	0x0010a033, 0x5930001f, 0x80000540, 0x02020000,
+	0x0010a041, 0x59325808, 0x592c040a, 0x8c00051e,
+	0x02000000, 0x0010a01c, 0x42027000, 0x00000041,
+	0x0401f001, 0x83380480, 0x00000054, 0x02021800,
+	0x001005d8, 0x83380480, 0x00000040, 0x02001000,
+	0x0010a067, 0x0c01f001, 0x0010a073, 0x000208aa,
+	0x0010a07f, 0x0010a086, 0x0010a073, 0x0010a073,
+	0x0010a073, 0x0010a073, 0x0010a075, 0x0010a07a,
+	0x0010a07a, 0x0010a073, 0x0010a073, 0x0010a073,
+	0x0010a073, 0x0010a07a, 0x0010a073, 0x0010a07a,
+	0x0010a073, 0x0010a075, 0x4a026203, 0x00000001,
+	0x493a6403, 0x42000800, 0x80002042, 0x0401f672,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x14aa62b1,
+	0x00000000, 0x00000000, 0x00000000, 0x00000005,
+	0xfffffffb, 0x02800004, 0x00000000, 0x0000c000,
+	0x0000071d, 0x073fca5a, 0x0705a5a5, 0x01928009,
+	0x070ff0e1, 0x03800006, 0x04958010, 0x05308000,
+	0x05008000, 0x0600902f, 0x04a004dc, 0x0202f051,
+	0x042e4020, 0x018f021b, 0x033e5000, 0x03020000,
+	0x078d0018, 0x0493041a, 0x0092041c, 0x038a0305,
+	0x078b0303, 0x048e8010, 0x0678aae5, 0x06000001,
+	0x07818174, 0x040010e6, 0x0448e0e6, 0x04818010,
+	0x002fb008, 0x0448e0e6, 0x04818010, 0x060ff0e6,
+	0x00580401, 0x054880ff, 0x04818010, 0x022a5001,
+	0x030430d4, 0x06780043, 0x030e0000, 0x030450ff,
+	0x06780043, 0x03019000, 0x058185c6, 0x027c0045,
+	0x03020000, 0x06810037, 0x027c0045, 0x03040000,
+	0x068100c7, 0x027c0045, 0x03080000, 0x0781061e,
+	0x04908037, 0x029105c4, 0x010410a6, 0x0379ff41,
+	0x037fffff, 0x072d6000, 0x07601241, 0x050f80ff,
+	0x032fa009, 0x05600400, 0x050f80ff, 0x056c04ff,
+	0x068105dc, 0x073fa009, 0x06000001, 0x0279ff02,
+	0x0700ffff, 0x070ff0d1, 0x0179feff, 0x0700ffff,
+	0x045c0402, 0x048185dc, 0x060ff0d0, 0x0179feff,
+	0x0700ffff, 0x057dfeff, 0x0700ffff, 0x078105be,
+	0x05600e41, 0x050f80ff, 0x032fa069, 0x07480000,
+	0x068105d0, 0x06780043, 0x070000f0, 0x0781005f,
+	0x037c00ff, 0x06000010, 0x0781005f, 0x038005cc,
+	0x0379ff00, 0x070fffff, 0x06780043, 0x07f00000,
+	0x075a0000, 0x020ef001, 0x028605ce, 0x05484000,
+	0x02a1819e, 0x062d6001, 0x002fb001, 0x070ff069,
+	0x01868072, 0x060ff079, 0x055c0441, 0x06810010,
+	0x012fb000, 0x060560fb, 0x03800078, 0x060ff079,
+	0x02868198, 0x070ff069, 0x055c0441, 0x06810010,
+	0x060560fb, 0x0400d0d0, 0x062d6002, 0x0648300d,
+	0x06810086, 0x070ff0d1, 0x062d6001, 0x045c040b,
+	0x06810089, 0x05488000, 0x04818086, 0x072e500c,
+	0x00208001, 0x05a004e1, 0x02800010, 0x062d6001,
+	0x07f00000, 0x07f00000, 0x070ff0d1, 0x0179feff,
+	0x070000ff, 0x055c040c, 0x058180bb, 0x0007b001,
+	0x03079041, 0x0307a000, 0x06600a79, 0x050f80ff,
+	0x053fa80a, 0x06000010, 0x072d5003, 0x078d0096,
+	0x0307c003, 0x0007d004, 0x0107e005, 0x0307f006,
+	0x02080007, 0x00081008, 0x01082009, 0x0308300a,
+	0x0008400b, 0x0308500c, 0x068d00a1, 0x0678007a,
+	0x07f00000, 0x010880ff, 0x03386000, 0x03010000,
+	0x072e6300, 0x020ef07f, 0x02860010, 0x070ff07d,
+	0x0450047c, 0x050f80ff, 0x002fa819, 0x068d00ae,
+	0x02080001, 0x00081002, 0x0448807a, 0x068100b5,
+	0x0379ff03, 0x070000ff, 0x01082003, 0x068d00b6,
+	0x02386004, 0x03010000, 0x072e6c00, 0x02800010,
+	0x06780043, 0x070000f0, 0x078105d7, 0x050020ff,
+	0x027c0002, 0x06000010, 0x078100c3, 0x038005d7,
+	0x0700c0d1, 0x0379ff0c, 0x070000ff, 0x0380008e,
+	0x0204a051, 0x06780043, 0x070000f0, 0x037c00ff,
+	0x06000010, 0x0781816a, 0x072d6000, 0x019485c0,
+	0x050fb056, 0x044880e6, 0x04818010, 0x060ff0d0,
+	0x0179feff, 0x0700ffff, 0x057dfeff, 0x0700ffff,
+	0x078105be, 0x05a00212, 0x0349c0e4, 0x0781811d,
+	0x070ff093, 0x050010ff, 0x070ff093, 0x045c0401,
+	0x058180db, 0x02046092, 0x04002046, 0x04600202,
+	0x00540401, 0x048280e6, 0x04500425, 0x070060ff,
+	0x0730ffff, 0x0700000f, 0x0742000f, 0x05810190,
+	0x07a005a6, 0x0648a002, 0x048180e9, 0x00047089,
+	0x070ff047, 0x045c0443, 0x077800ff, 0x07f00000,
+	0x0781818e, 0x07780047, 0x0500e000, 0x048185ad,
+	0x070ff006, 0x01860117, 0x0179fe47, 0x0700000f,
+	0x010480ff, 0x056c7048, 0x06818102, 0x007a0d4a,
+	0x04003801, 0x0220f001, 0x0180010f, 0x07608e48,
+	0x034a60ff, 0x0700f0ff, 0x074b88ff, 0x037000ff,
+	0x07000600, 0x05500448, 0x074d00ff, 0x045a044a,
+	0x0304a0ff, 0x070ff00f, 0x01540406, 0x05820117,
+	0x04950120, 0x05a001bd, 0x02868123, 0x0134bfff,
+	0x070fffff, 0x0104102e, 0x050fd041, 0x00800126,
+	0x0595011d, 0x05a001bd, 0x0186011d, 0x0202f00e,
+	0x052e4030, 0x040fd02f, 0x070fc0ff, 0x05a00218,
+	0x02800010, 0x0400e02f, 0x042e4020, 0x0202f051,
+	0x0004100e, 0x0004b00e, 0x050fd041, 0x024a6c46,
+	0x04500423, 0x050070ff, 0x03620024, 0x050080ff,
+	0x04004046, 0x0700500f, 0x03206000, 0x05601048,
+	0x0700a0ff, 0x0700900a, 0x070ff005, 0x04500446,
+	0x00540425, 0x04820157, 0x05601622, 0x050f80ff,
+	0x063fa032, 0x06000002, 0x03203000, 0x01204000,
+	0x03205000, 0x0120b000, 0x0320c000, 0x07601441,
+	0x050f80ff, 0x043fa852, 0x06000001, 0x070ff056,
+	0x056c02ff, 0x050fb0ff, 0x070560ff, 0x03079041,
+	0x05600e41, 0x050f80ff, 0x073fa011, 0x0600003d,
+	0x06780043, 0x07f00000, 0x065a007a, 0x010880ff,
+	0x04a001b6, 0x058d0150, 0x0208a04a, 0x0108b04b,
+	0x02386001, 0x03010000, 0x072e6300, 0x028000a8,
+	0x0500d00a, 0x05500405, 0x014a68ff, 0x070090ff,
+	0x0154040a, 0x0700c0ff, 0x0600a023, 0x0500b024,
+	0x02206001, 0x05601622, 0x050f80ff, 0x063fa04a,
+	0x06000002, 0x05601022, 0x050f80ff, 0x043fa819,
+	0x06000001, 0x0600a00d, 0x0180013c, 0x06780043,
+	0x070000f0, 0x050010ff, 0x027c0001, 0x07000030,
+	0x078105b4, 0x027c0001, 0x06000020, 0x078105b4,
+	0x038005cc, 0x054880ff, 0x06810010, 0x070ff056,
+	0x050fb0ff, 0x044880e5, 0x0581017d, 0x044880e6,
+	0x04818010, 0x00800183, 0x056c02ff, 0x050fb0ff,
+	0x070560ff, 0x072e5300, 0x044880e6, 0x04818010,
+	0x072d5003, 0x06780043, 0x07f00000, 0x010880ff,
+	0x058d0187, 0x03386005, 0x03010000, 0x033e6000,
+	0x0700000c, 0x052e5200, 0x02800010, 0x0120918e,
+	0x018004e4, 0x01209190, 0x018004e4, 0x00209192,
+	0x018004e4, 0x03209000, 0x018004e4, 0x01209196,
+	0x018004e4, 0x00209198, 0x018004e4, 0x02493075,
+	0x06810510, 0x0120919a, 0x018004e4, 0x06601e01,
+	0x050f80ff, 0x063fa029, 0x06000008, 0x02015010,
+	0x02016051, 0x00017051, 0x00011051, 0x05601a41,
+	0x050f80ff, 0x053fa83a, 0x06000008, 0x05600e41,
+	0x050f80ff, 0x01464000, 0x032fa00a, 0x07006011,
+	0x05007012, 0x04008013, 0x07009014, 0x0600a015,
+	0x0400b016, 0x0700c017, 0x07c00000, 0x072d5003,
+	0x06601479, 0x050f80ff, 0x048d01b9, 0x063fa051,
+	0x0600003e, 0x07c00000, 0x06005051, 0x0400e02c,
+	0x0660060e, 0x050f80ff, 0x032fa009, 0x0379ff00,
+	0x070000ff, 0x076c0000, 0x058101dd, 0x0660480e,
+	0x0500e0ff, 0x034000ff, 0x01540427, 0x0582020a,
+	0x03400005, 0x070ff005, 0x055c0428, 0x0481020e,
+	0x01680e05, 0x056c0405, 0x068181bf, 0x040f8029,
+	0x053fa809, 0x07000024, 0x06600649, 0x050f80ff,
+	0x032fa009, 0x0379ff00, 0x070000ff, 0x076c0000,
+	0x068181bf, 0x0400e049, 0x0340002d, 0x050f802b,
+	0x053fa80a, 0x06000016, 0x0660480e, 0x0302c0ff,
+	0x034000ff, 0x01540427, 0x0582020c, 0x072d6000,
+	0x0460040e, 0x050f80ff, 0x0104e0d1, 0x0379ff4e,
+	0x0700ffff, 0x062d6002, 0x032fa009, 0x0004d0d0,
+	0x074b004d, 0x07780000, 0x07ffff00, 0x055a044d,
+	0x070000ff, 0x00201008, 0x04002051, 0x06003051,
+	0x05304000, 0x07000060, 0x03205009, 0x07006022,
+	0x0460040e, 0x050f80ff, 0x032fa03a, 0x06603c0e,
+	0x050f80ff, 0x073fa00a, 0x07000027, 0x050010d1,
+	0x0460320e, 0x050f80ff, 0x012fa80a, 0x060ff00e,
+	0x055c042e, 0x04810210, 0x07c00000, 0x0400e026,
+	0x008001cb, 0x0202c026, 0x008001e6, 0x0500e02e,
+	0x008001e6, 0x0400e051, 0x01800209, 0x0349c0e4,
+	0x04810215, 0x07c00000, 0x013e4000, 0x070c0000,
+	0x07c00000, 0x013e4000, 0x03080000, 0x07c00000,
+	0x009702f4, 0x022a5002, 0x0790821d, 0x00910291,
+	0x030400a6, 0x0678aae5, 0x06000001, 0x00a1860e,
+	0x06600c40, 0x050f80ff, 0x032fa021, 0x074b0000,
+	0x076c0600, 0x07818293, 0x05600403, 0x050f80ff,
+	0x073fa009, 0x06000002, 0x0279ff04, 0x0700ffff,
+	0x010440d7, 0x0179fe44, 0x0700ffff, 0x045c0404,
+	0x07818295, 0x0349f044, 0x0681829e, 0x02495001,
+	0x06818297, 0x060ff079, 0x045c0440, 0x0781823c,
+	0x0644f07a, 0x002fb008, 0x060ff079, 0x045c0440,
+	0x07818241, 0x0644f07a, 0x002fb008, 0x0648f001,
+	0x07818288, 0x04600e40, 0x050f80ff, 0x06480001,
+	0x04810257, 0x0448e001, 0x04810273, 0x02460001,
+	0x0644f001, 0x012fa80a, 0x04008040, 0x05a004ee,
+	0x0286828c, 0x05a004d8, 0x062da001, 0x013e4000,
+	0x06000080, 0x06930013, 0x02920013, 0x02800010,
+	0x0644f001, 0x012fa80a, 0x020ef002, 0x00860275,
+	0x04600840, 0x050f80ff, 0x053fa809, 0x06000002,
+	0x05780105, 0x00800440, 0x017c0105, 0x05000400,
+	0x06818275, 0x06601e02, 0x050f80ff, 0x053fa809,
+	0x06000002, 0x04602a40, 0x050f80ff, 0x070ff005,
+	0x053fa809, 0x06000002, 0x055c0405, 0x06818275,
+	0x04008040, 0x0045e008, 0x05a004d8, 0x00800251,
+	0x0644f001, 0x012fa80a, 0x050020d8, 0x04600440,
+	0x050f80ff, 0x073fa00a, 0x06000001, 0x06480001,
+	0x07818281, 0x05308000, 0x03040000, 0x06009040,
+	0x04a004dc, 0x00800251, 0x06a0060e, 0x054b0800,
+	0x056a0700, 0x06600c40, 0x050f80ff, 0x032fa00a,
+	0x00800251, 0x013e4000, 0x06000080, 0x01209288,
+	0x018004e4, 0x06009008, 0x05308000, 0x05004000,
+	0x04a004dc, 0x00800251, 0x02209002, 0x008002e5,
+	0x03209000, 0x008002e5, 0x02209004, 0x008002e5,
+	0x04a002fd, 0x062da001, 0x05308000, 0x05002000,
+	0x06009040, 0x04a004dc, 0x02800013, 0x013e4000,
+	0x06000080, 0x02495001, 0x078182db, 0x04600840,
+	0x050f80ff, 0x053fa809, 0x06000001, 0x0721f000,
+	0x0349f003, 0x058102aa, 0x0245f01f, 0x06000002,
+	0x018602db, 0x07601400, 0x050f80ff, 0x012fa809,
+	0x06480001, 0x058102db, 0x06602440, 0x050f80ff,
+	0x012fa809, 0x020ef001, 0x038682db, 0x019b02db,
+	0x050020d8, 0x062da001, 0x06303002, 0x05000430,
+	0x04600440, 0x050f80ff, 0x073fa012, 0x06000001,
+	0x028f82bf, 0x050040d8, 0x062da001, 0x07601e00,
+	0x050f80ff, 0x073fa009, 0x06000001, 0x060ff004,
+	0x00540402, 0x048202d9, 0x06005051, 0x06006051,
+	0x06602240, 0x050f80ff, 0x063fa01a, 0x06000002,
+	0x06600a40, 0x050f80ff, 0x073fa00a, 0x07000003,
+	0x060ff040, 0x045a041f, 0x010eb0ff, 0x06930013,
+	0x02920013, 0x02800010, 0x04004002, 0x018002c9,
+	0x04a002fd, 0x062da001, 0x05308000, 0x07005000,
+	0x06009040, 0x04a004dc, 0x050080d8, 0x05a004e1,
+	0x062da001, 0x02800013, 0x050fd009, 0x050fd041,
+	0x013e4000, 0x06000080, 0x05308000, 0x03013000,
+	0x04a004dc, 0x010440d7, 0x0349f044, 0x048102f2,
+	0x062da001, 0x008f02f2, 0x03e00000, 0x062da001,
+	0x02800013, 0x0249c0e5, 0x06810013, 0x062da001,
+	0x07f00000, 0x07f00000, 0x033e5000, 0x070c0000,
+	0x018f02f6, 0x03800011, 0x050020d8, 0x04600440,
+	0x050f80ff, 0x073fa00a, 0x06000001, 0x07c00000,
+	0x002fb001, 0x03800306, 0x012fb000, 0x03075087,
+	0x068d0307, 0x03386000, 0x03020000, 0x04482075,
+	0x06810352, 0x0648a0e6, 0x07810347, 0x0642007f,
+	0x06810345, 0x0340007e, 0x060ff038, 0x0154047e,
+	0x02d00334, 0x0560027d, 0x050f80ff, 0x032fa009,
+	0x030ef000, 0x02860504, 0x0107d000, 0x05600800,
+	0x050f80ff, 0x032fa009, 0x03681e00, 0x04500420,
+	0x050f80ff, 0x073fa009, 0x0700003f, 0x03800311,
+	0x070ff07d, 0x0450047c, 0x050f80ff, 0x002fa819,
+	0x078d0327, 0x02080001, 0x00081002, 0x0448807a,
+	0x0781032e, 0x0379ff03, 0x070000ff, 0x01082003,
+	0x068d032f, 0x02386004, 0x03010000, 0x072e6c00,
+	0x02800352, 0x0380033a, 0x0380033c, 0x0280033e,
+	0x02800340, 0x03800342, 0x03800344, 0x0727c005,
+	0x02800323, 0x0627c008, 0x02800323, 0x0627c00b,
+	0x02800323, 0x0627c00e, 0x02800323, 0x0727c011,
+	0x02800323, 0x03800314, 0x052e6800, 0x02800352,
+	0x044880e6, 0x07810533, 0x052e6200, 0x070ff088,
+	0x0179feff, 0x070fffff, 0x04818501, 0x060ff083,
+	0x0086836d, 0x033e6000, 0x07000003, 0x068d0352,
+	0x07286000, 0x07f00000, 0x078d0355, 0x038c0306,
+	0x0648c0e6, 0x05818372, 0x0448e0e6, 0x0781036a,
+	0x004920e6, 0x07810365, 0x07a0056f, 0x05001088,
+	0x00700101, 0x03100000, 0x00088001, 0x033e6000,
+	0x07000088, 0x03800560, 0x02386001, 0x07030000,
+	0x033e6000, 0x06000008, 0x028003f1, 0x02799075,
+	0x0500040f, 0x06810010, 0x06601479, 0x050080ff,
+	0x06309052, 0x0600003e, 0x02800376, 0x06602279,
+	0x050080ff, 0x05309812, 0x07000041, 0x0648007a,
+	0x0781037e, 0x04488075, 0x0581837e, 0x040f8008,
+	0x070fa009, 0x0049107a, 0x01a183f3, 0x00798075,
+	0x06000507, 0x05818521, 0x0448b075, 0x06810385,
+	0x02493075, 0x0681050e, 0x0249c0e6, 0x048183e0,
+	0x0648c0e6, 0x0581839a, 0x068d0389, 0x02386001,
+	0x07030000, 0x0049107a, 0x07810390, 0x020ef083,
+	0x0386039a, 0x06483075, 0x068103ef, 0x0678007a,
+	0x07000035, 0x03a184cf, 0x05308000, 0x07060000,
+	0x06009079, 0x04a004dc, 0x028003ef, 0x0448807a,
+	0x0681039e, 0x06483075, 0x058104f9, 0x0448d07a,
+	0x068103a2, 0x06483075, 0x058104f9, 0x068d03a2,
+	0x02386001, 0x07030000, 0x0444e07a, 0x0648307a,
+	0x048183c7, 0x0448707a, 0x068103ea, 0x0648f07a,
+	0x078103b2, 0x05a004cf, 0x04008079, 0x05a004ee,
+	0x008683c2, 0x05a004d8, 0x028003ef, 0x0560107b,
+	0x050f80ff, 0x032fa009, 0x0349c000, 0x058183c0,
+	0x04600e79, 0x050f80ff, 0x073fa00a, 0x0600003d,
+	0x06600a79, 0x050f80ff, 0x053fa80a, 0x06000010,
+	0x028003ef, 0x0046e07a, 0x028003ea, 0x06009008,
+	0x05308000, 0x05004000, 0x04a004dc, 0x028003ef,
+	0x0560167b, 0x050f80ff, 0x032fa011, 0x070ff000,
+	0x04500401, 0x030460ff, 0x060ff025, 0x00540446,
+	0x078203d1, 0x030460ff, 0x04092046, 0x05a00218,
+	0x06600679, 0x050f80ff, 0x00201007, 0x012fa80a,
+	0x0046047a, 0x034630ff, 0x050020ff, 0x06003051,
+	0x04600e79, 0x050f80ff, 0x073fa012, 0x06000001,
+	0x028003ef, 0x033e6a00, 0x0202000e, 0x02079051,
+	0x07000088, 0x078d03e4, 0x0744c000, 0x01088000,
+	0x03386006, 0x03010000, 0x02800010, 0x05a004cf,
+	0x05308000, 0x03020000, 0x06009079, 0x04a004dc,
+	0x033e6a00, 0x0302000a, 0x02079051, 0x02800010,
+	0x04603e79, 0x050f80ff, 0x032fa009, 0x070ff000,
+	0x0186040c, 0x057dfeff, 0x07ffffff, 0x0581040c,
+	0x050f8000, 0x012fa811, 0x0079fe02, 0x070000ff,
+	0x077d66ff, 0x060000dc, 0x0781840c, 0x060ff001,
+	0x0286840d, 0x064b0002, 0x06420002, 0x060ff002,
+	0x05500400, 0x050f80ff, 0x05004084, 0x073fa00a,
+	0x06000002, 0x07c00000, 0x04600201, 0x050f80ff,
+	0x073fa009, 0x06000001, 0x0079fe02, 0x070000ff,
+	0x077d72ff, 0x070000dd, 0x0781840c, 0x064b0002,
+	0x06420002, 0x06000001, 0x01800406, 0x0605004c,
+	0x0180041e, 0x0493041a, 0x04a004d5, 0x054bc450,
+	0x05810421, 0x01d00422, 0x01800421, 0x00800432,
+	0x00800434, 0x00800432, 0x008004a7, 0x0180043f,
+	0x00800434, 0x01800471, 0x00800432, 0x00800432,
+	0x008004ab, 0x00800432, 0x018004af, 0x008004c4,
+	0x01800488, 0x00800432, 0x00800432, 0x00209432,
+	0x018004e4, 0x0379ff50, 0x070fffff, 0x060ff079,
+	0x055c0450, 0x048104a4, 0x002fb008, 0x060ff079,
+	0x055c0450, 0x058104a3, 0x04a004c7, 0x0180049c,
+	0x0179fe50, 0x070fffff, 0x070050ff, 0x060ff079,
+	0x055c0405, 0x04810449, 0x002fb008, 0x060ff079,
+	0x055c0405, 0x078184a0, 0x070ff087, 0x017980ff,
+	0x06000507, 0x06818451, 0x02203040, 0x05002087,
+	0x0049d002, 0x0481046b, 0x04930458, 0x01257000,
+	0x073c3fff, 0x0700000f, 0x052e4003, 0x072e5030,
+	0x0304c050, 0x02400057, 0x06740057, 0x06000002,
+	0x06820016, 0x04002083, 0x07003084, 0x04004085,
+	0x06602279, 0x050f80ff, 0x063fa01a, 0x06000001,
+	0x05a004cf, 0x07a00578, 0x033e6a00, 0x0302000a,
+	0x062e5020, 0x003e4002, 0x07000a00, 0x028003f1,
+	0x07420003, 0x0781844e, 0x00798002, 0x06000507,
+	0x06818451, 0x0180045c, 0x05930478, 0x01257000,
+	0x073c3fff, 0x0700000f, 0x052e4003, 0x072e5030,
+	0x0304c050, 0x067800e6, 0x07000041, 0x0581047d,
+	0x07a00581, 0x04818016, 0x002fb008, 0x067800e6,
+	0x07000041, 0x04810483, 0x07a00581, 0x04818016,
+	0x062e5020, 0x003e4002, 0x07000a00, 0x03e00000,
+	0x02800010, 0x0379ff50, 0x070fffff, 0x060ff079,
+	0x055c0450, 0x0781848e, 0x0245507a, 0x002fb008,
+	0x060ff079, 0x055c0450, 0x07818493, 0x0245507a,
+	0x002fb008, 0x05600e50, 0x050f80ff, 0x012fa809,
+	0x02455001, 0x05600e50, 0x050f80ff, 0x012fa80a,
+	0x0080049d, 0x002fb008, 0x003e4002, 0x07000a00,
+	0x02800016, 0x079384a3, 0x062e5020, 0x042e4002,
+	0x002fb008, 0x013e4000, 0x05000e00, 0x02800016,
+	0x0179fe50, 0x070fffff, 0x010210ff, 0x02800016,
+	0x0179fe50, 0x070fffff, 0x050340ff, 0x0080049d,
+	0x0179fe50, 0x070fffff, 0x0102e0ff, 0x0760282e,
+	0x050f80ff, 0x05222000, 0x07223000, 0x05224000,
+	0x07225000, 0x07226000, 0x05227000, 0x05228000,
+	0x07229000, 0x0722a000, 0x0522b000, 0x063fa051,
+	0x07000011, 0x0202c026, 0x0522d000, 0x052e400c,
+	0x02800016, 0x030430d4, 0x062e5008, 0x00800176,
+	0x05600e50, 0x050f80ff, 0x032fa009, 0x03460000,
+	0x018004d2, 0x0246007a, 0x0045207a, 0x008004d0,
+	0x0246007a, 0x0600007a, 0x04600e79, 0x050f80ff,
+	0x032fa00a, 0x07c00000, 0x029284d5, 0x070500e1,
+	0x07c00000, 0x0245f008, 0x048404d9, 0x020e0008,
+	0x07c00000, 0x070ff009, 0x065a0008, 0x058404de,
+	0x020e0008, 0x07c00000, 0x058404e1, 0x020e0008,
+	0x07c00000, 0x05308000, 0x0500d000, 0x04a004dc,
+	0x04a004e9, 0x02800010, 0x052e4300, 0x072e500c,
+	0x073c3fff, 0x0700000f, 0x07c00000, 0x06602208,
+	0x050f80ff, 0x032fa011, 0x076a0000, 0x068184f7,
+	0x066a0001, 0x048104f7, 0x04002051, 0x07c00000,
+	0x00202001, 0x07c00000, 0x0648307a, 0x00a18608,
+	0x05a004cc, 0x05308000, 0x05001000, 0x06009079,
+	0x04a004dc, 0x03800560, 0x0249c0e6, 0x058104f9,
+	0x0280036d, 0x0648307a, 0x07818196, 0x05a004cf,
+	0x05308000, 0x03013000, 0x03209006, 0x04a004dc,
+	0x033e6000, 0x07030000, 0x02800345, 0x02490075,
+	0x0781051e, 0x04002089, 0x04780102, 0x07f00000,
+	0x05001088, 0x07a0056f, 0x04740101, 0x03100000,
+	0x060ff002, 0x045c0401, 0x0481851f, 0x00088001,
+	0x033e6000, 0x070000c0, 0x0380055c, 0x07f00000,
+	0x0220951f, 0x018004e4, 0x0648307a, 0x07810527,
+	0x06780075, 0x06000007, 0x0581852e, 0x06a00608,
+	0x06486075, 0x06818194, 0x02490075, 0x0781819a,
+	0x04487075, 0x05818536, 0x0280053d, 0x05308000,
+	0x03010000, 0x06009079, 0x04a004dc, 0x02800010,
+	0x0448e0e6, 0x04818352, 0x00800192, 0x05308000,
+	0x0500e000, 0x06009079, 0x04a004dc, 0x04008089,
+	0x05a004e1, 0x0380055c, 0x05a004cc, 0x05308000,
+	0x0700f000, 0x06009079, 0x07000088, 0x06a00545,
+	0x04a004dc, 0x02800010, 0x03386000, 0x07030000,
+	0x07f00000, 0x078d0548, 0x033e6a00, 0x0202000e,
+	0x02079051, 0x0448b075, 0x07810553, 0x02493075,
+	0x07810553, 0x05301005, 0x03010000, 0x03800555,
+	0x05301006, 0x03010000, 0x05002087, 0x06485002,
+	0x05818555, 0x0744c000, 0x01088000, 0x02086001,
+	0x07c00000, 0x05001088, 0x07a0056f, 0x0644c001,
+	0x00088001, 0x033e6a00, 0x0202000e, 0x004920e6,
+	0x05818565, 0x02079051, 0x078d0565, 0x060ff089,
+	0x034990ff, 0x0781056c, 0x03386005, 0x03010000,
+	0x02800010, 0x03386006, 0x03010000, 0x02800010,
+	0x078d056f, 0x03386000, 0x07030000, 0x07f00000,
+	0x068d0573, 0x070ff087, 0x074850ff, 0x05818574,
+	0x07c00000, 0x078d0578, 0x02386001, 0x07030000,
+	0x07f00000, 0x068d057c, 0x070ff087, 0x074850ff,
+	0x0581857d, 0x07c00000, 0x05002087, 0x0049d002,
+	0x05818590, 0x002fb008, 0x067800e6, 0x07000041,
+	0x002fb008, 0x05818590, 0x07a005a6, 0x0448e002,
+	0x07810593, 0x0648a002, 0x0481859d, 0x06486002,
+	0x06810597, 0x02400057, 0x056a02ff, 0x07c00000,
+	0x07a005a6, 0x06788102, 0x06000004, 0x05818590,
+	0x04002089, 0x070ff0d4, 0x045c0402, 0x077800ff,
+	0x07f00000, 0x05818590, 0x00202010, 0x038c0590,
+	0x07f00000, 0x06420002, 0x0481859e, 0x07a00578,
+	0x033e6a00, 0x0302000a, 0x07c00000, 0x07f00000,
+	0x060ff0a2, 0x050020ff, 0x060ff0a2, 0x045c0402,
+	0x048185a7, 0x07c00000, 0x05a00218, 0x03495047,
+	0x078105b2, 0x0320901d, 0x02800604, 0x0220901f,
+	0x02800604, 0x014980e4, 0x04818010, 0x013e4000,
+	0x07003000, 0x05600e35, 0x050f80ff, 0x07a006fc,
+	0x01208003, 0x05a004e1, 0x038005cc, 0x03209009,
+	0x02800604, 0x03209011, 0x02800604, 0x02209007,
+	0x02800604, 0x03209003, 0x02800604, 0x00498043,
+	0x058185be, 0x00497043, 0x048185c2, 0x02209001,
+	0x02800604, 0x0220900d, 0x02800604, 0x0320900f,
+	0x02800604, 0x03493000, 0x068105d5, 0x027c0045,
+	0x070a0000, 0x078105de, 0x0220900b, 0x02800604,
+	0x02209013, 0x05308000, 0x01012000, 0x04a004dc,
+	0x00800183, 0x03209005, 0x02800604, 0x072e500c,
+	0x00208002, 0x05a004e1, 0x02800010, 0x02209015,
+	0x02800604, 0x072d6000, 0x05308000, 0x05007000,
+	0x07f00000, 0x070090d1, 0x0379ff09, 0x0700ffff,
+	0x04a004dc, 0x03209017, 0x02800604, 0x033e5000,
+	0x06000080, 0x02209019, 0x02800604, 0x072d6000,
+	0x033e5000, 0x06000080, 0x07f00000, 0x060ff0d0,
+	0x0179feff, 0x0700ffff, 0x057dfeff, 0x0700ffff,
+	0x04818010, 0x02400058, 0x00642058, 0x06820010,
+	0x033e5000, 0x06000080, 0x04058051, 0x0320901b,
+	0x02800604, 0x05308000, 0x01012000, 0x04a004dc,
+	0x00800176, 0x05a00218, 0x05308000, 0x05008000,
+	0x06009079, 0x04a004dc, 0x07c00000, 0x034900e4,
+	0x05818618, 0x013e4000, 0x070000c0, 0x07f00000,
+	0x034900e4, 0x04818616, 0x07c00000, 0x013e4000,
+	0x06000080, 0x07f00000, 0x07f00000, 0x07f00000,
+	0x034900e4, 0x06810610, 0x03800618, 0x072d6000,
+	0x00498043, 0x06810632, 0x060ff0d0, 0x0179feff,
+	0x0700ffff, 0x057dfeff, 0x0700ffff, 0x058185e2,
+	0x050f8030, 0x032fa009, 0x0379ff00, 0x0700ffff,
+	0x070ff0d1, 0x0179feff, 0x0700ffff, 0x055c0400,
+	0x078105e2, 0x04004051, 0x0280067a, 0x06a006dc,
+	0x062d6001, 0x020ef004, 0x038605e4, 0x06600004,
+	0x050f80ff, 0x032fa009, 0x074b0000, 0x05002000,
+	0x0769ff00, 0x01640800, 0x078205e4, 0x01640e00,
+	0x058285e4, 0x070ff036, 0x045c0404, 0x0581864d,
+	0x072d6000, 0x050f8030, 0x032fa009, 0x0379ff00,
+	0x0700ffff, 0x070ff0d1, 0x0179feff, 0x0700ffff,
+	0x055c0400, 0x078105e2, 0x04482034, 0x078105ff,
+	0x06483034, 0x058185ff, 0x070ff0d4, 0x077800ff,
+	0x070000f0, 0x037c00ff, 0x06000010, 0x0681067a,
+	0x06a006d6, 0x024900e5, 0x0681065d, 0x033e5000,
+	0x06000080, 0x02800010, 0x04601c04, 0x050f80ff,
+	0x053fa809, 0x06000020, 0x030ef041, 0x038605ee,
+	0x062d6002, 0x05602a41, 0x050f80ff, 0x012fa809,
+	0x060ff0d0, 0x074b00ff, 0x045c0401, 0x05818678,
+	0x062d6001, 0x07602841, 0x050f80ff, 0x053fa809,
+	0x06000001, 0x070ff0d1, 0x054b80ff, 0x074b0003,
+	0x055c0403, 0x05818678, 0x033e5000, 0x06000080,
+	0x0080070e, 0x07600041, 0x0280065e, 0x06a006d6,
+	0x024900e5, 0x06810680, 0x033e5000, 0x06000080,
+	0x02800010, 0x06a006c2, 0x030ef041, 0x028605f2,
+	0x04058051, 0x072d6000, 0x05601041, 0x050f80ff,
+	0x012fa809, 0x0600a0d0, 0x0500b0d1, 0x062d6001,
+	0x07f00000, 0x07f00000, 0x0600c0d0, 0x0500d0d1,
+	0x062d6002, 0x0279ff0d, 0x07ff0000, 0x044d800d,
+	0x060ff0d0, 0x074b00ff, 0x065a000d, 0x06601201,
+	0x050f80ff, 0x073fa022, 0x07000005, 0x0079fe0d,
+	0x070000ff, 0x050020ff, 0x05602a41, 0x050f80ff,
+	0x073fa00a, 0x06000001, 0x020ef004, 0x028606bf,
+	0x04601c04, 0x050f80ff, 0x053fa809, 0x06000001,
+	0x050f80ff, 0x053fa80a, 0x06000020, 0x07602841,
+	0x050f80ff, 0x073fa009, 0x06000001, 0x0279ff02,
+	0x070000ff, 0x0678000d, 0x0700ff00, 0x065a0002,
+	0x07602841, 0x050f80ff, 0x073fa00a, 0x06000001,
+	0x07600041, 0x050f80ff, 0x053fa80a, 0x06000001,
+	0x07601241, 0x050f80ff, 0x073fa00a, 0x06000002,
+	0x033e5000, 0x06000080, 0x0080070e, 0x040f8032,
+	0x073fa011, 0x06000001, 0x060ff002, 0x055c0403,
+	0x058186ca, 0x00041051, 0x07c00000, 0x04600402,
+	0x04500432, 0x050f80ff, 0x053fa809, 0x06000020,
+	0x00400402, 0x01680eff, 0x070030ff, 0x040f8032,
+	0x053fa80a, 0x06000001, 0x07c00000, 0x024900e5,
+	0x068106d9, 0x07c00000, 0x033e5000, 0x070000c0,
+	0x07c00000, 0x05004036, 0x060000d0, 0x0179fe00,
+	0x0700ffff, 0x057dfeff, 0x0700ffff, 0x068106fb,
+	0x070000d1, 0x0379ff00, 0x0700ffff, 0x06005051,
+	0x060ff031, 0x05500405, 0x050f80ff, 0x073fa009,
+	0x06000002, 0x020ef004, 0x038606f5, 0x04600404,
+	0x050f80ff, 0x012fa809, 0x0079fe01, 0x0700ffff,
+	0x055c0400, 0x068106fb, 0x01400405, 0x070050ff,
+	0x057de0ff, 0x06000007, 0x058186e7, 0x04004051,
+	0x07c00000, 0x072d6000, 0x07f00000, 0x07f00000,
+	0x000110d0, 0x010120d1, 0x062d6001, 0x07f00000,
+	0x07f00000, 0x020130d0, 0x010140d1, 0x062d6002,
+	0x010170d4, 0x07f00000, 0x020150d0, 0x030160d1,
+	0x053fa83a, 0x06000008, 0x07c00000, 0x07600c41,
+	0x050f80ff, 0x073fa009, 0x06000001, 0x04780102,
+	0x07ffff00, 0x046a0702, 0x050f80ff, 0x073fa00a,
+	0x06000001, 0x05600e41, 0x050f80ff, 0x032fa069,
+	0x03800053, 0xba6b4e34, 0x02800004, 0x00000000,
+	0x00008000, 0x00000518, 0x040f801f, 0x012fa8c9,
+	0x040f801f, 0x073fa081, 0x06000010, 0x03200005,
+	0x07420000, 0x050fb000, 0x040f801f, 0x073fa011,
+	0x06000038, 0x040f801f, 0x053fa859, 0x0700003a,
+	0x050fe000, 0x0581800a, 0x0684003d, 0x04958019,
+	0x030e0011, 0x072e4200, 0x03800014, 0x0291001f,
+	0x050010c0, 0x04482001, 0x058180e8, 0x06483001,
+	0x0781814b, 0x02920029, 0x068b0029, 0x018a0150,
+	0x050010c0, 0x06780001, 0x050007c0, 0x06818223,
+	0x06780001, 0x0500f800, 0x07818263, 0x03910030,
+	0x040fe029, 0x03860030, 0x076c001d, 0x04810294,
+	0x076c0a1d, 0x048102b9, 0x0292003d, 0x040fe02f,
+	0x0286003d, 0x06000013, 0x050fb000, 0x066c0073,
+	0x068103c2, 0x0297003d, 0x014920e4, 0x0481803d,
+	0x03400000, 0x076c0a00, 0x04818034, 0x0796003f,
+	0x03b900b8, 0x05908014, 0x010170e1, 0x07780017,
+	0x03e00000, 0x06810092, 0x050010ff, 0x0179fe17,
+	0x031fffff, 0x070000ff, 0x05600800, 0x050f80ff,
+	0x073fa009, 0x06000001, 0x06780002, 0x02800040,
+	0x037c00ff, 0x03800000, 0x0681005e, 0x0249f002,
+	0x068100ab, 0x0448e002, 0x0681005e, 0x07600c00,
+	0x050f80ff, 0x073fa009, 0x06000001, 0x06780002,
+	0x07ffff00, 0x037c00ff, 0x05000200, 0x048180ab,
+	0x064bd401, 0x03d00060, 0x038000a9, 0x02800068,
+	0x03800072, 0x0280007c, 0x02800086, 0x03800090,
+	0x038000a9, 0x038000a9, 0x050fe027, 0x0186806c,
+	0x01028000, 0x0380006f, 0x07600027, 0x050f80ff,
+	0x032fa00a, 0x01027000, 0x02400029, 0x028000ab,
+	0x040fe025, 0x00868076, 0x03026000, 0x02800079,
+	0x06600025, 0x050f80ff, 0x032fa00a, 0x03025000,
+	0x02400029, 0x028000ab, 0x050fe021, 0x00868080,
+	0x01022000, 0x02800083, 0x07600021, 0x050f80ff,
+	0x032fa00a, 0x01021000, 0x02400029, 0x028000ab,
+	0x040fe023, 0x0086808a, 0x01024000, 0x0380008d,
+	0x06600023, 0x050f80ff, 0x032fa00a, 0x03023000,
+	0x02400029, 0x028000ab, 0x06a000c8, 0x028000ab,
+	0x01640817, 0x058280a9, 0x070ff017, 0x03d00096,
+	0x0280009e, 0x038000a0, 0x038000a3, 0x038000a6,
+	0x038000a9, 0x038000a9, 0x038000a9, 0x038000a9,
+	0x03e00000, 0x03800014, 0x059080a0, 0x030160e1,
+	0x028000ab, 0x059080a3, 0x030150e1, 0x028000ab,
+	0x059080a6, 0x010140e1, 0x028000ab, 0x060fc013,
+	0x06a00510, 0x03800014, 0x072e4800, 0x07000012,
+	0x038000bb, 0x0747f000, 0x05600800, 0x050f80ff,
+	0x012fa809, 0x0249f001, 0x078100bb, 0x01012000,
+	0x052e4c00, 0x07c00000, 0x070000eb, 0x0349f000,
+	0x058180af, 0x05600800, 0x050f80ff, 0x012fa809,
+	0x0448e001, 0x068100c1, 0x07c00000, 0x0079c101,
+	0x07ffffff, 0x027a4b01, 0x03800000, 0x05600800,
+	0x050f80ff, 0x012fa80a, 0x07600c00, 0x050f80ff,
+	0x012fa821, 0x06780001, 0x07ffff00, 0x037c00ff,
+	0x05000700, 0x078100dd, 0x06601804, 0x070030ff,
+	0x050f80ff, 0x012fa809, 0x05002000, 0x050f8003,
+	0x073fa00a, 0x06000001, 0x040fe001, 0x038600de,
+	0x04600201, 0x050f80ff, 0x032fa00a, 0x07c00000,
+	0x050fe02e, 0x008680e3, 0x0102e000, 0x0302f000,
+	0x038000e7, 0x0760002e, 0x050f80ff, 0x032fa00a,
+	0x0102e000, 0x07c00000, 0x022c0004, 0x056c041d,
+	0x078100fc, 0x056c021d, 0x04810113, 0x056c081d,
+	0x04810125, 0x076c061d, 0x0581013f, 0x0521d000,
+	0x0202c013, 0x0202a013, 0x02020013, 0x0460021a,
+	0x050f80ff, 0x053fa80a, 0x07000009, 0x03b600ac,
+	0x0484801f, 0x0280003d, 0x040fe02a, 0x028600f2,
+	0x06000013, 0x04001013, 0x0560102b, 0x050f80ff,
+	0x032fa012, 0x06420029, 0x0660002a, 0x050f80ff,
+	0x053fa809, 0x06000001, 0x050fe003, 0x00860110,
+	0x01028003, 0x0660002a, 0x050f80ff, 0x053fa80a,
+	0x07000009, 0x00800140, 0x00028013, 0x00027013,
+	0x00800140, 0x040fe02a, 0x028600f1, 0x06420029,
+	0x0660002a, 0x050f80ff, 0x053fa809, 0x06000001,
+	0x050fe003, 0x01860122, 0x03026003, 0x0660002a,
+	0x050f80ff, 0x053fa80a, 0x07000009, 0x00800140,
+	0x02026013, 0x02025013, 0x00800140, 0x040fe02a,
+	0x028600f1, 0x06420029, 0x0660002a, 0x050f80ff,
+	0x053fa809, 0x06000001, 0x050fe003, 0x00860134,
+	0x01022003, 0x0660002a, 0x050f80ff, 0x053fa80a,
+	0x07000009, 0x01800136, 0x00022013, 0x00021013,
+	0x0647f020, 0x007a0120, 0x04000101, 0x04a00285,
+	0x0400802a, 0x05a004f5, 0x009480f1, 0x0521d005,
+	0x028000f2, 0x038000fa, 0x0647f020, 0x06486020,
+	0x06818145, 0x04a00285, 0x028000f1, 0x007a0120,
+	0x04000101, 0x04a00285, 0x0400802a, 0x05a004f5,
+	0x028000f1, 0x040fd02a, 0x052e4003, 0x00208010,
+	0x05a004f5, 0x038000fa, 0x00018098, 0x07480018,
+	0x06818161, 0x05481018, 0x0781815f, 0x05482018,
+	0x0681815d, 0x07483018, 0x0681815b, 0x002fb004,
+	0x00800162, 0x012fb003, 0x00800162, 0x002fb002,
+	0x00800162, 0x002fb001, 0x00800162, 0x012fb000,
+	0x0179fe78, 0x070000ff, 0x030190ff, 0x00017086,
+	0x058b0166, 0x03385000, 0x03020000, 0x07780017,
+	0x00430407, 0x078181ee, 0x046c0419, 0x048101a2,
+	0x046c0219, 0x05810172, 0x07219000, 0x00800186,
+	0x07219000, 0x07483017, 0x0481018c, 0x05482017,
+	0x05810193, 0x0448b075, 0x06818186, 0x06601476,
+	0x050f80ff, 0x073fa022, 0x0600003e, 0x06000080,
+	0x05001081, 0x05002082, 0x06003083, 0x05004084,
+	0x04601c76, 0x050f80ff, 0x022fa02a, 0x07219000,
+	0x07780078, 0x07ffff00, 0x045a0419, 0x010780ff,
+	0x0484801f, 0x0280003d, 0x040fe07f, 0x0086019b,
+	0x05a001bb, 0x00920186, 0x040fe07f, 0x07a681bb,
+	0x00800186, 0x0560107b, 0x050f80ff, 0x032fa009,
+	0x0744f000, 0x0560107b, 0x050f80ff, 0x032fa00a,
+	0x00800179, 0x052e400c, 0x040080fb, 0x046aa108,
+	0x06009076, 0x04002075, 0x05a004fc, 0x00800186,
+	0x06219001, 0x05482017, 0x058101af, 0x058b01a5,
+	0x060ff086, 0x0349f0ff, 0x07818165, 0x07483017,
+	0x058101ac, 0x050fd0ff, 0x040fe07f, 0x07a681bb,
+	0x00800186, 0x05004084, 0x05a00205, 0x00920186,
+	0x070ff07d, 0x0450047c, 0x056004ff, 0x050f80ff,
+	0x032fa009, 0x070ff000, 0x00540479, 0x030790ff,
+	0x01800193, 0x060ff079, 0x0054047a, 0x058201e7,
+	0x058101e7, 0x070ff07d, 0x0450047c, 0x050f80ff,
+	0x002fa819, 0x058b01c3, 0x02080001, 0x00081002,
+	0x01082003, 0x048b01c7, 0x03385000, 0x03010000,
+	0x02400019, 0x070ff003, 0x04500479, 0x030790ff,
+	0x0340007e, 0x0642007f, 0x058101e7, 0x070ff07e,
+	0x050f80ff, 0x032fa009, 0x050fe000, 0x028681e6,
+	0x070ff07d, 0x056002ff, 0x050f80ff, 0x032fa009,
+	0x0107d000, 0x018601e8, 0x0560087d, 0x050f80ff,
+	0x032fa009, 0x0569fe00, 0x0550041b, 0x050f80ff,
+	0x032fa009, 0x0107e000, 0x070ff07e, 0x018001d2,
+	0x0307c000, 0x07c00000, 0x052e400c, 0x040080fb,
+	0x046aa108, 0x06009076, 0x04002075, 0x018004fc,
+	0x040fd076, 0x050fd017, 0x060ff086, 0x077800ff,
+	0x07000060, 0x037c00ff, 0x07000060, 0x078181f0,
+	0x07780078, 0x07ffff00, 0x045a0419, 0x010780ff,
+	0x06601476, 0x050f80ff, 0x073fa022, 0x0600003e,
+	0x052e400c, 0x040080fb, 0x066a8108, 0x06009076,
+	0x04002075, 0x05a004fc, 0x02800029, 0x0240007f,
+	0x0742007e, 0x050f807e, 0x032fa009, 0x050fe000,
+	0x0286821f, 0x070ff07d, 0x055c047b, 0x05810214,
+	0x0760007d, 0x050f80ff, 0x032fa009, 0x050fe000,
+	0x03868214, 0x070ff07b, 0x0107d0ff, 0x0560087d,
+	0x050f80ff, 0x032fa009, 0x03681e00, 0x0450041c,
+	0x0107e0ff, 0x050f80ff, 0x032fa009, 0x050fe000,
+	0x01860221, 0x0307c000, 0x07c00000, 0x040fd076,
+	0x02800510, 0x010180c0, 0x0548e018, 0x0781823c,
+	0x0748f018, 0x06818238, 0x03490018, 0x06818234,
+	0x01491018, 0x07818230, 0x073c0000, 0x06000040,
+	0x02200004, 0x0180023f, 0x073c0000, 0x06000020,
+	0x03200003, 0x0180023f, 0x073c0000, 0x06000010,
+	0x02200002, 0x0180023f, 0x073c0000, 0x06000008,
+	0x02200001, 0x0180023f, 0x073c0000, 0x06000004,
+	0x06000013, 0x050fb000, 0x040fe076, 0x00860258,
+	0x046c0273, 0x04810268, 0x066c0073, 0x04810249,
+	0x040fd076, 0x06a00510, 0x03800014, 0x040fd076,
+	0x0080024c, 0x00452075, 0x00077013, 0x0647f075,
+	0x06486075, 0x06818252, 0x05a0028b, 0x00800258,
+	0x007a0175, 0x04000101, 0x05a0028b, 0x04008076,
+	0x0245f008, 0x05a004f5, 0x07273000, 0x05600272,
+	0x050f80ff, 0x053fa80a, 0x07000009, 0x0379ff78,
+	0x070000ff, 0x02076013, 0x02075013, 0x0484801f,
+	0x0280003d, 0x070fc0ff, 0x052e400c, 0x00208020,
+	0x05a004f5, 0x00800261, 0x04600276, 0x050010ff,
+	0x040f8001, 0x032fa009, 0x040f8001, 0x053fa80a,
+	0x07000009, 0x070ff000, 0x0286827a, 0x06601276,
+	0x050f80ff, 0x073fa009, 0x0700000c, 0x07601818,
+	0x050f80ff, 0x053fa80a, 0x07000009, 0x0180027b,
+	0x07a000de, 0x0448b075, 0x0581024b, 0x06000013,
+	0x04001013, 0x0560107b, 0x050f80ff, 0x032fa012,
+	0x0046b075, 0x03b600ac, 0x0080024c, 0x06000020,
+	0x04001016, 0x0460082a, 0x050f80ff, 0x032fa012,
+	0x07c00000, 0x06000075, 0x040010a2, 0x044b0801,
+	0x060ff016, 0x065a0001, 0x04600876, 0x050f80ff,
+	0x032fa012, 0x07c00000, 0x050fe022, 0x0186029a,
+	0x0421d004, 0x0302a022, 0x04a002c1, 0x018002b1,
+	0x040fe026, 0x008602b3, 0x0421d001, 0x0202a026,
+	0x04a002c1, 0x0202c013, 0x00683e20, 0x070060ff,
+	0x056c0206, 0x048102f4, 0x056c0406, 0x0781030a,
+	0x076c0606, 0x06810379, 0x056c1606, 0x078182b1,
+	0x04488020, 0x07810387, 0x040fd02a, 0x0521d000,
+	0x0202a013, 0x02020013, 0x008002b3, 0x04a004ec,
+	0x008002bf, 0x050fe028, 0x008602bf, 0x0302a028,
+	0x0421d002, 0x04a002c1, 0x008002c8, 0x050fe022,
+	0x008602bf, 0x0421d004, 0x0302a022, 0x04a002c1,
+	0x04a004ec, 0x05848030, 0x0280003d, 0x0460082a,
+	0x050f80ff, 0x022fa031, 0x03020000, 0x0002b004,
+	0x01018005, 0x07c00000, 0x0400702a, 0x06a003ba,
+	0x007a0101, 0x07060000, 0x07303000, 0x07008290,
+	0x07600018, 0x050f80ff, 0x053fa809, 0x07000003,
+	0x0448e007, 0x068182d6, 0x06006013, 0x018002dd,
+	0x02400010, 0x048102d6, 0x06006010, 0x0460322a,
+	0x050f80ff, 0x073fa00a, 0x07000003, 0x050f801e,
+	0x032fa03a, 0x063aa020, 0x06000002, 0x013e4000,
+	0x07000030, 0x009802e3, 0x070ff0f6, 0x036830ff,
+	0x078182e4, 0x070f001e, 0x0560102b, 0x050f10ff,
+	0x063f3c08, 0x0600000d, 0x013e4000, 0x06000020,
+	0x040f801a, 0x0320000a, 0x022017d0, 0x032fa012,
+	0x0202c013, 0x008002bf, 0x04007013, 0x06a003ba,
+	0x007a0101, 0x07050000, 0x07303000, 0x07008890,
+	0x074d0005, 0x06006013, 0x050f801e, 0x032fa03a,
+	0x05601a2b, 0x050f80ff, 0x022fa019, 0x04001002,
+	0x04002013, 0x040f801f, 0x022fa01a, 0x073aa00c,
+	0x06000002, 0x07300c03, 0x0600000d, 0x028003a7,
+	0x04007013, 0x06a003ba, 0x007a0101, 0x03070000,
+	0x0660282a, 0x050f80ff, 0x073fa009, 0x06000004,
+	0x02499008, 0x07810317, 0x07303000, 0x07008890,
+	0x02800319, 0x07303000, 0x04008980, 0x05007003,
+	0x074d0005, 0x06006013, 0x050f801e, 0x032fa03a,
+	0x0760142b, 0x050f80ff, 0x032fa021, 0x064b0002,
+	0x02499008, 0x06810325, 0x0644c002, 0x054b0400,
+	0x050040ff, 0x06698104, 0x0581833a, 0x06000013,
+	0x04001013, 0x04780102, 0x06000010, 0x06003013,
+	0x04004013, 0x06005013, 0x06006013, 0x04007013,
+	0x00644015, 0x07820336, 0x04448002, 0x02205008,
+	0x040f801f, 0x032fa042, 0x04008015, 0x03800371,
+	0x046c8004, 0x05818348, 0x01208018, 0x06780002,
+	0x07000003, 0x0581834b, 0x06003001, 0x06000013,
+	0x04001013, 0x04004013, 0x06005013, 0x040f801f,
+	0x022fa032, 0x03800371, 0x040fd02a, 0x06a00510,
+	0x03800014, 0x04488002, 0x07810350, 0x070ff003,
+	0x04500408, 0x050080ff, 0x06489002, 0x06810357,
+	0x0379ff00, 0x070000ff, 0x070ff000, 0x04500408,
+	0x050080ff, 0x07005003, 0x05004000, 0x06003001,
+	0x06000013, 0x04001013, 0x040f801f, 0x022fa032,
+	0x05601c2b, 0x050f80ff, 0x022fa031, 0x06600c1f,
+	0x050f80ff, 0x022fa032, 0x02680608, 0x07810371,
+	0x016408ff, 0x057dfeff, 0x07ffffff, 0x034000ff,
+	0x045a0407, 0x070000ff, 0x0760061e, 0x050f80ff,
+	0x032fa00a, 0x06600908, 0x0669f908, 0x027a0008,
+	0x06000020, 0x070aa0ff, 0x014a20ff, 0x037a00ff,
+	0x060000dc, 0x070000ff, 0x028003a7, 0x04007013,
+	0x06a003ba, 0x007a0101, 0x07030000, 0x07303000,
+	0x07008190, 0x06006013, 0x050f801e, 0x032fa03a,
+	0x073aa000, 0x06000002, 0x07300c00, 0x07000005,
+	0x028003a7, 0x04007013, 0x06a003ba, 0x007a0101,
+	0x07810000, 0x07303000, 0x07000090, 0x06006013,
+	0x06600c2a, 0x050f80ff, 0x053fa809, 0x07000003,
+	0x04780107, 0x07ffff00, 0x007c0107, 0x07000500,
+	0x0581839a, 0x07303000, 0x05000890, 0x074d0005,
+	0x0660282a, 0x050f80ff, 0x053fa809, 0x07000003,
+	0x0049d007, 0x068103a1, 0x02206001, 0x050f801e,
+	0x032fa03a, 0x073aa000, 0x06000002, 0x07300c00,
+	0x07000005, 0x013e4000, 0x07000030, 0x039803a9,
+	0x070ff0f6, 0x036830ff, 0x058183aa, 0x070f001e,
+	0x040f101f, 0x070f3000, 0x013e4000, 0x06000020,
+	0x040f801a, 0x0320000a, 0x022017d0, 0x032fa012,
+	0x008002bf, 0x03200000, 0x06006076, 0x028003bc,
+	0x03200011, 0x0600602a, 0x05a00441, 0x05600406,
+	0x050f80ff, 0x053fa809, 0x06000002, 0x07c00000,
+	0x0207602f, 0x04600876, 0x050f80ff, 0x022fa031,
+	0x03075000, 0x0007b004, 0x01018005, 0x06600076,
+	0x050020ff, 0x050f80ff, 0x012fa809, 0x0202f001,
+	0x008683d0, 0x0002e013, 0x040f8002, 0x053fa80a,
+	0x07000009, 0x06273001, 0x0448b075, 0x048183da,
+	0x04602076, 0x050f80ff, 0x053fa811, 0x0700003c,
+	0x0179fe78, 0x070000ff, 0x030190ff, 0x018683e2,
+	0x07a003f6, 0x00078019, 0x039203f5, 0x0180043a,
+	0x040fd076, 0x040fd019, 0x04600276, 0x050020ff,
+	0x050f80ff, 0x032fa009, 0x040f8002, 0x053fa80a,
+	0x07000009, 0x050fe000, 0x008683f2, 0x07601818,
+	0x050f80ff, 0x053fa80a, 0x07000009, 0x038003f3,
+	0x07a000de, 0x07273000, 0x02076013, 0x0280003d,
+	0x078b03f6, 0x03385000, 0x07030000, 0x05600818,
+	0x050f80ff, 0x032fa009, 0x054b0400, 0x0308a0ff,
+	0x0179fe00, 0x070000ff, 0x010880ff, 0x0448b075,
+	0x04810410, 0x0760147b, 0x050f80ff, 0x002fa819,
+	0x064b0001, 0x02080002, 0x01081003, 0x00082001,
+	0x02083001, 0x02079001, 0x0207a001, 0x00084013,
+	0x0207f013, 0x00800432, 0x06485075, 0x05810428,
+	0x02465075, 0x06601476, 0x050f80ff, 0x073fa021,
+	0x0600003e, 0x070ff07d, 0x0450047c, 0x050f80ff,
+	0x002fa819, 0x058b041b, 0x02080001, 0x00081002,
+	0x01082003, 0x03079003, 0x0208307a, 0x0340007e,
+	0x0642007f, 0x0581042d, 0x070ff07e, 0x05a001d2,
+	0x0392842d, 0x01800439, 0x058b0428, 0x06601476,
+	0x050f80ff, 0x073fa041, 0x0600003e, 0x06602476,
+	0x050f80ff, 0x073fa009, 0x06000007, 0x0008400e,
+	0x048b0432, 0x03385000, 0x03010000, 0x06219001,
+	0x040fe07f, 0x01860439, 0x018001bb, 0x07c00000,
+	0x00683e75, 0x0581043f, 0x0448d075, 0x05810465,
+	0x01800493, 0x05a004f0, 0x038003f5, 0x0297844c,
+	0x07602418, 0x050f80ff, 0x012fa809, 0x06780001,
+	0x070000ff, 0x075a0000, 0x070ff014, 0x0569feff,
+	0x054b08ff, 0x075a0000, 0x05600418, 0x050f80ff,
+	0x012fa809, 0x040fe007, 0x03868453, 0x01204000,
+	0x00800461, 0x00700101, 0x03010000, 0x06780001,
+	0x07ff0000, 0x076c00ff, 0x0681845b, 0x00700101,
+	0x03010000, 0x05600418, 0x050f80ff, 0x012fa80a,
+	0x06780001, 0x07ff0000, 0x050040ff, 0x0279ff01,
+	0x0700ffff, 0x05002014, 0x07c00000, 0x04007076,
+	0x0448b075, 0x0481047f, 0x03200011, 0x06006076,
+	0x06a003bc, 0x007a0101, 0x07060000, 0x07303000,
+	0x07008290, 0x07600018, 0x050f80ff, 0x053fa809,
+	0x07000003, 0x0448e007, 0x07818477, 0x06006013,
+	0x0180048e, 0x02400010, 0x05810477, 0x06006010,
+	0x04603276, 0x050f80ff, 0x073fa00a, 0x07000003,
+	0x0180048e, 0x04602a76, 0x050f80ff, 0x032fa009,
+	0x060ff07a, 0x05500400, 0x070000ff, 0x04602a76,
+	0x050f80ff, 0x032fa00a, 0x07a003b7, 0x007a0101,
+	0x03010000, 0x06303008, 0x05008000, 0x0600600e,
+	0x050f8074, 0x032fa03a, 0x053079a0, 0x0700000c,
+	0x008004d3, 0x00683e75, 0x076c0aff, 0x058104b2,
+	0x04007013, 0x03200011, 0x06006076, 0x06a003bc,
+	0x007a0101, 0x03070000, 0x06602876, 0x050f80ff,
+	0x053fa809, 0x06000001, 0x03499003, 0x048104a7,
+	0x07303000, 0x07008890, 0x053079a0, 0x0700000c,
+	0x008004ab, 0x07303000, 0x04008980, 0x04307920,
+	0x0700000c, 0x074d0005, 0x06006013, 0x050f8074,
+	0x032fa03a, 0x04307920, 0x0700000c, 0x008004d3,
+	0x04602a76, 0x050f80ff, 0x032fa009, 0x060ff07a,
+	0x05500400, 0x070000ff, 0x04602a76, 0x050f80ff,
+	0x032fa00a, 0x04007076, 0x07a003b7, 0x007a0101,
+	0x03010000, 0x06303008, 0x07008800, 0x074d0005,
+	0x06600a76, 0x050f80ff, 0x073fa009, 0x07000003,
+	0x054b0406, 0x045a0404, 0x050040ff, 0x0600600e,
+	0x050f8074, 0x032fa03a, 0x0648c075, 0x058104d1,
+	0x06307d20, 0x0700000c, 0x008004d3, 0x04307920,
+	0x0700000c, 0x013e4000, 0x07000030, 0x009804d5,
+	0x070ff0f6, 0x074850ff, 0x068184d6, 0x050f2074,
+	0x060a0007, 0x040070fb, 0x046a7007, 0x050f40ff,
+	0x013e4000, 0x06000020, 0x0678007a, 0x07fff000,
+	0x068184e6, 0x0320000a, 0x022017d0, 0x008004e9,
+	0x0320000a, 0x06301b58, 0x06000001, 0x050f8072,
+	0x032fa012, 0x038003f5, 0x01208060, 0x0600902a,
+	0x04002020, 0x018004fc, 0x040080fb, 0x066ae108,
+	0x06009076, 0x04002075, 0x018004fc, 0x03201100,
+	0x078484fa, 0x06420001, 0x078184f6, 0x02800513,
+	0x020e0008, 0x07c00000, 0x050fd009, 0x040fd008,
+	0x03201100, 0x05848503, 0x06420001, 0x078184ff,
+	0x02800513, 0x007a0102, 0x04000101, 0x05600809,
+	0x050f80ff, 0x073fa00a, 0x06000001, 0x020e0008,
+	0x0684050d, 0x030e0009, 0x07c00000, 0x01011009,
+	0x052e4300, 0x07c00000, 0x052e400f, 0x01208090,
+	0x018004f5, 0x070fc0ff, 0x040f8013, 0x032fa009,
+	0x02800516, 0x15416ea9, 0xffef0b01
+};
+
+#ifdef UNIQUE_FW_NAME
+uint32_t fw2400_length02 = 0x000014ff ;
+#else
+uint32_t risc_code_length02 = 0x000014ff ;
+#endif
+
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 48e460eef05a..2efca52dff50 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -232,7 +232,7 @@ static ssize_t
 qla2x00_isp_name_show(struct class_device *cdev, char *buf)
 {
 	scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
-	return snprintf(buf, PAGE_SIZE, "%s\n", ha->brd_info->isp_name);
+	return snprintf(buf, PAGE_SIZE, "ISP%04X\n", ha->pdev->device);
 }
 
 static ssize_t
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 7b3efd531297..79d8a914f9d0 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -22,6 +22,7 @@
 #include <linux/completion.h>
 #include <linux/interrupt.h>
 #include <linux/workqueue.h>
+#include <linux/firmware.h>
 #include <asm/semaphore.h>
 
 #include <scsi/scsi.h>
@@ -29,6 +30,7 @@
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_cmnd.h>
 
+#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE)
 #if defined(CONFIG_SCSI_QLA21XX) || defined(CONFIG_SCSI_QLA21XX_MODULE)
 #define IS_QLA2100(ha)	((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2100)
 #else
@@ -79,9 +81,23 @@
 #define IS_QLA2522(ha)	0
 #endif
 
+#else	/* !defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) */
+
+#define IS_QLA2100(ha)	((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2100)
+#define IS_QLA2200(ha)	((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2200)
+#define IS_QLA2300(ha)	((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2300)
+#define IS_QLA2312(ha)	((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2312)
+#define IS_QLA2322(ha)	((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2322)
+#define IS_QLA6312(ha)	((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP6312)
+#define IS_QLA6322(ha)	((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP6322)
+#define IS_QLA2422(ha)	((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2422)
+#define IS_QLA2432(ha)	((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432)
+#define IS_QLA2512(ha)	((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2512)
+#define IS_QLA2522(ha)	((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2522)
+#endif
+
 #define IS_QLA23XX(ha)	(IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA2322(ha) || \
     			 IS_QLA6312(ha) || IS_QLA6322(ha))
-
 #define IS_QLA24XX(ha)	(IS_QLA2422(ha) || IS_QLA2432(ha))
 #define IS_QLA25XX(ha)	(IS_QLA2512(ha) || IS_QLA2522(ha))
 
@@ -2124,6 +2140,12 @@ struct qla_board_info {
 	struct scsi_host_template *sht;
 };
 
+struct fw_blob {
+	char *name;
+	uint32_t segs[4];
+	const struct firmware *fw;
+};
+
 /* Return data from MBC_GET_ID_LIST call. */
 struct gid_list_info {
 	uint8_t	al_pa;
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index fedcb0d3fc72..bec81adcf4fd 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -33,8 +33,8 @@ extern int qla24xx_nvram_config(struct scsi_qla_host *);
 extern void qla2x00_update_fw_options(struct scsi_qla_host *);
 extern void qla24xx_update_fw_options(scsi_qla_host_t *);
 extern int qla2x00_load_risc(struct scsi_qla_host *, uint32_t *);
+extern int qla24xx_load_risc(scsi_qla_host_t *, uint32_t *);
 extern int qla24xx_load_risc_flash(scsi_qla_host_t *, uint32_t *);
-extern int qla24xx_load_risc_hotplug(scsi_qla_host_t *, uint32_t *);
 
 extern fc_port_t *qla2x00_alloc_fcport(scsi_qla_host_t *, gfp_t);
 
@@ -76,6 +76,8 @@ extern void qla2x00_blink_led(scsi_qla_host_t *);
 
 extern int qla2x00_down_timeout(struct semaphore *, unsigned long);
 
+extern struct fw_blob *qla2x00_request_firmware(scsi_qla_host_t *);
+
 /*
  * Global Function Prototypes in qla_iocb.c source file.
  */
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index c46d2469b85f..7d973bd9022b 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -8,7 +8,6 @@
 
 #include <linux/delay.h>
 #include <linux/vmalloc.h>
-#include <linux/firmware.h>
 #include <scsi/scsi_transport_fc.h>
 
 #include "qla_devtbl.h"
@@ -3484,17 +3483,16 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
 	return (rval);
 }
 
+#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE)
+
 int
 qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
 {
-	int		rval;
-	uint16_t	cnt;
-	uint16_t	*risc_code;
-	unsigned long	risc_address;
-	unsigned long	risc_code_size;
-	int		num;
-	int		i;
-	uint16_t	*req_ring;
+	int	rval, num, i;
+	uint32_t cnt;
+	uint16_t *risc_code;
+	uint32_t risc_addr, risc_size;
+	uint16_t *req_ring;
 	struct qla_fw_info *fw_iter;
 
 	rval = QLA_SUCCESS;
@@ -3504,37 +3502,29 @@ qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
 	*srisc_addr = *ha->brd_info->fw_info->fwstart;
 	while (fw_iter->addressing != FW_INFO_ADDR_NOMORE) {
 		risc_code = fw_iter->fwcode;
-		risc_code_size = *fw_iter->fwlen;
-
-		if (fw_iter->addressing == FW_INFO_ADDR_NORMAL) {
-			risc_address = *fw_iter->fwstart;
-		} else {
-			/* Extended address */
-			risc_address = *fw_iter->lfwstart;
-		}
+		risc_size = *fw_iter->fwlen;
+		if (fw_iter->addressing == FW_INFO_ADDR_NORMAL)
+			risc_addr = *fw_iter->fwstart;
+		else
+			risc_addr = *fw_iter->lfwstart;
 
 		num = 0;
 		rval = 0;
-		while (risc_code_size > 0 && !rval) {
+		while (risc_size > 0 && !rval) {
 			cnt = (uint16_t)(ha->fw_transfer_size >> 1);
-			if (cnt > risc_code_size)
-				cnt = risc_code_size;
+			if (cnt > risc_size)
+				cnt = risc_size;
 
 			DEBUG7(printk("scsi(%ld): Loading risc segment@ "
 			    "addr %p, number of bytes 0x%x, offset 0x%lx.\n",
-			    ha->host_no, risc_code, cnt, risc_address));
+			    ha->host_no, risc_code, cnt, risc_addr));
 
 			req_ring = (uint16_t *)ha->request_ring;
 			for (i = 0; i < cnt; i++)
 				req_ring[i] = cpu_to_le16(risc_code[i]);
 
-			if (fw_iter->addressing == FW_INFO_ADDR_NORMAL) {
-				rval = qla2x00_load_ram(ha, ha->request_dma,
-				    risc_address, cnt);
-			} else {
-				rval = qla2x00_load_ram_ext(ha,
-				    ha->request_dma, risc_address, cnt);
-			}
+			rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr,
+			    cnt);
 			if (rval) {
 				DEBUG(printk("scsi(%ld): [ERROR] Failed to "
 				    "load segment %d of firmware\n",
@@ -3548,16 +3538,76 @@ qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
 			}
 
 			risc_code += cnt;
-			risc_address += cnt;
-			risc_code_size -= cnt;
+			risc_addr += cnt;
+			risc_size -= cnt;
 			num++;
 		}
 
 		/* Next firmware sequence */
 		fw_iter++;
 	}
+	return rval;
+}
 
-	return (rval);
+int
+qla24xx_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
+{
+	int	rval, num, i;
+	uint32_t cnt;
+	uint32_t *risc_code;
+	uint32_t risc_addr, risc_size;
+	uint32_t *req_ring;
+	struct qla_fw_info *fw_iter;
+
+	rval = QLA_SUCCESS;
+
+	/* Load firmware sequences */
+	fw_iter = ha->brd_info->fw_info;
+	*srisc_addr = *((uint32_t *)fw_iter->lfwstart);
+	while (fw_iter->addressing != FW_INFO_ADDR_NOMORE) {
+		risc_code = (uint32_t *)fw_iter->fwcode;
+		risc_size = *((uint32_t *)fw_iter->fwlen);
+		risc_addr = *((uint32_t *)fw_iter->lfwstart);
+
+		num = 0;
+		rval = 0;
+		while (risc_size > 0 && !rval) {
+			cnt = (uint32_t)(ha->fw_transfer_size >> 2);
+			if (cnt > risc_size)
+				cnt = risc_size;
+
+			DEBUG7(printk("scsi(%ld): Loading risc segment@ "
+			    "addr %p, number of bytes 0x%x, offset 0x%lx.\n",
+			    ha->host_no, risc_code, cnt, risc_addr));
+
+			req_ring = (uint32_t *)ha->request_ring;
+			for (i = 0; i < cnt; i++)
+				req_ring[i] = cpu_to_le32(risc_code[i]);
+
+			rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr,
+			    cnt);
+			if (rval) {
+				DEBUG(printk("scsi(%ld): [ERROR] Failed to "
+				    "load segment %d of firmware\n",
+				    ha->host_no, num));
+				qla_printk(KERN_WARNING, ha,
+				    "[ERROR] Failed to load segment %d of "
+				    "firmware\n", num);
+
+				qla2x00_dump_regs(ha);
+				break;
+			}
+
+			risc_code += cnt;
+			risc_addr += cnt;
+			risc_size -= cnt;
+			num++;
+		}
+
+		/* Next firmware sequence */
+		fw_iter++;
+	}
+	return rval;
 }
 
 int
@@ -3642,8 +3692,108 @@ qla24xx_load_risc_flash(scsi_qla_host_t *ha, uint32_t *srisc_addr)
 	return rval;
 }
 
+#else	/* !defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) */
+
 int
-qla24xx_load_risc_hotplug(scsi_qla_host_t *ha, uint32_t *srisc_addr)
+qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
+{
+	int	rval;
+	int	i, fragment;
+	uint16_t *wcode, *fwcode;
+	uint32_t risc_addr, risc_size, fwclen, wlen, *seg;
+	struct fw_blob *blob;
+
+	/* Load firmware blob. */
+	blob = qla2x00_request_firmware(ha);
+	if (!blob) {
+		qla_printk(KERN_ERR, ha, "Firmware image unavailable.\n");
+		return QLA_FUNCTION_FAILED;
+	}
+
+	rval = QLA_SUCCESS;
+
+	wcode = (uint16_t *)ha->request_ring;
+	*srisc_addr = 0;
+	fwcode = (uint16_t *)blob->fw->data;
+	fwclen = 0;
+
+	/* Validate firmware image by checking version. */
+	if (blob->fw->size < 8 * sizeof(uint16_t)) {
+		qla_printk(KERN_WARNING, ha,
+		    "Unable to verify integrity of firmware image (%Zd)!\n",
+		    blob->fw->size);
+		goto fail_fw_integrity;
+	}
+	for (i = 0; i < 4; i++)
+		wcode[i] = be16_to_cpu(fwcode[i + 4]);
+	if ((wcode[0] == 0xffff && wcode[1] == 0xffff && wcode[2] == 0xffff &&
+	    wcode[3] == 0xffff) || (wcode[0] == 0 && wcode[1] == 0 &&
+		wcode[2] == 0 && wcode[3] == 0)) {
+		qla_printk(KERN_WARNING, ha,
+		    "Unable to verify integrity of firmware image!\n");
+		qla_printk(KERN_WARNING, ha,
+		    "Firmware data: %04x %04x %04x %04x!\n", wcode[0],
+		    wcode[1], wcode[2], wcode[3]);
+		goto fail_fw_integrity;
+	}
+
+	seg = blob->segs;
+	while (*seg && rval == QLA_SUCCESS) {
+		risc_addr = *seg;
+		*srisc_addr = *srisc_addr == 0 ? *seg : *srisc_addr;
+		risc_size = be16_to_cpu(fwcode[3]);
+
+		/* Validate firmware image size. */
+		fwclen += risc_size * sizeof(uint16_t);
+		if (blob->fw->size < fwclen) {
+			qla_printk(KERN_WARNING, ha,
+			    "Unable to verify integrity of firmware image "
+			    "(%Zd)!\n", blob->fw->size);
+			goto fail_fw_integrity;
+		}
+
+		fragment = 0;
+		while (risc_size > 0 && rval == QLA_SUCCESS) {
+			wlen = (uint16_t)(ha->fw_transfer_size >> 1);
+			if (wlen > risc_size)
+				wlen = risc_size;
+
+			DEBUG7(printk("scsi(%ld): Loading risc segment@ risc "
+			    "addr %x, number of words 0x%x.\n", ha->host_no,
+			    risc_addr, wlen));
+
+			for (i = 0; i < wlen; i++)
+				wcode[i] = swab16(fwcode[i]);
+
+			rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr,
+			    wlen);
+			if (rval) {
+				DEBUG(printk("scsi(%ld):[ERROR] Failed to load "
+				    "segment %d of firmware\n", ha->host_no,
+				    fragment));
+				qla_printk(KERN_WARNING, ha,
+				    "[ERROR] Failed to load segment %d of "
+				    "firmware\n", fragment);
+				break;
+			}
+
+			fwcode += wlen;
+			risc_addr += wlen;
+			risc_size -= wlen;
+			fragment++;
+		}
+
+		/* Next segment. */
+		seg++;
+	}
+	return rval;
+
+fail_fw_integrity:
+	return QLA_FUNCTION_FAILED;
+}
+
+int
+qla24xx_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
 {
 	int	rval;
 	int	segments, fragment;
@@ -3651,14 +3801,13 @@ qla24xx_load_risc_hotplug(scsi_qla_host_t *ha, uint32_t *srisc_addr)
 	uint32_t risc_addr;
 	uint32_t risc_size;
 	uint32_t i;
-	const struct firmware *fw_entry;
+	struct fw_blob *blob;
 	uint32_t *fwcode, fwclen;
 
-	if (request_firmware(&fw_entry, ha->brd_info->fw_fname,
-	    &ha->pdev->dev)) {
-		qla_printk(KERN_ERR, ha,
-		    "Firmware image file not available: '%s'\n",
-		    ha->brd_info->fw_fname);
+	/* Load firmware blob. */
+	blob = qla2x00_request_firmware(ha);
+	if (!blob) {
+		qla_printk(KERN_ERR, ha, "Firmware image unavailable.\n");
 		return QLA_FUNCTION_FAILED;
 	}
 
@@ -3667,14 +3816,14 @@ qla24xx_load_risc_hotplug(scsi_qla_host_t *ha, uint32_t *srisc_addr)
 	segments = FA_RISC_CODE_SEGMENTS;
 	dcode = (uint32_t *)ha->request_ring;
 	*srisc_addr = 0;
-	fwcode = (uint32_t *)fw_entry->data;
+	fwcode = (uint32_t *)blob->fw->data;
 	fwclen = 0;
 
 	/* Validate firmware image by checking version. */
-	if (fw_entry->size < 8 * sizeof(uint32_t)) {
+	if (blob->fw->size < 8 * sizeof(uint32_t)) {
 		qla_printk(KERN_WARNING, ha,
-		    "Unable to verify integrity of flash firmware image "
-		    "(%Zd)!\n", fw_entry->size);
+		    "Unable to verify integrity of firmware image (%Zd)!\n",
+		    blob->fw->size);
 		goto fail_fw_integrity;
 	}
 	for (i = 0; i < 4; i++)
@@ -3684,7 +3833,7 @@ qla24xx_load_risc_hotplug(scsi_qla_host_t *ha, uint32_t *srisc_addr)
 	    (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 &&
 		dcode[3] == 0)) {
 		qla_printk(KERN_WARNING, ha,
-		    "Unable to verify integrity of flash firmware image!\n");
+		    "Unable to verify integrity of firmware image!\n");
 		qla_printk(KERN_WARNING, ha,
 		    "Firmware data: %08x %08x %08x %08x!\n", dcode[0],
 		    dcode[1], dcode[2], dcode[3]);
@@ -3698,10 +3847,11 @@ qla24xx_load_risc_hotplug(scsi_qla_host_t *ha, uint32_t *srisc_addr)
 
 		/* Validate firmware image size. */
 		fwclen += risc_size * sizeof(uint32_t);
-		if (fw_entry->size < fwclen) {
+		if (blob->fw->size < fwclen) {
 			qla_printk(KERN_WARNING, ha,
-			    "Unable to verify integrity of flash firmware "
-			    "image (%Zd)!\n", fw_entry->size);
+			    "Unable to verify integrity of firmware image "
+			    "(%Zd)!\n", blob->fw->size);
+
 			goto fail_fw_integrity;
 		}
 
@@ -3739,13 +3889,9 @@ qla24xx_load_risc_hotplug(scsi_qla_host_t *ha, uint32_t *srisc_addr)
 		/* Next segment. */
 		segments--;
 	}
-
-	release_firmware(fw_entry);
 	return rval;
 
 fail_fw_integrity:
-
-	release_firmware(fw_entry);
 	return QLA_FUNCTION_FAILED;
-
 }
+#endif
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index c58c9d97b041..24304300d7b5 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -54,10 +54,12 @@ module_param(ql2xloginretrycount, int, S_IRUGO|S_IRUSR);
 MODULE_PARM_DESC(ql2xloginretrycount,
 		"Specify an alternate value for the NVRAM login retry count.");
 
-int ql2xfwloadbin=1;
-module_param(ql2xfwloadbin, int, S_IRUGO|S_IRUSR);
-MODULE_PARM_DESC(ql2xfwloadbin,
-		"Load ISP2xxx firmware image via hotplug.");
+#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE)
+int ql2xfwloadflash;
+module_param(ql2xfwloadflash, int, S_IRUGO|S_IRUSR);
+MODULE_PARM_DESC(ql2xfwloadflash,
+		"Load ISP24xx firmware image from FLASH (onboard memory).");
+#endif
 
 static void qla2x00_free_device(scsi_qla_host_t *);
 
@@ -1261,12 +1263,16 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
 	char pci_info[20];
 	char fw_str[30];
 	fc_port_t *fcport;
+	struct scsi_host_template *sht;
 
 	if (pci_enable_device(pdev))
 		goto probe_out;
 
-	host = scsi_host_alloc(brd_info->sht ? brd_info->sht:
-	    &qla2x00_driver_template, sizeof(scsi_qla_host_t));
+	sht = &qla2x00_driver_template;
+	if (pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2422 ||
+	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432)
+		sht = &qla24xx_driver_template;
+	host = scsi_host_alloc(sht, sizeof(scsi_qla_host_t));
 	if (host == NULL) {
 		printk(KERN_WARNING
 		    "qla2xxx: Couldn't allocate host from scsi layer!\n");
@@ -1291,8 +1297,8 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
 		goto probe_failed;
 
 	qla_printk(KERN_INFO, ha,
-	    "Found an %s, irq %d, iobase 0x%p\n", ha->brd_info->isp_name,
-	    pdev->irq, ha->iobase);
+	    "Found an ISP%04X, irq %d, iobase 0x%p\n", pdev->device, pdev->irq,
+	    ha->iobase);
 
 	spin_lock_init(&ha->hardware_lock);
 
@@ -1368,9 +1374,11 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
 		ha->isp_ops.reset_adapter = qla24xx_reset_adapter;
 		ha->isp_ops.nvram_config = qla24xx_nvram_config;
 		ha->isp_ops.update_fw_options = qla24xx_update_fw_options;
-		ha->isp_ops.load_risc = qla24xx_load_risc_flash;
-		if (ql2xfwloadbin)
-			ha->isp_ops.load_risc = qla24xx_load_risc_hotplug;
+		ha->isp_ops.load_risc = qla24xx_load_risc;
+#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE)
+		if (ql2xfwloadflash)
+			ha->isp_ops.load_risc = qla24xx_load_risc_flash;
+#endif
 		ha->isp_ops.pci_info_str = qla24xx_pci_info_str;
 		ha->isp_ops.fw_version_str = qla24xx_fw_version_str;
 		ha->isp_ops.intr_handler = qla24xx_intr_handler;
@@ -1531,11 +1539,12 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
 	qla_printk(KERN_INFO, ha, "\n"
 	    " QLogic Fibre Channel HBA Driver: %s\n"
 	    "  QLogic %s - %s\n"
-	    "  %s: %s @ %s hdma%c, host#=%ld, fw=%s\n", qla2x00_version_str,
-	    ha->model_number, ha->model_desc ? ha->model_desc: "",
-	    ha->brd_info->isp_name, ha->isp_ops.pci_info_str(ha, pci_info),
-	    pci_name(pdev), ha->flags.enable_64bit_addressing ? '+': '-',
-	    ha->host_no, ha->isp_ops.fw_version_str(ha, fw_str));
+	    "  ISP%04X: %s @ %s hdma%c, host#=%ld, fw=%s\n",
+	    qla2x00_version_str, ha->model_number,
+	    ha->model_desc ? ha->model_desc: "", pdev->device,
+	    ha->isp_ops.pci_info_str(ha, pci_info), pci_name(pdev),
+	    ha->flags.enable_64bit_addressing ? '+': '-', ha->host_no,
+	    ha->isp_ops.fw_version_str(ha, fw_str));
 
 	/* Go with fc_rport registration. */
 	list_for_each_entry(fcport, &ha->fcports, list)
@@ -2483,45 +2492,115 @@ qla2x00_down_timeout(struct semaphore *sema, unsigned long timeout)
 	return -ETIMEDOUT;
 }
 
-static struct qla_board_info qla_board_tbl[] = {
-	{
-		.drv_name	= "qla2400",
-		.isp_name	= "ISP2422",
-		.fw_fname	= "ql2400_fw.bin",
-		.sht		= &qla24xx_driver_template,
-	},
-	{
-		.drv_name	= "qla2400",
-		.isp_name	= "ISP2432",
-		.fw_fname	= "ql2400_fw.bin",
-		.sht		= &qla24xx_driver_template,
-	},
+#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE)
+
+#define qla2x00_release_firmware()	do { } while (0)
+#define qla2x00_pci_module_init()	(0)
+#define qla2x00_pci_module_exit()	do { } while (0)
+
+#else	/* !defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) */
+
+/* Firmware interface routines. */
+
+#define FW_BLOBS	6
+#define FW_ISP21XX	0
+#define FW_ISP22XX	1
+#define FW_ISP2300	2
+#define FW_ISP2322	3
+#define FW_ISP63XX	4
+#define FW_ISP24XX	5
+
+static DECLARE_MUTEX(qla_fw_lock);
+
+static struct fw_blob qla_fw_blobs[FW_BLOBS] = {
+	{ .name = "ql2100_fw.bin", .segs = { 0x1000, 0 }, },
+	{ .name = "ql2200_fw.bin", .segs = { 0x1000, 0 }, },
+	{ .name = "ql2300_fw.bin", .segs = { 0x800, 0 }, },
+	{ .name = "ql2322_fw.bin", .segs = { 0x800, 0x1c000, 0x1e000, 0 }, },
+	{ .name = "ql6312_fw.bin", .segs = { 0x800, 0 }, },
+	{ .name = "ql2400_fw.bin", },
+};
+
+struct fw_blob *
+qla2x00_request_firmware(scsi_qla_host_t *ha)
+{
+	struct fw_blob *blob;
+
+	blob = NULL;
+	if (IS_QLA2100(ha)) {
+		blob = &qla_fw_blobs[FW_ISP21XX];
+	} else if (IS_QLA2200(ha)) {
+		blob = &qla_fw_blobs[FW_ISP22XX];
+	} else if (IS_QLA2300(ha) || IS_QLA2312(ha)) {
+		blob = &qla_fw_blobs[FW_ISP2300];
+	} else if (IS_QLA2322(ha)) {
+		blob = &qla_fw_blobs[FW_ISP2322];
+	} else if (IS_QLA6312(ha) || IS_QLA6322(ha)) {
+		blob = &qla_fw_blobs[FW_ISP63XX];
+	} else if (IS_QLA24XX(ha)) {
+		blob = &qla_fw_blobs[FW_ISP24XX];
+	}
+
+	down(&qla_fw_lock);
+	if (blob->fw)
+		goto out;
+
+	if (request_firmware(&blob->fw, blob->name, &ha->pdev->dev)) {
+		DEBUG2(printk("scsi(%ld): Failed to load firmware image "
+		    "(%s).\n", ha->host_no, blob->name));
+		blob->fw = NULL;
+		blob = NULL;
+		goto out;
+	}
+
+out:
+	up(&qla_fw_lock);
+	return blob;
+}
+
+static void
+qla2x00_release_firmware(void)
+{
+	int idx;
+
+	down(&qla_fw_lock);
+	for (idx = 0; idx < FW_BLOBS; idx++)
+		if (qla_fw_blobs[idx].fw)
+			release_firmware(qla_fw_blobs[idx].fw);
+	up(&qla_fw_lock);
+}
+
+static struct qla_board_info qla_board_tbl = {
+	.drv_name       = "qla2xxx",
 };
 
 static struct pci_device_id qla2xxx_pci_tbl[] = {
-	{
-		.vendor		= PCI_VENDOR_ID_QLOGIC,
-		.device		= PCI_DEVICE_ID_QLOGIC_ISP2422,
-		.subvendor	= PCI_ANY_ID,
-		.subdevice	= PCI_ANY_ID,
-		.driver_data	= (unsigned long)&qla_board_tbl[0],
-	},
-	{
-		.vendor		= PCI_VENDOR_ID_QLOGIC,
-		.device		= PCI_DEVICE_ID_QLOGIC_ISP2432,
-		.subvendor	= PCI_ANY_ID,
-		.subdevice	= PCI_ANY_ID,
-		.driver_data	= (unsigned long)&qla_board_tbl[1],
-	},
-	{0, 0},
+	{ PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2100,
+		PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2200,
+		PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2300,
+		PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2312,
+		PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2322,
+		PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP6312,
+		PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP6322,
+		PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2422,
+		PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2432,
+		PCI_ANY_ID, PCI_ANY_ID, },
+	{ 0 },
 };
 MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl);
 
 static int __devinit
 qla2xxx_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 {
-	return qla2x00_probe_one(pdev,
-	    (struct qla_board_info *)id->driver_data);
+	return qla2x00_probe_one(pdev, &qla_board_tbl);
 }
 
 static void __devexit
@@ -2532,11 +2611,28 @@ qla2xxx_remove_one(struct pci_dev *pdev)
 
 static struct pci_driver qla2xxx_pci_driver = {
 	.name		= "qla2xxx",
+	.driver		= {
+		.owner		= THIS_MODULE,
+	},
 	.id_table	= qla2xxx_pci_tbl,
 	.probe		= qla2xxx_probe_one,
 	.remove		= __devexit_p(qla2xxx_remove_one),
 };
 
+static inline int
+qla2x00_pci_module_init(void)
+{
+	return pci_module_init(&qla2xxx_pci_driver);
+}
+
+static inline void
+qla2x00_pci_module_exit(void)
+{
+	pci_unregister_driver(&qla2xxx_pci_driver);
+}
+
+#endif
+
 /**
  * qla2x00_module_init - Module initialization.
  **/
@@ -2556,6 +2652,9 @@ qla2x00_module_init(void)
 
 	/* Derive version string. */
 	strcpy(qla2x00_version_str, QLA2XXX_VERSION);
+#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE)
+	strcat(qla2x00_version_str, "-fw");
+#endif
 #if DEBUG_QLA2100
 	strcat(qla2x00_version_str, "-debug");
 #endif
@@ -2565,7 +2664,7 @@ qla2x00_module_init(void)
 		return -ENODEV;
 
 	printk(KERN_INFO "QLogic Fibre Channel HBA Driver\n");
-	ret = pci_module_init(&qla2xxx_pci_driver);
+	ret = qla2x00_pci_module_init();
 	if (ret) {
 		kmem_cache_destroy(srb_cachep);
 		fc_release_transport(qla2xxx_transport_template);
@@ -2579,7 +2678,8 @@ qla2x00_module_init(void)
 static void __exit
 qla2x00_module_exit(void)
 {
-	pci_unregister_driver(&qla2xxx_pci_driver);
+	qla2x00_pci_module_exit();
+	qla2x00_release_firmware();
 	kmem_cache_destroy(srb_cachep);
 	fc_release_transport(qla2xxx_transport_template);
 }
diff --git a/drivers/scsi/raid_class.c b/drivers/scsi/raid_class.c
index 5b1c12041a4f..5ec5f44602ac 100644
--- a/drivers/scsi/raid_class.c
+++ b/drivers/scsi/raid_class.c
@@ -115,7 +115,7 @@ static DECLARE_TRANSPORT_CLASS(raid_class,
 			       raid_remove,
 			       NULL);
 
-static struct {
+static const struct {
 	enum raid_state	value;
 	char		*name;
 } raid_states[] = {
diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c
index 9321cdf45680..cd54244058b5 100644
--- a/drivers/scsi/sata_mv.c
+++ b/drivers/scsi/sata_mv.c
@@ -374,7 +374,6 @@ static struct scsi_host_template mv_sht = {
 	.dma_boundary		= MV_DMA_BOUNDARY,
 	.slave_configure	= ata_scsi_slave_config,
 	.bios_param		= ata_std_bios_param,
-	.ordered_flush		= 1,
 };
 
 static const struct ata_port_operations mv5_ops = {
@@ -431,7 +430,7 @@ static const struct ata_port_operations mv6_ops = {
 	.host_stop		= mv_host_stop,
 };
 
-static struct ata_port_info mv_port_info[] = {
+static const struct ata_port_info mv_port_info[] = {
 	{  /* chip_504x */
 		.sht		= &mv_sht,
 		.host_flags	= MV_COMMON_FLAGS,
@@ -1243,8 +1242,10 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
 				VPRINTK("port %u IRQ found for qc, "
 					"ata_status 0x%x\n", port,ata_status);
 				/* mark qc status appropriately */
-				if (!(qc->tf.ctl & ATA_NIEN))
-					ata_qc_complete(qc, err_mask);
+				if (!(qc->tf.ctl & ATA_NIEN)) {
+					qc->err_mask |= err_mask;
+					ata_qc_complete(qc);
+				}
 			}
 		}
 	}
@@ -1865,7 +1866,8 @@ static void mv_eng_timeout(struct ata_port *ap)
 	 	 */
 		spin_lock_irqsave(&ap->host_set->lock, flags);
 		qc->scsidone = scsi_finish_command;
-		ata_qc_complete(qc, AC_ERR_OTHER);
+		qc->err_mask |= AC_ERR_OTHER;
+		ata_qc_complete(qc);
 		spin_unlock_irqrestore(&ap->host_set->lock, flags);
 	}
 }
diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c
index 4954896dfdb9..c0cf52cb975a 100644
--- a/drivers/scsi/sata_nv.c
+++ b/drivers/scsi/sata_nv.c
@@ -235,7 +235,6 @@ static struct scsi_host_template nv_sht = {
 	.dma_boundary		= ATA_DMA_BOUNDARY,
 	.slave_configure	= ata_scsi_slave_config,
 	.bios_param		= ata_std_bios_param,
-	.ordered_flush		= 1,
 };
 
 static const struct ata_port_operations nv_ops = {
diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c
index 2691625f9bce..3d1ea09a06a1 100644
--- a/drivers/scsi/sata_promise.c
+++ b/drivers/scsi/sata_promise.c
@@ -114,7 +114,6 @@ static struct scsi_host_template pdc_ata_sht = {
 	.dma_boundary		= ATA_DMA_BOUNDARY,
 	.slave_configure	= ata_scsi_slave_config,
 	.bios_param		= ata_std_bios_param,
-	.ordered_flush		= 1,
 };
 
 static const struct ata_port_operations pdc_sata_ops = {
@@ -161,7 +160,7 @@ static const struct ata_port_operations pdc_pata_ops = {
 	.host_stop		= ata_pci_host_stop,
 };
 
-static struct ata_port_info pdc_port_info[] = {
+static const struct ata_port_info pdc_port_info[] = {
 	/* board_2037x */
 	{
 		.sht		= &pdc_ata_sht,
@@ -401,7 +400,8 @@ static void pdc_eng_timeout(struct ata_port *ap)
 	case ATA_PROT_NODATA:
 		printk(KERN_ERR "ata%u: command timeout\n", ap->id);
 		drv_stat = ata_wait_idle(ap);
-		ata_qc_complete(qc, __ac_err_mask(drv_stat));
+		qc->err_mask |= __ac_err_mask(drv_stat);
+		ata_qc_complete(qc);
 		break;
 
 	default:
@@ -410,7 +410,8 @@ static void pdc_eng_timeout(struct ata_port *ap)
 		printk(KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n",
 		       ap->id, qc->tf.command, drv_stat);
 
-		ata_qc_complete(qc, ac_err_mask(drv_stat));
+		qc->err_mask |= ac_err_mask(drv_stat);
+		ata_qc_complete(qc);
 		break;
 	}
 
@@ -422,21 +423,21 @@ out:
 static inline unsigned int pdc_host_intr( struct ata_port *ap,
                                           struct ata_queued_cmd *qc)
 {
-	unsigned int handled = 0, err_mask = 0;
+	unsigned int handled = 0;
 	u32 tmp;
 	void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr + PDC_GLOBAL_CTL;
 
 	tmp = readl(mmio);
 	if (tmp & PDC_ERR_MASK) {
-		err_mask = AC_ERR_DEV;
+		qc->err_mask |= AC_ERR_DEV;
 		pdc_reset_port(ap);
 	}
 
 	switch (qc->tf.protocol) {
 	case ATA_PROT_DMA:
 	case ATA_PROT_NODATA:
-		err_mask |= ac_err_mask(ata_wait_idle(ap));
-		ata_qc_complete(qc, err_mask);
+		qc->err_mask |= ac_err_mask(ata_wait_idle(ap));
+		ata_qc_complete(qc);
 		handled = 1;
 		break;
 
@@ -703,7 +704,7 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
 		probe_ent->port[3].scr_addr = base + 0x700;
 		break;
 	case board_2037x:
-       		probe_ent->n_ports = 2;
+		probe_ent->n_ports = 2;
 		break;
 	case board_20619:
 		probe_ent->n_ports = 4;
@@ -713,7 +714,7 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
 
 		probe_ent->port[2].scr_addr = base + 0x600;
 		probe_ent->port[3].scr_addr = base + 0x700;
-                break;
+		break;
 	default:
 		BUG();
 		break;
diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c
index a8987f5ff5cc..de05e2883f9c 100644
--- a/drivers/scsi/sata_qstor.c
+++ b/drivers/scsi/sata_qstor.c
@@ -170,7 +170,7 @@ static const struct ata_port_operations qs_ata_ops = {
 	.bmdma_status		= qs_bmdma_status,
 };
 
-static struct ata_port_info qs_port_info[] = {
+static const struct ata_port_info qs_port_info[] = {
 	/* board_2068_idx */
 	{
 		.sht		= &qs_ata_sht,
@@ -409,8 +409,8 @@ static inline unsigned int qs_intr_pkt(struct ata_host_set *host_set)
 					case 3: /* device error */
 						pp->state = qs_state_idle;
 						qs_enter_reg_mode(qc->ap);
-						ata_qc_complete(qc,
-							ac_err_mask(sDST));
+						qc->err_mask |= ac_err_mask(sDST);
+						ata_qc_complete(qc);
 						break;
 					default:
 						break;
@@ -447,7 +447,8 @@ static inline unsigned int qs_intr_mmio(struct ata_host_set *host_set)
 
 				/* complete taskfile transaction */
 				pp->state = qs_state_idle;
-				ata_qc_complete(qc, ac_err_mask(status));
+				qc->err_mask |= ac_err_mask(status);
+				ata_qc_complete(qc);
 				handled = 1;
 			}
 		}
diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
index 36091868560d..b017f85e6d6a 100644
--- a/drivers/scsi/sata_sil.c
+++ b/drivers/scsi/sata_sil.c
@@ -147,7 +147,6 @@ static struct scsi_host_template sil_sht = {
 	.dma_boundary		= ATA_DMA_BOUNDARY,
 	.slave_configure	= ata_scsi_slave_config,
 	.bios_param		= ata_std_bios_param,
-	.ordered_flush		= 1,
 };
 
 static const struct ata_port_operations sil_ops = {
@@ -176,7 +175,7 @@ static const struct ata_port_operations sil_ops = {
 	.host_stop		= ata_pci_host_stop,
 };
 
-static struct ata_port_info sil_port_info[] = {
+static const struct ata_port_info sil_port_info[] = {
 	/* sil_3112 */
 	{
 		.sht		= &sil_sht,
diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c
index e0d6f194f54f..923130185a9e 100644
--- a/drivers/scsi/sata_sil24.c
+++ b/drivers/scsi/sata_sil24.c
@@ -292,7 +292,6 @@ static struct scsi_host_template sil24_sht = {
 	.dma_boundary		= ATA_DMA_BOUNDARY,
 	.slave_configure	= ata_scsi_slave_config,
 	.bios_param		= ata_std_bios_param,
-	.ordered_flush		= 1, /* NCQ not supported yet */
 };
 
 static const struct ata_port_operations sil24_ops = {
@@ -654,7 +653,8 @@ static void sil24_eng_timeout(struct ata_port *ap)
 	 */
 	printk(KERN_ERR "ata%u: command timeout\n", ap->id);
 	qc->scsidone = scsi_finish_command;
-	ata_qc_complete(qc, AC_ERR_OTHER);
+	qc->err_mask |= AC_ERR_OTHER;
+	ata_qc_complete(qc);
 
 	sil24_reset_controller(ap);
 }
@@ -711,8 +711,10 @@ static void sil24_error_intr(struct ata_port *ap, u32 slot_stat)
 		sil24_reset_controller(ap);
 	}
 
-	if (qc)
-		ata_qc_complete(qc, err_mask);
+	if (qc) {
+		qc->err_mask |= err_mask;
+		ata_qc_complete(qc);
+	}
 }
 
 static inline void sil24_host_intr(struct ata_port *ap)
@@ -734,8 +736,10 @@ static inline void sil24_host_intr(struct ata_port *ap)
 		 */
 		sil24_update_tf(ap);
 
-		if (qc)
-			ata_qc_complete(qc, ac_err_mask(pp->tf.command));
+		if (qc) {
+			qc->err_mask |= ac_err_mask(pp->tf.command);
+			ata_qc_complete(qc);
+		}
 	} else
 		sil24_error_intr(ap, slot_stat);
 }
diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c
index 32e12620b162..2df8c5632ac3 100644
--- a/drivers/scsi/sata_sis.c
+++ b/drivers/scsi/sata_sis.c
@@ -99,7 +99,6 @@ static struct scsi_host_template sis_sht = {
 	.dma_boundary		= ATA_DMA_BOUNDARY,
 	.slave_configure	= ata_scsi_slave_config,
 	.bios_param		= ata_std_bios_param,
-	.ordered_flush		= 1,
 };
 
 static const struct ata_port_operations sis_ops = {
diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c
index 6e7f7c83a75a..668373590aa4 100644
--- a/drivers/scsi/sata_svw.c
+++ b/drivers/scsi/sata_svw.c
@@ -303,7 +303,6 @@ static struct scsi_host_template k2_sata_sht = {
 	.proc_info		= k2_sata_proc_info,
 #endif
 	.bios_param		= ata_std_bios_param,
-	.ordered_flush		= 1,
 };
 
 
diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c
index ac7b0d819ebc..bc87c16c80d2 100644
--- a/drivers/scsi/sata_sx4.c
+++ b/drivers/scsi/sata_sx4.c
@@ -194,7 +194,6 @@ static struct scsi_host_template pdc_sata_sht = {
 	.dma_boundary		= ATA_DMA_BOUNDARY,
 	.slave_configure	= ata_scsi_slave_config,
 	.bios_param		= ata_std_bios_param,
-	.ordered_flush		= 1,
 };
 
 static const struct ata_port_operations pdc_20621_ops = {
@@ -215,7 +214,7 @@ static const struct ata_port_operations pdc_20621_ops = {
 	.host_stop		= pdc20621_host_stop,
 };
 
-static struct ata_port_info pdc_port_info[] = {
+static const struct ata_port_info pdc_port_info[] = {
 	/* board_20621 */
 	{
 		.sht		= &pdc_sata_sht,
@@ -719,7 +718,8 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
 			VPRINTK("ata%u: read hdma, 0x%x 0x%x\n", ap->id,
 				readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
 			/* get drive status; clear intr; complete txn */
-			ata_qc_complete(qc, ac_err_mask(ata_wait_idle(ap)));
+			qc->err_mask |= ac_err_mask(ata_wait_idle(ap));
+			ata_qc_complete(qc);
 			pdc20621_pop_hdma(qc);
 		}
 
@@ -757,7 +757,8 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
 			VPRINTK("ata%u: write ata, 0x%x 0x%x\n", ap->id,
 				readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
 			/* get drive status; clear intr; complete txn */
-			ata_qc_complete(qc, ac_err_mask(ata_wait_idle(ap)));
+			qc->err_mask |= ac_err_mask(ata_wait_idle(ap));
+			ata_qc_complete(qc);
 			pdc20621_pop_hdma(qc);
 		}
 		handled = 1;
@@ -767,7 +768,8 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
 
 		status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
 		DPRINTK("BUS_NODATA (drv_stat 0x%X)\n", status);
-		ata_qc_complete(qc, ac_err_mask(status));
+		qc->err_mask |= ac_err_mask(status);
+		ata_qc_complete(qc);
 		handled = 1;
 
 	} else {
@@ -882,7 +884,8 @@ static void pdc_eng_timeout(struct ata_port *ap)
 	case ATA_PROT_DMA:
 	case ATA_PROT_NODATA:
 		printk(KERN_ERR "ata%u: command timeout\n", ap->id);
-		ata_qc_complete(qc, __ac_err_mask(ata_wait_idle(ap)));
+		qc->err_mask |= __ac_err_mask(ata_wait_idle(ap));
+		ata_qc_complete(qc);
 		break;
 
 	default:
@@ -891,7 +894,8 @@ static void pdc_eng_timeout(struct ata_port *ap)
 		printk(KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n",
 		       ap->id, qc->tf.command, drv_stat);
 
-		ata_qc_complete(qc, ac_err_mask(drv_stat));
+		qc->err_mask |= ac_err_mask(drv_stat);
+		ata_qc_complete(qc);
 		break;
 	}
 
diff --git a/drivers/scsi/sata_uli.c b/drivers/scsi/sata_uli.c
index b2422a0f25c8..9635ca700977 100644
--- a/drivers/scsi/sata_uli.c
+++ b/drivers/scsi/sata_uli.c
@@ -87,7 +87,6 @@ static struct scsi_host_template uli_sht = {
 	.dma_boundary		= ATA_DMA_BOUNDARY,
 	.slave_configure	= ata_scsi_slave_config,
 	.bios_param		= ata_std_bios_param,
-	.ordered_flush		= 1,
 };
 
 static const struct ata_port_operations uli_ops = {
diff --git a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c
index c76215692da2..6d5b0a794cfd 100644
--- a/drivers/scsi/sata_via.c
+++ b/drivers/scsi/sata_via.c
@@ -106,7 +106,6 @@ static struct scsi_host_template svia_sht = {
 	.dma_boundary		= ATA_DMA_BOUNDARY,
 	.slave_configure	= ata_scsi_slave_config,
 	.bios_param		= ata_std_bios_param,
-	.ordered_flush		= 1,
 };
 
 static const struct ata_port_operations svia_sata_ops = {
diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c
index fcfa486965b4..2e2c3b7acb0c 100644
--- a/drivers/scsi/sata_vsc.c
+++ b/drivers/scsi/sata_vsc.c
@@ -235,7 +235,6 @@ static struct scsi_host_template vsc_sata_sht = {
 	.dma_boundary		= ATA_DMA_BOUNDARY,
 	.slave_configure	= ata_scsi_slave_config,
 	.bios_param		= ata_std_bios_param,
-	.ordered_flush		= 1,
 };
 
 
diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
index e69477d1889b..f01ec0a7c506 100644
--- a/drivers/scsi/scsi_devinfo.c
+++ b/drivers/scsi/scsi_devinfo.c
@@ -354,8 +354,9 @@ static int scsi_dev_info_list_add_str(char *dev_list)
  *     @model, if found, return the matching flags value, else return
  *     the host or global default settings.
  **/
-int scsi_get_device_flags(struct scsi_device *sdev, unsigned char *vendor,
-			  unsigned char *model)
+int scsi_get_device_flags(struct scsi_device *sdev,
+			  const unsigned char *vendor,
+			  const unsigned char *model)
 {
 	struct scsi_dev_info_list *devinfo;
 	unsigned int bflags;
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index c0ae9e965f6f..a2333d2c7af0 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -1320,23 +1320,6 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd)
 }
 
 /**
- * scsi_eh_lock_done - done function for eh door lock request
- * @scmd:	SCSI command block for the door lock request
- *
- * Notes:
- * 	We completed the asynchronous door lock request, and it has either
- * 	locked the door or failed.  We must free the command structures
- * 	associated with this request.
- **/
-static void scsi_eh_lock_done(struct scsi_cmnd *scmd)
-{
-	struct scsi_request *sreq = scmd->sc_request;
-
-	scsi_release_request(sreq);
-}
-
-
-/**
  * scsi_eh_lock_door - Prevent medium removal for the specified device
  * @sdev:	SCSI device to prevent medium removal
  *
@@ -1358,29 +1341,17 @@ static void scsi_eh_lock_done(struct scsi_cmnd *scmd)
  **/
 static void scsi_eh_lock_door(struct scsi_device *sdev)
 {
-	struct scsi_request *sreq = scsi_allocate_request(sdev, GFP_KERNEL);
+	unsigned char cmnd[MAX_COMMAND_SIZE];
 
-	if (unlikely(!sreq)) {
-		printk(KERN_ERR "%s: request allocate failed,"
-		       "prevent media removal cmd not sent\n", __FUNCTION__);
-		return;
-	}
+	cmnd[0] = ALLOW_MEDIUM_REMOVAL;
+	cmnd[1] = 0;
+	cmnd[2] = 0;
+	cmnd[3] = 0;
+	cmnd[4] = SCSI_REMOVAL_PREVENT;
+	cmnd[5] = 0;
 
-	sreq->sr_cmnd[0] = ALLOW_MEDIUM_REMOVAL;
-	sreq->sr_cmnd[1] = 0;
-	sreq->sr_cmnd[2] = 0;
-	sreq->sr_cmnd[3] = 0;
-	sreq->sr_cmnd[4] = SCSI_REMOVAL_PREVENT;
-	sreq->sr_cmnd[5] = 0;
-	sreq->sr_data_direction = DMA_NONE;
-	sreq->sr_bufflen = 0;
-	sreq->sr_buffer = NULL;
-	sreq->sr_allowed = 5;
-	sreq->sr_done = scsi_eh_lock_done;
-	sreq->sr_timeout_per_command = 10 * HZ;
-	sreq->sr_cmd_len = COMMAND_SIZE(sreq->sr_cmnd[0]);
-
-	scsi_insert_special_req(sreq, 1);
+	scsi_execute_async(sdev, cmnd, DMA_NONE, NULL, 0, 0, 10 * HZ,
+			   5, NULL, NULL, GFP_KERNEL);
 }
 
 
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index dc249cb970ea..ba93d6e66d48 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -63,39 +63,6 @@ static struct scsi_host_sg_pool scsi_sg_pools[] = {
 }; 	
 #undef SP
 
-
-/*
- * Function:    scsi_insert_special_req()
- *
- * Purpose:     Insert pre-formed request into request queue.
- *
- * Arguments:   sreq	- request that is ready to be queued.
- *              at_head	- boolean.  True if we should insert at head
- *                        of queue, false if we should insert at tail.
- *
- * Lock status: Assumed that lock is not held upon entry.
- *
- * Returns:     Nothing
- *
- * Notes:       This function is called from character device and from
- *              ioctl types of functions where the caller knows exactly
- *              what SCSI command needs to be issued.   The idea is that
- *              we merely inject the command into the queue (at the head
- *              for now), and then call the queue request function to actually
- *              process it.
- */
-int scsi_insert_special_req(struct scsi_request *sreq, int at_head)
-{
-	/*
-	 * Because users of this function are apt to reuse requests with no
-	 * modification, we have to sanitise the request flags here
-	 */
-	sreq->sr_request->flags &= ~REQ_DONTPREP;
-	blk_insert_request(sreq->sr_device->request_queue, sreq->sr_request,
-		       	   at_head, sreq);
-	return 0;
-}
-
 static void scsi_run_queue(struct request_queue *q);
 
 /*
@@ -249,8 +216,13 @@ void scsi_do_req(struct scsi_request *sreq, const void *cmnd,
 
 	/*
 	 * head injection *required* here otherwise quiesce won't work
+	 *
+	 * Because users of this function are apt to reuse requests with no
+	 * modification, we have to sanitise the request flags here
 	 */
-	scsi_insert_special_req(sreq, 1);
+	sreq->sr_request->flags &= ~REQ_DONTPREP;
+	blk_insert_request(sreq->sr_device->request_queue, sreq->sr_request,
+		       	   1, sreq);
 }
 EXPORT_SYMBOL(scsi_do_req);
 
@@ -287,6 +259,7 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
 	memcpy(req->cmd, cmd, req->cmd_len);
 	req->sense = sense;
 	req->sense_len = 0;
+	req->retries = retries;
 	req->timeout = timeout;
 	req->flags |= flags | REQ_BLOCK_PC | REQ_SPECIAL | REQ_QUIET;
 
@@ -327,6 +300,200 @@ int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd,
 }
 EXPORT_SYMBOL(scsi_execute_req);
 
+struct scsi_io_context {
+	void *data;
+	void (*done)(void *data, char *sense, int result, int resid);
+	char sense[SCSI_SENSE_BUFFERSIZE];
+};
+
+static kmem_cache_t *scsi_io_context_cache;
+
+static void scsi_end_async(struct request *req, int uptodate)
+{
+	struct scsi_io_context *sioc = req->end_io_data;
+
+	if (sioc->done)
+		sioc->done(sioc->data, sioc->sense, req->errors, req->data_len);
+
+	kmem_cache_free(scsi_io_context_cache, sioc);
+	__blk_put_request(req->q, req);
+}
+
+static int scsi_merge_bio(struct request *rq, struct bio *bio)
+{
+	struct request_queue *q = rq->q;
+
+	bio->bi_flags &= ~(1 << BIO_SEG_VALID);
+	if (rq_data_dir(rq) == WRITE)
+		bio->bi_rw |= (1 << BIO_RW);
+	blk_queue_bounce(q, &bio);
+
+	if (!rq->bio)
+		blk_rq_bio_prep(q, rq, bio);
+	else if (!q->back_merge_fn(q, rq, bio))
+		return -EINVAL;
+	else {
+		rq->biotail->bi_next = bio;
+		rq->biotail = bio;
+		rq->hard_nr_sectors += bio_sectors(bio);
+		rq->nr_sectors = rq->hard_nr_sectors;
+	}
+
+	return 0;
+}
+
+static int scsi_bi_endio(struct bio *bio, unsigned int bytes_done, int error)
+{
+	if (bio->bi_size)
+		return 1;
+
+	bio_put(bio);
+	return 0;
+}
+
+/**
+ * scsi_req_map_sg - map a scatterlist into a request
+ * @rq:		request to fill
+ * @sg:		scatterlist
+ * @nsegs:	number of elements
+ * @bufflen:	len of buffer
+ * @gfp:	memory allocation flags
+ *
+ * scsi_req_map_sg maps a scatterlist into a request so that the
+ * request can be sent to the block layer. We do not trust the scatterlist
+ * sent to use, as some ULDs use that struct to only organize the pages.
+ */
+static int scsi_req_map_sg(struct request *rq, struct scatterlist *sgl,
+			   int nsegs, unsigned bufflen, gfp_t gfp)
+{
+	struct request_queue *q = rq->q;
+	int nr_pages = (bufflen + PAGE_SIZE - 1) >> PAGE_SHIFT;
+	unsigned int data_len = 0, len, bytes, off;
+	struct page *page;
+	struct bio *bio = NULL;
+	int i, err, nr_vecs = 0;
+
+	for (i = 0; i < nsegs; i++) {
+		page = sgl[i].page;
+		off = sgl[i].offset;
+		len = sgl[i].length;
+		data_len += len;
+
+		while (len > 0) {
+			bytes = min_t(unsigned int, len, PAGE_SIZE - off);
+
+			if (!bio) {
+				nr_vecs = min_t(int, BIO_MAX_PAGES, nr_pages);
+				nr_pages -= nr_vecs;
+
+				bio = bio_alloc(gfp, nr_vecs);
+				if (!bio) {
+					err = -ENOMEM;
+					goto free_bios;
+				}
+				bio->bi_end_io = scsi_bi_endio;
+			}
+
+			if (bio_add_pc_page(q, bio, page, bytes, off) !=
+			    bytes) {
+				bio_put(bio);
+				err = -EINVAL;
+				goto free_bios;
+			}
+
+			if (bio->bi_vcnt >= nr_vecs) {
+				err = scsi_merge_bio(rq, bio);
+				if (err) {
+					bio_endio(bio, bio->bi_size, 0);
+					goto free_bios;
+				}
+				bio = NULL;
+			}
+
+			page++;
+			len -= bytes;
+			off = 0;
+		}
+	}
+
+	rq->buffer = rq->data = NULL;
+	rq->data_len = data_len;
+	return 0;
+
+free_bios:
+	while ((bio = rq->bio) != NULL) {
+		rq->bio = bio->bi_next;
+		/*
+		 * call endio instead of bio_put incase it was bounced
+		 */
+		bio_endio(bio, bio->bi_size, 0);
+	}
+
+	return err;
+}
+
+/**
+ * scsi_execute_async - insert request
+ * @sdev:	scsi device
+ * @cmd:	scsi command
+ * @data_direction: data direction
+ * @buffer:	data buffer (this can be a kernel buffer or scatterlist)
+ * @bufflen:	len of buffer
+ * @use_sg:	if buffer is a scatterlist this is the number of elements
+ * @timeout:	request timeout in seconds
+ * @retries:	number of times to retry request
+ * @flags:	or into request flags
+ **/
+int scsi_execute_async(struct scsi_device *sdev, const unsigned char *cmd,
+		       int data_direction, void *buffer, unsigned bufflen,
+		       int use_sg, int timeout, int retries, void *privdata,
+		       void (*done)(void *, char *, int, int), gfp_t gfp)
+{
+	struct request *req;
+	struct scsi_io_context *sioc;
+	int err = 0;
+	int write = (data_direction == DMA_TO_DEVICE);
+
+	sioc = kmem_cache_alloc(scsi_io_context_cache, gfp);
+	if (!sioc)
+		return DRIVER_ERROR << 24;
+	memset(sioc, 0, sizeof(*sioc));
+
+	req = blk_get_request(sdev->request_queue, write, gfp);
+	if (!req)
+		goto free_sense;
+	req->flags |= REQ_BLOCK_PC | REQ_QUIET;
+
+	if (use_sg)
+		err = scsi_req_map_sg(req, buffer, use_sg, bufflen, gfp);
+	else if (bufflen)
+		err = blk_rq_map_kern(req->q, req, buffer, bufflen, gfp);
+
+	if (err)
+		goto free_req;
+
+	req->cmd_len = COMMAND_SIZE(cmd[0]);
+	memcpy(req->cmd, cmd, req->cmd_len);
+	req->sense = sioc->sense;
+	req->sense_len = 0;
+	req->timeout = timeout;
+	req->retries = retries;
+	req->end_io_data = sioc;
+
+	sioc->data = privdata;
+	sioc->done = done;
+
+	blk_execute_rq_nowait(req->q, NULL, req, 1, scsi_end_async);
+	return 0;
+
+free_req:
+	blk_put_request(req);
+free_sense:
+	kfree(sioc);
+	return DRIVER_ERROR << 24;
+}
+EXPORT_SYMBOL_GPL(scsi_execute_async);
+
 /*
  * Function:    scsi_init_cmd_errh()
  *
@@ -624,7 +791,7 @@ static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int uptodate,
 	spin_lock_irqsave(q->queue_lock, flags);
 	if (blk_rq_tagged(req))
 		blk_queue_end_tag(q, req);
-	end_that_request_last(req);
+	end_that_request_last(req, uptodate);
 	spin_unlock_irqrestore(q->queue_lock, flags);
 
 	/*
@@ -765,9 +932,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes,
 	int sense_valid = 0;
 	int sense_deferred = 0;
 
-	if (blk_complete_barrier_rq(q, req, good_bytes >> 9))
-		return;
-
 	/*
 	 * Free up any indirection buffers we allocated for DMA purposes. 
 	 * For the case of a READ, we need to copy the data out of the
@@ -884,7 +1048,8 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes,
 			* system where READ CAPACITY failed, we may have read
 			* past the end of the disk.
 		 	*/
-			if (cmd->device->use_10_for_rw &&
+			if ((cmd->device->use_10_for_rw &&
+			    sshdr.asc == 0x20 && sshdr.ascq == 0x00) &&
 			    (cmd->cmnd[0] == READ_10 ||
 			     cmd->cmnd[0] == WRITE_10)) {
 				cmd->device->use_10_for_rw = 0;
@@ -1031,38 +1196,6 @@ static int scsi_init_io(struct scsi_cmnd *cmd)
 	return BLKPREP_KILL;
 }
 
-static int scsi_prepare_flush_fn(request_queue_t *q, struct request *rq)
-{
-	struct scsi_device *sdev = q->queuedata;
-	struct scsi_driver *drv;
-
-	if (sdev->sdev_state == SDEV_RUNNING) {
-		drv = *(struct scsi_driver **) rq->rq_disk->private_data;
-
-		if (drv->prepare_flush)
-			return drv->prepare_flush(q, rq);
-	}
-
-	return 0;
-}
-
-static void scsi_end_flush_fn(request_queue_t *q, struct request *rq)
-{
-	struct scsi_device *sdev = q->queuedata;
-	struct request *flush_rq = rq->end_io_data;
-	struct scsi_driver *drv;
-
-	if (flush_rq->errors) {
-		printk("scsi: barrier error, disabling flush support\n");
-		blk_queue_ordered(q, QUEUE_ORDERED_NONE);
-	}
-
-	if (sdev->sdev_state == SDEV_RUNNING) {
-		drv = *(struct scsi_driver **) rq->rq_disk->private_data;
-		drv->end_flush(q, rq);
-	}
-}
-
 static int scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk,
 			       sector_t *error_sector)
 {
@@ -1082,10 +1215,16 @@ static int scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk,
 static void scsi_generic_done(struct scsi_cmnd *cmd)
 {
 	BUG_ON(!blk_pc_request(cmd->request));
-	scsi_io_completion(cmd, cmd->result == 0 ? cmd->bufflen : 0, 0);
+	/*
+	 * This will complete the whole command with uptodate=1 so
+	 * as far as the block layer is concerned the command completed
+	 * successfully. Since this is a REQ_BLOCK_PC command the
+	 * caller should check the request's errors value
+	 */
+	scsi_io_completion(cmd, cmd->bufflen, 0);
 }
 
-void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd, int retries)
+void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd)
 {
 	struct request *req = cmd->request;
 
@@ -1100,7 +1239,7 @@ void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd, int retries)
 		cmd->sc_data_direction = DMA_FROM_DEVICE;
 	
 	cmd->transfersize = req->data_len;
-	cmd->allowed = retries;
+	cmd->allowed = req->retries;
 	cmd->timeout_per_command = req->timeout;
 }
 EXPORT_SYMBOL_GPL(scsi_setup_blk_pc_cmnd);
@@ -1240,7 +1379,7 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
 				goto kill;
 			}
 		} else {
-			scsi_setup_blk_pc_cmnd(cmd, 3);
+			scsi_setup_blk_pc_cmnd(cmd);
 			cmd->done = scsi_generic_done;
 		}
 	}
@@ -1529,17 +1668,6 @@ struct request_queue *scsi_alloc_queue(struct scsi_device *sdev)
 	blk_queue_segment_boundary(q, shost->dma_boundary);
 	blk_queue_issue_flush_fn(q, scsi_issue_flush_fn);
 
-	/*
-	 * ordered tags are superior to flush ordering
-	 */
-	if (shost->ordered_tag)
-		blk_queue_ordered(q, QUEUE_ORDERED_TAG);
-	else if (shost->ordered_flush) {
-		blk_queue_ordered(q, QUEUE_ORDERED_FLUSH);
-		q->prepare_flush_fn = scsi_prepare_flush_fn;
-		q->end_flush_fn = scsi_end_flush_fn;
-	}
-
 	if (!shost->use_clustering)
 		clear_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);
 	return q;
@@ -1603,6 +1731,14 @@ int __init scsi_init_queue(void)
 {
 	int i;
 
+	scsi_io_context_cache = kmem_cache_create("scsi_io_context",
+					sizeof(struct scsi_io_context),
+					0, 0, NULL, NULL);
+	if (!scsi_io_context_cache) {
+		printk(KERN_ERR "SCSI: can't init scsi io context cache\n");
+		return -ENOMEM;
+	}
+
 	for (i = 0; i < SG_MEMPOOL_NR; i++) {
 		struct scsi_host_sg_pool *sgp = scsi_sg_pools + i;
 		int size = sgp->size * sizeof(struct scatterlist);
@@ -1630,6 +1766,8 @@ void scsi_exit_queue(void)
 {
 	int i;
 
+	kmem_cache_destroy(scsi_io_context_cache);
+
 	for (i = 0; i < SG_MEMPOOL_NR; i++) {
 		struct scsi_host_sg_pool *sgp = scsi_sg_pools + i;
 		mempool_destroy(sgp->pool);
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
index d632d9e1493c..f04e7e11f57a 100644
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -40,7 +40,6 @@ extern void scsi_exit_hosts(void);
 extern int scsi_dispatch_cmd(struct scsi_cmnd *cmd);
 extern int scsi_setup_command_freelist(struct Scsi_Host *shost);
 extern void scsi_destroy_command_freelist(struct Scsi_Host *shost);
-extern int scsi_insert_special_req(struct scsi_request *sreq, int);
 extern void scsi_init_cmd_from_req(struct scsi_cmnd *cmd,
 		struct scsi_request *sreq);
 extern void __scsi_release_request(struct scsi_request *sreq);
@@ -57,7 +56,8 @@ static inline void scsi_log_completion(struct scsi_cmnd *cmd, int disposition)
 
 /* scsi_devinfo.c */
 extern int scsi_get_device_flags(struct scsi_device *sdev,
-				 unsigned char *vendor, unsigned char *model);
+				 const unsigned char *vendor,
+				 const unsigned char *model);
 extern int __init scsi_init_devinfo(void);
 extern void scsi_exit_devinfo(void);
 
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 4e6709f448e1..05ebb9cef961 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -74,7 +74,7 @@
 #define SCSI_SCAN_TARGET_PRESENT	1
 #define SCSI_SCAN_LUN_PRESENT		2
 
-static char *scsi_null_device_strs = "nullnullnullnull";
+static const char *scsi_null_device_strs = "nullnullnullnull";
 
 #define MAX_SCSI_LUNS	512
 
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index 46349293de08..ea7f3a433572 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -21,7 +21,7 @@
 #include "scsi_priv.h"
 #include "scsi_logging.h"
 
-static struct {
+static const struct {
 	enum scsi_device_state	value;
 	char			*name;
 } sdev_states[] = {
@@ -48,7 +48,7 @@ const char *scsi_device_state_name(enum scsi_device_state state)
 	return name;
 }
 
-static struct {
+static const struct {
 	enum scsi_host_state	value;
 	char			*name;
 } shost_states[] = {
@@ -263,9 +263,40 @@ static int scsi_bus_match(struct device *dev, struct device_driver *gendrv)
 	return (sdp->inq_periph_qual == SCSI_INQ_PQ_CON)? 1: 0;
 }
 
+static int scsi_bus_suspend(struct device * dev, pm_message_t state)
+{
+	struct scsi_device *sdev = to_scsi_device(dev);
+	struct scsi_host_template *sht = sdev->host->hostt;
+	int err;
+
+	err = scsi_device_quiesce(sdev);
+	if (err)
+		return err;
+
+	if (sht->suspend)
+		err = sht->suspend(sdev);
+
+	return err;
+}
+
+static int scsi_bus_resume(struct device * dev)
+{
+	struct scsi_device *sdev = to_scsi_device(dev);
+	struct scsi_host_template *sht = sdev->host->hostt;
+	int err = 0;
+
+	if (sht->resume)
+		err = sht->resume(sdev);
+
+	scsi_device_resume(sdev);
+	return err;
+}
+
 struct bus_type scsi_bus_type = {
         .name		= "scsi",
         .match		= scsi_bus_match,
+	.suspend	= scsi_bus_suspend,
+	.resume		= scsi_bus_resume,
 };
 
 int scsi_sysfs_register(void)
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 2a1a99a2ef56..685b997306cf 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -112,7 +112,7 @@ fc_enum_name_search(port_state, fc_port_state, fc_port_state_names)
 
 
 /* Convert fc_tgtid_binding_type values to ascii string name */
-static struct {
+static const struct {
 	enum fc_tgtid_binding_type	value;
 	char				*name;
 	int				matchlen;
@@ -150,7 +150,7 @@ get_fc_##title##_names(u32 table_key, char *buf)		\
 
 
 /* Convert FC_COS bit values to ascii string name */
-static struct {
+static const struct {
 	u32 			value;
 	char			*name;
 } fc_cos_names[] = {
@@ -164,7 +164,7 @@ fc_bitfield_name_search(cos, fc_cos_names)
 
 
 /* Convert FC_PORTSPEED bit values to ascii string name */
-static struct {
+static const struct {
 	u32 			value;
 	char			*name;
 } fc_port_speed_names[] = {
@@ -190,7 +190,7 @@ show_fc_fc4s (char *buf, u8 *fc4_list)
 
 
 /* Convert FC_RPORT_ROLE bit values to ascii string name */
-static struct {
+static const struct {
 	u32 			value;
 	char			*name;
 } fc_remote_port_role_names[] = {
diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c
index 38a53b5f9e9a..46da6fe10ad5 100644
--- a/drivers/scsi/scsi_transport_spi.c
+++ b/drivers/scsi/scsi_transport_spi.c
@@ -18,6 +18,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
+#include <linux/config.h>
 #include <linux/ctype.h>
 #include <linux/init.h>
 #include <linux/module.h>
@@ -378,9 +379,7 @@ static CLASS_DEVICE_ATTR(revalidate, S_IWUSR, NULL, store_spi_revalidate);
 
 /* Translate the period into ns according to the current spec
  * for SDTR/PPR messages */
-static ssize_t
-show_spi_transport_period_helper(struct class_device *cdev, char *buf,
-				 int period)
+static int period_to_str(char *buf, int period)
 {
 	int len, picosec;
 
@@ -398,6 +397,14 @@ show_spi_transport_period_helper(struct class_device *cdev, char *buf,
 		len = sprint_frac(buf, picosec, 1000);
 	}
 
+	return len;
+}
+
+static ssize_t
+show_spi_transport_period_helper(struct class_device *cdev, char *buf,
+				 int period)
+{
+	int len = period_to_str(buf, period);
 	buf[len++] = '\n';
 	buf[len] = '\0';
 	return len;
@@ -1041,12 +1048,133 @@ void spi_display_xfer_agreement(struct scsi_target *starget)
 			 tp->hold_mcs ? " HMCS" : "",
 			 tmp, tp->offset);
 	} else {
-		dev_info(&starget->dev, "%sasynchronous.\n",
+		dev_info(&starget->dev, "%sasynchronous\n",
 				tp->width ? "wide " : "");
 	}
 }
 EXPORT_SYMBOL(spi_display_xfer_agreement);
 
+#ifdef CONFIG_SCSI_CONSTANTS
+static const char * const one_byte_msgs[] = {
+/* 0x00 */ "Command Complete", NULL, "Save Pointers",
+/* 0x03 */ "Restore Pointers", "Disconnect", "Initiator Error", 
+/* 0x06 */ "Abort", "Message Reject", "Nop", "Message Parity Error",
+/* 0x0a */ "Linked Command Complete", "Linked Command Complete w/flag",
+/* 0x0c */ "Bus device reset", "Abort Tag", "Clear Queue", 
+/* 0x0f */ "Initiate Recovery", "Release Recovery"
+};
+
+static const char * const two_byte_msgs[] = {
+/* 0x20 */ "Simple Queue Tag", "Head of Queue Tag", "Ordered Queue Tag",
+/* 0x23 */ "Ignore Wide Residue"
+};
+
+static const char * const extended_msgs[] = {
+/* 0x00 */ "Modify Data Pointer", "Synchronous Data Transfer Request",
+/* 0x02 */ "SCSI-I Extended Identify", "Wide Data Transfer Request",
+/* 0x04 */ "Parallel Protocol Request"
+};
+
+void print_nego(const unsigned char *msg, int per, int off, int width)
+{
+	if (per) {
+		char buf[20];
+		period_to_str(buf, msg[per]);
+		printk("period = %s ns ", buf);
+	}
+
+	if (off)
+		printk("offset = %d ", msg[off]);
+	if (width)
+		printk("width = %d ", 8 << msg[width]);
+}
+
+int spi_print_msg(const unsigned char *msg)
+{
+	int len = 0, i;
+	if (msg[0] == EXTENDED_MESSAGE) {
+		len = 3 + msg[1];
+		if (msg[2] < ARRAY_SIZE(extended_msgs))
+			printk ("%s ", extended_msgs[msg[2]]); 
+		else 
+			printk ("Extended Message, reserved code (0x%02x) ",
+				(int) msg[2]);
+		switch (msg[2]) {
+		case EXTENDED_MODIFY_DATA_POINTER:
+			printk("pointer = %d", (int) (msg[3] << 24) |
+				(msg[4] << 16) | (msg[5] << 8) | msg[6]);
+			break;
+		case EXTENDED_SDTR:
+			print_nego(msg, 3, 4, 0);
+			break;
+		case EXTENDED_WDTR:
+			print_nego(msg, 0, 0, 3);
+			break;
+		case EXTENDED_PPR:
+			print_nego(msg, 3, 5, 6);
+			break;
+		default:
+		for (i = 2; i < len; ++i) 
+			printk("%02x ", msg[i]);
+		}
+	/* Identify */
+	} else if (msg[0] & 0x80) {
+		printk("Identify disconnect %sallowed %s %d ",
+			(msg[0] & 0x40) ? "" : "not ",
+			(msg[0] & 0x20) ? "target routine" : "lun",
+			msg[0] & 0x7);
+		len = 1;
+	/* Normal One byte */
+	} else if (msg[0] < 0x1f) {
+		if (msg[0] < ARRAY_SIZE(one_byte_msgs))
+			printk(one_byte_msgs[msg[0]]);
+		else
+			printk("reserved (%02x) ", msg[0]);
+		len = 1;
+	/* Two byte */
+	} else if (msg[0] <= 0x2f) {
+		if ((msg[0] - 0x20) < ARRAY_SIZE(two_byte_msgs))
+			printk("%s %02x ", two_byte_msgs[msg[0] - 0x20], 
+				msg[1]);
+		else 
+			printk("reserved two byte (%02x %02x) ", 
+				msg[0], msg[1]);
+		len = 2;
+	} else 
+		printk("reserved");
+	return len;
+}
+EXPORT_SYMBOL(spi_print_msg);
+
+#else  /* ifndef CONFIG_SCSI_CONSTANTS */
+
+int spi_print_msg(const unsigned char *msg)
+{
+	int len = 0, i;
+
+	if (msg[0] == EXTENDED_MESSAGE) {
+		len = 3 + msg[1];
+		for (i = 0; i < len; ++i)
+			printk("%02x ", msg[i]);
+	/* Identify */
+	} else if (msg[0] & 0x80) {
+		printk("%02x ", msg[0]);
+		len = 1;
+	/* Normal One byte */
+	} else if (msg[0] < 0x1f) {
+		printk("%02x ", msg[0]);
+		len = 1;
+	/* Two byte */
+	} else if (msg[0] <= 0x2f) {
+		printk("%02x %02x", msg[0], msg[1]);
+		len = 2;
+	} else 
+		printk("%02x ", msg[0]);
+	return len;
+}
+EXPORT_SYMBOL(spi_print_msg);
+#endif /* ! CONFIG_SCSI_CONSTANTS */
+
 #define SETUP_ATTRIBUTE(field)						\
 	i->private_attrs[count] = class_device_attr_##field;		\
 	if (!i->f->set_##field) {					\
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 03fcbab30033..32d4d8d7b9f3 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -102,6 +102,7 @@ struct scsi_disk {
 	u8		write_prot;
 	unsigned	WCE : 1;	/* state of disk WCE bit */
 	unsigned	RCD : 1;	/* state of disk RCD bit, unused */
+	unsigned	DPOFUA : 1;	/* state of disk DPOFUA bit */
 };
 
 static DEFINE_IDR(sd_index_idr);
@@ -121,8 +122,7 @@ static void sd_shutdown(struct device *dev);
 static void sd_rescan(struct device *);
 static int sd_init_command(struct scsi_cmnd *);
 static int sd_issue_flush(struct device *, sector_t *);
-static void sd_end_flush(request_queue_t *, struct request *);
-static int sd_prepare_flush(request_queue_t *, struct request *);
+static void sd_prepare_flush(request_queue_t *, struct request *);
 static void sd_read_capacity(struct scsi_disk *sdkp, char *diskname,
 			     unsigned char *buffer);
 
@@ -137,8 +137,6 @@ static struct scsi_driver sd_template = {
 	.rescan			= sd_rescan,
 	.init_command		= sd_init_command,
 	.issue_flush		= sd_issue_flush,
-	.prepare_flush		= sd_prepare_flush,
-	.end_flush		= sd_end_flush,
 };
 
 /*
@@ -245,7 +243,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
 	 * SG_IO from block layer already setup, just copy cdb basically
 	 */
 	if (blk_pc_request(rq)) {
-		scsi_setup_blk_pc_cmnd(SCpnt, SD_PASSTHROUGH_RETRIES);
+		scsi_setup_blk_pc_cmnd(SCpnt);
 		if (rq->timeout)
 			timeout = rq->timeout;
 
@@ -346,6 +344,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
 	
 	if (block > 0xffffffff) {
 		SCpnt->cmnd[0] += READ_16 - READ_6;
+		SCpnt->cmnd[1] |= blk_fua_rq(rq) ? 0x8 : 0;
 		SCpnt->cmnd[2] = sizeof(block) > 4 ? (unsigned char) (block >> 56) & 0xff : 0;
 		SCpnt->cmnd[3] = sizeof(block) > 4 ? (unsigned char) (block >> 48) & 0xff : 0;
 		SCpnt->cmnd[4] = sizeof(block) > 4 ? (unsigned char) (block >> 40) & 0xff : 0;
@@ -365,6 +364,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
 			this_count = 0xffff;
 
 		SCpnt->cmnd[0] += READ_10 - READ_6;
+		SCpnt->cmnd[1] |= blk_fua_rq(rq) ? 0x8 : 0;
 		SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff;
 		SCpnt->cmnd[3] = (unsigned char) (block >> 16) & 0xff;
 		SCpnt->cmnd[4] = (unsigned char) (block >> 8) & 0xff;
@@ -373,6 +373,17 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
 		SCpnt->cmnd[7] = (unsigned char) (this_count >> 8) & 0xff;
 		SCpnt->cmnd[8] = (unsigned char) this_count & 0xff;
 	} else {
+		if (unlikely(blk_fua_rq(rq))) {
+			/*
+			 * This happens only if this drive failed
+			 * 10byte rw command with ILLEGAL_REQUEST
+			 * during operation and thus turned off
+			 * use_10_for_rw.
+			 */
+			printk(KERN_ERR "sd: FUA write on READ/WRITE(6) drive\n");
+			return 0;
+		}
+
 		SCpnt->cmnd[1] |= (unsigned char) ((block >> 16) & 0x1f);
 		SCpnt->cmnd[2] = (unsigned char) ((block >> 8) & 0xff);
 		SCpnt->cmnd[3] = (unsigned char) block & 0xff;
@@ -729,42 +740,13 @@ static int sd_issue_flush(struct device *dev, sector_t *error_sector)
 	return ret;
 }
 
-static void sd_end_flush(request_queue_t *q, struct request *flush_rq)
-{
-	struct request *rq = flush_rq->end_io_data;
-	struct scsi_cmnd *cmd = rq->special;
-	unsigned int bytes = rq->hard_nr_sectors << 9;
-
-	if (!flush_rq->errors) {
-		spin_unlock(q->queue_lock);
-		scsi_io_completion(cmd, bytes, 0);
-		spin_lock(q->queue_lock);
-	} else if (blk_barrier_postflush(rq)) {
-		spin_unlock(q->queue_lock);
-		scsi_io_completion(cmd, 0, bytes);
-		spin_lock(q->queue_lock);
-	} else {
-		/*
-		 * force journal abort of barriers
-		 */
-		end_that_request_first(rq, -EOPNOTSUPP, rq->hard_nr_sectors);
-		end_that_request_last(rq);
-	}
-}
-
-static int sd_prepare_flush(request_queue_t *q, struct request *rq)
+static void sd_prepare_flush(request_queue_t *q, struct request *rq)
 {
-	struct scsi_device *sdev = q->queuedata;
-	struct scsi_disk *sdkp = dev_get_drvdata(&sdev->sdev_gendev);
-
-	if (!sdkp || !sdkp->WCE)
-		return 0;
-
 	memset(rq->cmd, 0, sizeof(rq->cmd));
-	rq->flags |= REQ_BLOCK_PC | REQ_SOFTBARRIER;
+	rq->flags |= REQ_BLOCK_PC;
 	rq->timeout = SD_TIMEOUT;
 	rq->cmd[0] = SYNCHRONIZE_CACHE;
-	return 1;
+	rq->cmd_len = 10;
 }
 
 static void sd_rescan(struct device *dev)
@@ -1427,10 +1409,18 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname,
 			sdkp->RCD = 0;
 		}
 
+		sdkp->DPOFUA = (data.device_specific & 0x10) != 0;
+		if (sdkp->DPOFUA && !sdkp->device->use_10_for_rw) {
+			printk(KERN_NOTICE "SCSI device %s: uses "
+			       "READ/WRITE(6), disabling FUA\n", diskname);
+			sdkp->DPOFUA = 0;
+		}
+
 		ct =  sdkp->RCD + 2*sdkp->WCE;
 
-		printk(KERN_NOTICE "SCSI device %s: drive cache: %s\n",
-		       diskname, types[ct]);
+		printk(KERN_NOTICE "SCSI device %s: drive cache: %s%s\n",
+		       diskname, types[ct],
+		       sdkp->DPOFUA ? " w/ FUA" : "");
 
 		return;
 	}
@@ -1462,6 +1452,7 @@ static int sd_revalidate_disk(struct gendisk *disk)
 	struct scsi_disk *sdkp = scsi_disk(disk);
 	struct scsi_device *sdp = sdkp->device;
 	unsigned char *buffer;
+	unsigned ordered;
 
 	SCSI_LOG_HLQUEUE(3, printk("sd_revalidate_disk: disk=%s\n", disk->disk_name));
 
@@ -1495,12 +1486,24 @@ static int sd_revalidate_disk(struct gendisk *disk)
 	 */
 	if (sdkp->media_present) {
 		sd_read_capacity(sdkp, disk->disk_name, buffer);
-		if (sdp->removable)
-			sd_read_write_protect_flag(sdkp, disk->disk_name,
-						   buffer);
+		sd_read_write_protect_flag(sdkp, disk->disk_name, buffer);
 		sd_read_cache_type(sdkp, disk->disk_name, buffer);
 	}
-		
+
+	/*
+	 * We now have all cache related info, determine how we deal
+	 * with ordered requests.  Note that as the current SCSI
+	 * dispatch function can alter request order, we cannot use
+	 * QUEUE_ORDERED_TAG_* even when ordered tag is supported.
+	 */
+	if (sdkp->WCE)
+		ordered = sdkp->DPOFUA
+			? QUEUE_ORDERED_DRAIN_FUA : QUEUE_ORDERED_DRAIN_FLUSH;
+	else
+		ordered = QUEUE_ORDERED_DRAIN;
+
+	blk_queue_ordered(sdkp->disk->queue, ordered, sd_prepare_flush);
+
 	set_capacity(disk, sdkp->capacity);
 	kfree(buffer);
 
@@ -1600,6 +1603,7 @@ static int sd_probe(struct device *dev)
 	strcpy(gd->devfs_name, sdp->devfs_name);
 
 	gd->private_data = &sdkp->driver;
+	gd->queue = sdkp->device->request_queue;
 
 	sd_revalidate_disk(gd);
 
@@ -1607,7 +1611,6 @@ static int sd_probe(struct device *dev)
 	gd->flags = GENHD_FL_DRIVERFS;
 	if (sdp->removable)
 		gd->flags |= GENHD_FL_REMOVABLE;
-	gd->queue = sdkp->device->request_queue;
 
 	dev_set_drvdata(dev, sdkp);
 	add_disk(gd);
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index b55c2a8a547c..221e96e2620a 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -104,8 +104,6 @@ static int sg_allow_dio = SG_ALLOW_DIO_DEF;
 static int sg_add(struct class_device *, struct class_interface *);
 static void sg_remove(struct class_device *, struct class_interface *);
 
-static Scsi_Request *dummy_cmdp;	/* only used for sizeof */
-
 static DEFINE_RWLOCK(sg_dev_arr_lock);	/* Also used to lock
 							   file descriptor list for device */
 
@@ -119,7 +117,7 @@ typedef struct sg_scatter_hold { /* holding area for scsi scatter gather info */
 	unsigned short sglist_len; /* size of malloc'd scatter-gather list ++ */
 	unsigned bufflen;	/* Size of (aggregate) data buffer */
 	unsigned b_malloc_len;	/* actual len malloc'ed in buffer */
-	void *buffer;		/* Data buffer or scatter list (k_use_sg>0) */
+	struct scatterlist *buffer;/* scatter list */
 	char dio_in_use;	/* 0->indirect IO (or mmap), 1->dio */
 	unsigned char cmd_opcode; /* first byte of command */
 } Sg_scatter_hold;
@@ -128,12 +126,11 @@ struct sg_device;		/* forward declarations */
 struct sg_fd;
 
 typedef struct sg_request {	/* SG_MAX_QUEUE requests outstanding per file */
-	Scsi_Request *my_cmdp;	/* != 0  when request with lower levels */
 	struct sg_request *nextrp;	/* NULL -> tail request (slist) */
 	struct sg_fd *parentfp;	/* NULL -> not in use */
 	Sg_scatter_hold data;	/* hold buffer, perhaps scatter list */
 	sg_io_hdr_t header;	/* scsi command+info, see <scsi/sg.h> */
-	unsigned char sense_b[sizeof (dummy_cmdp->sr_sense_buffer)];
+	unsigned char sense_b[SCSI_SENSE_BUFFERSIZE];
 	char res_used;		/* 1 -> using reserve buffer, 0 -> not ... */
 	char orphan;		/* 1 -> drop on sight, 0 -> normal */
 	char sg_io_owned;	/* 1 -> packet belongs to SG_IO */
@@ -174,7 +171,8 @@ typedef struct sg_device { /* holds the state of each scsi generic device */
 } Sg_device;
 
 static int sg_fasync(int fd, struct file *filp, int mode);
-static void sg_cmd_done(Scsi_Cmnd * SCpnt);	/* tasklet or soft irq callback */
+/* tasklet or soft irq callback */
+static void sg_cmd_done(void *data, char *sense, int result, int resid);
 static int sg_start_req(Sg_request * srp);
 static void sg_finish_rem_req(Sg_request * srp);
 static int sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size);
@@ -195,8 +193,8 @@ static void sg_remove_scat(Sg_scatter_hold * schp);
 static void sg_build_reserve(Sg_fd * sfp, int req_size);
 static void sg_link_reserve(Sg_fd * sfp, Sg_request * srp, int size);
 static void sg_unlink_reserve(Sg_fd * sfp, Sg_request * srp);
-static char *sg_page_malloc(int rqSz, int lowDma, int *retSzp);
-static void sg_page_free(char *buff, int size);
+static struct page *sg_page_malloc(int rqSz, int lowDma, int *retSzp);
+static void sg_page_free(struct page *page, int size);
 static Sg_fd *sg_add_sfp(Sg_device * sdp, int dev);
 static int sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp);
 static void __sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp);
@@ -207,7 +205,6 @@ static int sg_res_in_use(Sg_fd * sfp);
 static int sg_allow_access(unsigned char opcode, char dev_type);
 static int sg_build_direct(Sg_request * srp, Sg_fd * sfp, int dxfer_len);
 static Sg_device *sg_get_dev(int dev);
-static inline unsigned char *sg_scatg2virt(const struct scatterlist *sclp);
 #ifdef CONFIG_SCSI_PROC_FS
 static int sg_last_dev(void);
 #endif
@@ -226,6 +223,7 @@ sg_open(struct inode *inode, struct file *filp)
 {
 	int dev = iminor(inode);
 	int flags = filp->f_flags;
+	struct request_queue *q;
 	Sg_device *sdp;
 	Sg_fd *sfp;
 	int res;
@@ -287,7 +285,9 @@ sg_open(struct inode *inode, struct file *filp)
 	}
 	if (!sdp->headfp) {	/* no existing opens on this device */
 		sdp->sgdebug = 0;
-		sdp->sg_tablesize = sdp->device->host->sg_tablesize;
+		q = sdp->device->request_queue;
+		sdp->sg_tablesize = min(q->max_hw_segments,
+					q->max_phys_segments);
 	}
 	if ((sfp = sg_add_sfp(sdp, dev)))
 		filp->private_data = sfp;
@@ -340,6 +340,7 @@ sg_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos)
 		return -ENXIO;
 	SCSI_LOG_TIMEOUT(3, printk("sg_read: %s, count=%d\n",
 				   sdp->disk->disk_name, (int) count));
+
 	if (!access_ok(VERIFY_WRITE, buf, count))
 		return -EFAULT;
 	if (sfp->force_packid && (count >= SZ_SG_HEADER)) {
@@ -491,7 +492,7 @@ sg_new_read(Sg_fd * sfp, char __user *buf, size_t count, Sg_request * srp)
 	if ((hp->mx_sb_len > 0) && hp->sbp) {
 		if ((CHECK_CONDITION & hp->masked_status) ||
 		    (DRIVER_SENSE & hp->driver_status)) {
-			int sb_len = sizeof (dummy_cmdp->sr_sense_buffer);
+			int sb_len = SCSI_SENSE_BUFFERSIZE;
 			sb_len = (hp->mx_sb_len > sb_len) ? sb_len : hp->mx_sb_len;
 			len = 8 + (int) srp->sense_b[7];	/* Additional sense length field */
 			len = (len > sb_len) ? sb_len : len;
@@ -525,7 +526,7 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
 	Sg_request *srp;
 	struct sg_header old_hdr;
 	sg_io_hdr_t *hp;
-	unsigned char cmnd[sizeof (dummy_cmdp->sr_cmnd)];
+	unsigned char cmnd[MAX_COMMAND_SIZE];
 
 	if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp)))
 		return -ENXIO;
@@ -624,7 +625,7 @@ sg_new_write(Sg_fd * sfp, const char __user *buf, size_t count,
 	int k;
 	Sg_request *srp;
 	sg_io_hdr_t *hp;
-	unsigned char cmnd[sizeof (dummy_cmdp->sr_cmnd)];
+	unsigned char cmnd[MAX_COMMAND_SIZE];
 	int timeout;
 	unsigned long ul_timeout;
 
@@ -692,11 +693,9 @@ static int
 sg_common_write(Sg_fd * sfp, Sg_request * srp,
 		unsigned char *cmnd, int timeout, int blocking)
 {
-	int k;
-	Scsi_Request *SRpnt;
+	int k, data_dir;
 	Sg_device *sdp = sfp->parentdp;
 	sg_io_hdr_t *hp = &srp->header;
-	request_queue_t *q;
 
 	srp->data.cmd_opcode = cmnd[0];	/* hold opcode of command */
 	hp->status = 0;
@@ -723,51 +722,36 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp,
 		sg_finish_rem_req(srp);
 		return -ENODEV;
 	}
-	SRpnt = scsi_allocate_request(sdp->device, GFP_ATOMIC);
-	if (SRpnt == NULL) {
-		SCSI_LOG_TIMEOUT(1, printk("sg_write: no mem\n"));
-		sg_finish_rem_req(srp);
-		return -ENOMEM;
-	}
 
-	srp->my_cmdp = SRpnt;
-	q = SRpnt->sr_device->request_queue;
-	SRpnt->sr_request->rq_disk = sdp->disk;
-	SRpnt->sr_sense_buffer[0] = 0;
-	SRpnt->sr_cmd_len = hp->cmd_len;
-	SRpnt->sr_use_sg = srp->data.k_use_sg;
-	SRpnt->sr_sglist_len = srp->data.sglist_len;
-	SRpnt->sr_bufflen = srp->data.bufflen;
-	SRpnt->sr_underflow = 0;
-	SRpnt->sr_buffer = srp->data.buffer;
 	switch (hp->dxfer_direction) {
 	case SG_DXFER_TO_FROM_DEV:
 	case SG_DXFER_FROM_DEV:
-		SRpnt->sr_data_direction = DMA_FROM_DEVICE;
+		data_dir = DMA_FROM_DEVICE;
 		break;
 	case SG_DXFER_TO_DEV:
-		SRpnt->sr_data_direction = DMA_TO_DEVICE;
+		data_dir = DMA_TO_DEVICE;
 		break;
 	case SG_DXFER_UNKNOWN:
-		SRpnt->sr_data_direction = DMA_BIDIRECTIONAL;
+		data_dir = DMA_BIDIRECTIONAL;
 		break;
 	default:
-		SRpnt->sr_data_direction = DMA_NONE;
+		data_dir = DMA_NONE;
 		break;
 	}
-	SRpnt->upper_private_data = srp;
-	srp->data.k_use_sg = 0;
-	srp->data.sglist_len = 0;
-	srp->data.bufflen = 0;
-	srp->data.buffer = NULL;
 	hp->duration = jiffies_to_msecs(jiffies);
 /* Now send everything of to mid-level. The next time we hear about this
    packet is when sg_cmd_done() is called (i.e. a callback). */
-	scsi_do_req(SRpnt, (void *) cmnd,
-		    (void *) SRpnt->sr_buffer, hp->dxfer_len,
-		    sg_cmd_done, timeout, SG_DEFAULT_RETRIES);
-	/* dxfer_len overwrites SRpnt->sr_bufflen, hence need for b_malloc_len */
-	return 0;
+	if (scsi_execute_async(sdp->device, cmnd, data_dir, srp->data.buffer,
+				hp->dxfer_len, srp->data.k_use_sg, timeout,
+				SG_DEFAULT_RETRIES, srp, sg_cmd_done,
+				GFP_ATOMIC)) {
+		SCSI_LOG_TIMEOUT(1, printk("sg_write: scsi_execute_async failed\n"));
+		/*
+		 * most likely out of mem, but could also be a bad map
+		 */
+		return -ENOMEM;
+	} else
+		return 0;
 }
 
 static int
@@ -1156,45 +1140,22 @@ sg_fasync(int fd, struct file *filp, int mode)
 	return (retval < 0) ? retval : 0;
 }
 
-static inline unsigned char *
-sg_scatg2virt(const struct scatterlist *sclp)
-{
-	return (sclp && sclp->page) ?
-	    (unsigned char *) page_address(sclp->page) + sclp->offset : NULL;
-}
-
 /* When startFinish==1 increments page counts for pages other than the 
-   first of scatter gather elements obtained from __get_free_pages().
+   first of scatter gather elements obtained from alloc_pages().
    When startFinish==0 decrements ... */
 static void
 sg_rb_correct4mmap(Sg_scatter_hold * rsv_schp, int startFinish)
 {
-	void *page_ptr;
+	struct scatterlist *sg = rsv_schp->buffer;
 	struct page *page;
 	int k, m;
 
 	SCSI_LOG_TIMEOUT(3, printk("sg_rb_correct4mmap: startFinish=%d, scatg=%d\n", 
 				   startFinish, rsv_schp->k_use_sg));
 	/* N.B. correction _not_ applied to base page of each allocation */
-	if (rsv_schp->k_use_sg) {	/* reserve buffer is a scatter gather list */
-		struct scatterlist *sclp = rsv_schp->buffer;
-
-		for (k = 0; k < rsv_schp->k_use_sg; ++k, ++sclp) {
-			for (m = PAGE_SIZE; m < sclp->length; m += PAGE_SIZE) {
-				page_ptr = sg_scatg2virt(sclp) + m;
-				page = virt_to_page(page_ptr);
-				if (startFinish)
-					get_page(page);
-				else {
-					if (page_count(page) > 0)
-						__put_page(page);
-				}
-			}
-		}
-	} else {		/* reserve buffer is just a single allocation */
-		for (m = PAGE_SIZE; m < rsv_schp->bufflen; m += PAGE_SIZE) {
-			page_ptr = (unsigned char *) rsv_schp->buffer + m;
-			page = virt_to_page(page_ptr);
+	for (k = 0; k < rsv_schp->k_use_sg; ++k, ++sg) {
+		for (m = PAGE_SIZE; m < sg->length; m += PAGE_SIZE) {
+			page = sg->page;
 			if (startFinish)
 				get_page(page);
 			else {
@@ -1210,9 +1171,10 @@ sg_vma_nopage(struct vm_area_struct *vma, unsigned long addr, int *type)
 {
 	Sg_fd *sfp;
 	struct page *page = NOPAGE_SIGBUS;
-	void *page_ptr = NULL;
-	unsigned long offset;
+	unsigned long offset, len, sa;
 	Sg_scatter_hold *rsv_schp;
+	struct scatterlist *sg;
+	int k;
 
 	if ((NULL == vma) || (!(sfp = (Sg_fd *) vma->vm_private_data)))
 		return page;
@@ -1222,30 +1184,21 @@ sg_vma_nopage(struct vm_area_struct *vma, unsigned long addr, int *type)
 		return page;
 	SCSI_LOG_TIMEOUT(3, printk("sg_vma_nopage: offset=%lu, scatg=%d\n",
 				   offset, rsv_schp->k_use_sg));
-	if (rsv_schp->k_use_sg) {	/* reserve buffer is a scatter gather list */
-		int k;
-		unsigned long sa = vma->vm_start;
-		unsigned long len;
-		struct scatterlist *sclp = rsv_schp->buffer;
-
-		for (k = 0; (k < rsv_schp->k_use_sg) && (sa < vma->vm_end);
-		     ++k, ++sclp) {
-			len = vma->vm_end - sa;
-			len = (len < sclp->length) ? len : sclp->length;
-			if (offset < len) {
-				page_ptr = sg_scatg2virt(sclp) + offset;
-				page = virt_to_page(page_ptr);
-				get_page(page);	/* increment page count */
-				break;
-			}
-			sa += len;
-			offset -= len;
+	sg = rsv_schp->buffer;
+	sa = vma->vm_start;
+	for (k = 0; (k < rsv_schp->k_use_sg) && (sa < vma->vm_end);
+	     ++k, ++sg) {
+		len = vma->vm_end - sa;
+		len = (len < sg->length) ? len : sg->length;
+		if (offset < len) {
+			page = sg->page;
+			get_page(page);	/* increment page count */
+			break;
 		}
-	} else {		/* reserve buffer is just a single allocation */
-		page_ptr = (unsigned char *) rsv_schp->buffer + offset;
-		page = virt_to_page(page_ptr);
-		get_page(page);	/* increment page count */
+		sa += len;
+		offset -= len;
 	}
+
 	if (type)
 		*type = VM_FAULT_MINOR;
 	return page;
@@ -1259,8 +1212,10 @@ static int
 sg_mmap(struct file *filp, struct vm_area_struct *vma)
 {
 	Sg_fd *sfp;
-	unsigned long req_sz;
+	unsigned long req_sz, len, sa;
 	Sg_scatter_hold *rsv_schp;
+	int k;
+	struct scatterlist *sg;
 
 	if ((!filp) || (!vma) || (!(sfp = (Sg_fd *) filp->private_data)))
 		return -ENXIO;
@@ -1273,24 +1228,15 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma)
 	if (req_sz > rsv_schp->bufflen)
 		return -ENOMEM;	/* cannot map more than reserved buffer */
 
-	if (rsv_schp->k_use_sg) { /* reserve buffer is a scatter gather list */
-		int k;
-		unsigned long sa = vma->vm_start;
-		unsigned long len;
-		struct scatterlist *sclp = rsv_schp->buffer;
-
-		for (k = 0; (k < rsv_schp->k_use_sg) && (sa < vma->vm_end);
-		     ++k, ++sclp) {
-			if (0 != sclp->offset)
-				return -EFAULT;	/* non page aligned memory ?? */
-			len = vma->vm_end - sa;
-			len = (len < sclp->length) ? len : sclp->length;
-			sa += len;
-		}
-	} else {	/* reserve buffer is just a single allocation */
-		if ((unsigned long) rsv_schp->buffer & (PAGE_SIZE - 1))
-			return -EFAULT;	/* non page aligned memory ?? */
+	sa = vma->vm_start;
+	sg = rsv_schp->buffer;
+	for (k = 0; (k < rsv_schp->k_use_sg) && (sa < vma->vm_end);
+	     ++k, ++sg) {
+		len = vma->vm_end - sa;
+		len = (len < sg->length) ? len : sg->length;
+		sa += len;
 	}
+
 	if (0 == sfp->mmap_called) {
 		sg_rb_correct4mmap(rsv_schp, 1);	/* do only once per fd lifetime */
 		sfp->mmap_called = 1;
@@ -1304,21 +1250,16 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma)
 /* This function is a "bottom half" handler that is called by the
  * mid level when a command is completed (or has failed). */
 static void
-sg_cmd_done(Scsi_Cmnd * SCpnt)
+sg_cmd_done(void *data, char *sense, int result, int resid)
 {
-	Scsi_Request *SRpnt = NULL;
+	Sg_request *srp = data;
 	Sg_device *sdp = NULL;
 	Sg_fd *sfp;
-	Sg_request *srp = NULL;
 	unsigned long iflags;
 	unsigned int ms;
 
-	if (SCpnt && (SRpnt = SCpnt->sc_request))
-		srp = (Sg_request *) SRpnt->upper_private_data;
 	if (NULL == srp) {
 		printk(KERN_ERR "sg_cmd_done: NULL request\n");
-		if (SRpnt)
-			scsi_release_request(SRpnt);
 		return;
 	}
 	sfp = srp->parentfp;
@@ -1326,49 +1267,34 @@ sg_cmd_done(Scsi_Cmnd * SCpnt)
 		sdp = sfp->parentdp;
 	if ((NULL == sdp) || sdp->detached) {
 		printk(KERN_INFO "sg_cmd_done: device detached\n");
-		scsi_release_request(SRpnt);
 		return;
 	}
 
-	/* First transfer ownership of data buffers to sg_device object. */
-	srp->data.k_use_sg = SRpnt->sr_use_sg;
-	srp->data.sglist_len = SRpnt->sr_sglist_len;
-	srp->data.bufflen = SRpnt->sr_bufflen;
-	srp->data.buffer = SRpnt->sr_buffer;
-	/* now clear out request structure */
-	SRpnt->sr_use_sg = 0;
-	SRpnt->sr_sglist_len = 0;
-	SRpnt->sr_bufflen = 0;
-	SRpnt->sr_buffer = NULL;
-	SRpnt->sr_underflow = 0;
-	SRpnt->sr_request->rq_disk = NULL; /* "sg" _disowns_ request blk */
-
-	srp->my_cmdp = NULL;
 
 	SCSI_LOG_TIMEOUT(4, printk("sg_cmd_done: %s, pack_id=%d, res=0x%x\n",
-		sdp->disk->disk_name, srp->header.pack_id, (int) SRpnt->sr_result));
-	srp->header.resid = SCpnt->resid;
+		sdp->disk->disk_name, srp->header.pack_id, result));
+	srp->header.resid = resid;
 	ms = jiffies_to_msecs(jiffies);
 	srp->header.duration = (ms > srp->header.duration) ?
 				(ms - srp->header.duration) : 0;
-	if (0 != SRpnt->sr_result) {
+	if (0 != result) {
 		struct scsi_sense_hdr sshdr;
 
-		memcpy(srp->sense_b, SRpnt->sr_sense_buffer,
-		       sizeof (srp->sense_b));
-		srp->header.status = 0xff & SRpnt->sr_result;
-		srp->header.masked_status = status_byte(SRpnt->sr_result);
-		srp->header.msg_status = msg_byte(SRpnt->sr_result);
-		srp->header.host_status = host_byte(SRpnt->sr_result);
-		srp->header.driver_status = driver_byte(SRpnt->sr_result);
+		memcpy(srp->sense_b, sense, sizeof (srp->sense_b));
+		srp->header.status = 0xff & result;
+		srp->header.masked_status = status_byte(result);
+		srp->header.msg_status = msg_byte(result);
+		srp->header.host_status = host_byte(result);
+		srp->header.driver_status = driver_byte(result);
 		if ((sdp->sgdebug > 0) &&
 		    ((CHECK_CONDITION == srp->header.masked_status) ||
 		     (COMMAND_TERMINATED == srp->header.masked_status)))
-			scsi_print_req_sense("sg_cmd_done", SRpnt);
+			__scsi_print_sense("sg_cmd_done", sense,
+					   SCSI_SENSE_BUFFERSIZE);
 
 		/* Following if statement is a patch supplied by Eric Youngdale */
-		if (driver_byte(SRpnt->sr_result) != 0
-		    && scsi_command_normalize_sense(SCpnt, &sshdr)
+		if (driver_byte(result) != 0
+		    && scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, &sshdr)
 		    && !scsi_sense_is_deferred(&sshdr)
 		    && sshdr.sense_key == UNIT_ATTENTION
 		    && sdp->device->removable) {
@@ -1379,8 +1305,6 @@ sg_cmd_done(Scsi_Cmnd * SCpnt)
 	}
 	/* Rely on write phase to clean out srp status values, so no "else" */
 
-	scsi_release_request(SRpnt);
-	SRpnt = NULL;
 	if (sfp->closed) {	/* whoops this fd already released, cleanup */
 		SCSI_LOG_TIMEOUT(1, printk("sg_cmd_done: already closed, freeing ...\n"));
 		sg_finish_rem_req(srp);
@@ -1431,6 +1355,7 @@ static int sg_sysfs_valid = 0;
 
 static int sg_alloc(struct gendisk *disk, struct scsi_device *scsidp)
 {
+	struct request_queue *q = scsidp->request_queue;
 	Sg_device *sdp;
 	unsigned long iflags;
 	void *old_sg_dev_arr = NULL;
@@ -1473,7 +1398,7 @@ static int sg_alloc(struct gendisk *disk, struct scsi_device *scsidp)
 	sdp->disk = disk;
 	sdp->device = scsidp;
 	init_waitqueue_head(&sdp->o_excl_wait);
-	sdp->sg_tablesize = scsidp->host ? scsidp->host->sg_tablesize : 0;
+	sdp->sg_tablesize = min(q->max_hw_segments, q->max_phys_segments);
 
 	sg_nr_dev++;
 	sg_dev_arr[k] = sdp;
@@ -1753,36 +1678,35 @@ sg_finish_rem_req(Sg_request * srp)
 static int
 sg_build_sgat(Sg_scatter_hold * schp, const Sg_fd * sfp, int tablesize)
 {
-	int ret_sz;
-	int elem_sz = sizeof (struct scatterlist);
-	int sg_bufflen = tablesize * elem_sz;
-	int mx_sc_elems = tablesize;
+	int sg_bufflen = tablesize * sizeof(struct scatterlist);
+	unsigned int gfp_flags = GFP_ATOMIC | __GFP_NOWARN;
 
-	schp->buffer = sg_page_malloc(sg_bufflen, sfp->low_dma, &ret_sz);
+	/*
+	 * TODO: test without low_dma, we should not need it since
+	 * the block layer will bounce the buffer for us
+	 *
+	 * XXX(hch): we shouldn't need GFP_DMA for the actual S/G list.
+	 */
+	if (sfp->low_dma)
+		 gfp_flags |= GFP_DMA;
+	schp->buffer = kzalloc(sg_bufflen, gfp_flags);
 	if (!schp->buffer)
 		return -ENOMEM;
-	else if (ret_sz != sg_bufflen) {
-		sg_bufflen = ret_sz;
-		mx_sc_elems = sg_bufflen / elem_sz;
-	}
 	schp->sglist_len = sg_bufflen;
-	memset(schp->buffer, 0, sg_bufflen);
-	return mx_sc_elems;	/* number of scat_gath elements allocated */
+	return tablesize;	/* number of scat_gath elements allocated */
 }
 
 #ifdef SG_ALLOW_DIO_CODE
 /* vvvvvvvv  following code borrowed from st driver's direct IO vvvvvvvvv */
-	/* hopefully this generic code will moved to a library */
+	/* TODO: hopefully we can use the generic block layer code */
 
 /* Pin down user pages and put them into a scatter gather list. Returns <= 0 if
    - mapping of all pages not successful
-   - any page is above max_pfn
    (i.e., either completely successful or fails)
 */
 static int 
 st_map_user_pages(struct scatterlist *sgl, const unsigned int max_pages, 
-	          unsigned long uaddr, size_t count, int rw,
-	          unsigned long max_pfn)
+	          unsigned long uaddr, size_t count, int rw)
 {
 	unsigned long end = (uaddr + count + PAGE_SIZE - 1) >> PAGE_SHIFT;
 	unsigned long start = uaddr >> PAGE_SHIFT;
@@ -1828,21 +1752,17 @@ st_map_user_pages(struct scatterlist *sgl, const unsigned int max_pages,
                  * probably wrong function for rw==WRITE
                  */
 		flush_dcache_page(pages[i]);
-		if (page_to_pfn(pages[i]) > max_pfn)
-			goto out_unlock;
 		/* ?? Is locking needed? I don't think so */
 		/* if (TestSetPageLocked(pages[i]))
 		   goto out_unlock; */
         }
 
-	/* Populate the scatter/gather list */
-	sgl[0].page = pages[0]; 
+	sgl[0].page = pages[0];
 	sgl[0].offset = uaddr & ~PAGE_MASK;
 	if (nr_pages > 1) {
 		sgl[0].length = PAGE_SIZE - sgl[0].offset;
 		count -= sgl[0].length;
 		for (i=1; i < nr_pages ; i++) {
-			sgl[i].offset = 0;
 			sgl[i].page = pages[i]; 
 			sgl[i].length = count < PAGE_SIZE ? count : PAGE_SIZE;
 			count -= PAGE_SIZE;
@@ -1855,10 +1775,6 @@ st_map_user_pages(struct scatterlist *sgl, const unsigned int max_pages,
 	kfree(pages);
 	return nr_pages;
 
- out_unlock:
-	/* for (j=0; j < i; j++)
-	   unlock_page(pages[j]); */
-	res = 0;
  out_unmap:
 	if (res > 0) {
 		for (j=0; j < res; j++)
@@ -1904,20 +1820,20 @@ sg_build_direct(Sg_request * srp, Sg_fd * sfp, int dxfer_len)
 	sg_io_hdr_t *hp = &srp->header;
 	Sg_scatter_hold *schp = &srp->data;
 	int sg_tablesize = sfp->parentdp->sg_tablesize;
-	struct scatterlist *sgl;
 	int mx_sc_elems, res;
 	struct scsi_device *sdev = sfp->parentdp->device;
 
 	if (((unsigned long)hp->dxferp &
 			queue_dma_alignment(sdev->request_queue)) != 0)
 		return 1;
+
 	mx_sc_elems = sg_build_sgat(schp, sfp, sg_tablesize);
         if (mx_sc_elems <= 0) {
                 return 1;
         }
-	sgl = (struct scatterlist *)schp->buffer;
-	res = st_map_user_pages(sgl, mx_sc_elems, (unsigned long)hp->dxferp, dxfer_len, 
-				(SG_DXFER_TO_DEV == hp->dxfer_direction) ? 1 : 0, ULONG_MAX);
+	res = st_map_user_pages(schp->buffer, mx_sc_elems,
+				(unsigned long)hp->dxferp, dxfer_len, 
+				(SG_DXFER_TO_DEV == hp->dxfer_direction) ? 1 : 0);
 	if (res <= 0)
 		return 1;
 	schp->k_use_sg = res;
@@ -1932,9 +1848,11 @@ sg_build_direct(Sg_request * srp, Sg_fd * sfp, int dxfer_len)
 static int
 sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size)
 {
-	int ret_sz;
+	struct scatterlist *sg;
+	int ret_sz = 0, k, rem_sz, num, mx_sc_elems;
+	int sg_tablesize = sfp->parentdp->sg_tablesize;
 	int blk_size = buff_size;
-	unsigned char *p = NULL;
+	struct page *p = NULL;
 
 	if ((blk_size < 0) || (!sfp))
 		return -EFAULT;
@@ -1944,59 +1862,35 @@ sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size)
 	blk_size = (blk_size + SG_SECTOR_MSK) & (~SG_SECTOR_MSK);
 	SCSI_LOG_TIMEOUT(4, printk("sg_build_indirect: buff_size=%d, blk_size=%d\n",
 				   buff_size, blk_size));
-	if (blk_size <= SG_SCATTER_SZ) {
-		p = sg_page_malloc(blk_size, sfp->low_dma, &ret_sz);
-		if (!p)
-			return -ENOMEM;
-		if (blk_size == ret_sz) {	/* got it on the first attempt */
-			schp->k_use_sg = 0;
-			schp->buffer = p;
-			schp->bufflen = blk_size;
-			schp->b_malloc_len = blk_size;
-			return 0;
-		}
-	} else {
-		p = sg_page_malloc(SG_SCATTER_SZ, sfp->low_dma, &ret_sz);
+
+	/* N.B. ret_sz carried into this block ... */
+	mx_sc_elems = sg_build_sgat(schp, sfp, sg_tablesize);
+	if (mx_sc_elems < 0)
+		return mx_sc_elems;	/* most likely -ENOMEM */
+
+	for (k = 0, sg = schp->buffer, rem_sz = blk_size;
+	     (rem_sz > 0) && (k < mx_sc_elems);
+	     ++k, rem_sz -= ret_sz, ++sg) {
+		
+		num = (rem_sz > SG_SCATTER_SZ) ? SG_SCATTER_SZ : rem_sz;
+		p = sg_page_malloc(num, sfp->low_dma, &ret_sz);
 		if (!p)
 			return -ENOMEM;
-	}
-/* Want some local declarations, so start new block ... */
-	{			/* lets try and build a scatter gather list */
-		struct scatterlist *sclp;
-		int k, rem_sz, num;
-		int mx_sc_elems;
-		int sg_tablesize = sfp->parentdp->sg_tablesize;
-		int first = 1;
-
-		/* N.B. ret_sz carried into this block ... */
-		mx_sc_elems = sg_build_sgat(schp, sfp, sg_tablesize);
-		if (mx_sc_elems < 0)
-			return mx_sc_elems;	/* most likely -ENOMEM */
-
-		for (k = 0, sclp = schp->buffer, rem_sz = blk_size;
-		     (rem_sz > 0) && (k < mx_sc_elems);
-		     ++k, rem_sz -= ret_sz, ++sclp) {
-			if (first)
-				first = 0;
-			else {
-				num =
-				    (rem_sz >
-				     SG_SCATTER_SZ) ? SG_SCATTER_SZ : rem_sz;
-				p = sg_page_malloc(num, sfp->low_dma, &ret_sz);
-				if (!p)
-					break;
-			}
-			sg_set_buf(sclp, p, ret_sz);
-
-			SCSI_LOG_TIMEOUT(5, printk("sg_build_build: k=%d, a=0x%p, len=%d\n",
-					  k, sg_scatg2virt(sclp), ret_sz));
-		}		/* end of for loop */
-		schp->k_use_sg = k;
-		SCSI_LOG_TIMEOUT(5, printk("sg_build_indirect: k_use_sg=%d, rem_sz=%d\n", k, rem_sz));
-		schp->bufflen = blk_size;
-		if (rem_sz > 0)	/* must have failed */
-			return -ENOMEM;
-	}
+
+		sg->page = p;
+		sg->length = ret_sz;
+
+		SCSI_LOG_TIMEOUT(5, printk("sg_build_build: k=%d, a=0x%p, len=%d\n",
+				  k, p, ret_sz));
+	}		/* end of for loop */
+
+	schp->k_use_sg = k;
+	SCSI_LOG_TIMEOUT(5, printk("sg_build_indirect: k_use_sg=%d, rem_sz=%d\n", k, rem_sz));
+
+	schp->bufflen = blk_size;
+	if (rem_sz > 0)	/* must have failed */
+		return -ENOMEM;
+
 	return 0;
 }
 
@@ -2005,6 +1899,7 @@ sg_write_xfer(Sg_request * srp)
 {
 	sg_io_hdr_t *hp = &srp->header;
 	Sg_scatter_hold *schp = &srp->data;
+	struct scatterlist *sg = schp->buffer;
 	int num_xfer = 0;
 	int j, k, onum, usglen, ksglen, res;
 	int iovec_count = (int) hp->iovec_count;
@@ -2033,63 +1928,45 @@ sg_write_xfer(Sg_request * srp)
 	} else
 		onum = 1;
 
-	if (0 == schp->k_use_sg) {	/* kernel has single buffer */
-		for (j = 0, p = schp->buffer; j < onum; ++j) {
-			res = sg_u_iovec(hp, iovec_count, j, 1, &usglen, &up);
-			if (res)
-				return res;
-			usglen = (num_xfer > usglen) ? usglen : num_xfer;
-			if (__copy_from_user(p, up, usglen))
-				return -EFAULT;
-			p += usglen;
-			num_xfer -= usglen;
-			if (num_xfer <= 0)
-				return 0;
-		}
-	} else {		/* kernel using scatter gather list */
-		struct scatterlist *sclp = (struct scatterlist *) schp->buffer;
-
-		ksglen = (int) sclp->length;
-		p = sg_scatg2virt(sclp);
-		for (j = 0, k = 0; j < onum; ++j) {
-			res = sg_u_iovec(hp, iovec_count, j, 1, &usglen, &up);
-			if (res)
-				return res;
-
-			for (; p; ++sclp, ksglen = (int) sclp->length,
-				  p = sg_scatg2virt(sclp)) {
-				if (usglen <= 0)
-					break;
-				if (ksglen > usglen) {
-					if (usglen >= num_xfer) {
-						if (__copy_from_user
-						    (p, up, num_xfer))
-							return -EFAULT;
-						return 0;
-					}
-					if (__copy_from_user(p, up, usglen))
-						return -EFAULT;
-					p += usglen;
-					ksglen -= usglen;
-					break;
-				} else {
-					if (ksglen >= num_xfer) {
-						if (__copy_from_user
-						    (p, up, num_xfer))
-							return -EFAULT;
-						return 0;
-					}
-					if (__copy_from_user(p, up, ksglen))
+	ksglen = sg->length;
+	p = page_address(sg->page);
+	for (j = 0, k = 0; j < onum; ++j) {
+		res = sg_u_iovec(hp, iovec_count, j, 1, &usglen, &up);
+		if (res)
+			return res;
+
+		for (; p; ++sg, ksglen = sg->length,
+		     p = page_address(sg->page)) {
+			if (usglen <= 0)
+				break;
+			if (ksglen > usglen) {
+				if (usglen >= num_xfer) {
+					if (__copy_from_user(p, up, num_xfer))
 						return -EFAULT;
-					up += ksglen;
-					usglen -= ksglen;
+					return 0;
 				}
-				++k;
-				if (k >= schp->k_use_sg)
+				if (__copy_from_user(p, up, usglen))
+					return -EFAULT;
+				p += usglen;
+				ksglen -= usglen;
+				break;
+			} else {
+				if (ksglen >= num_xfer) {
+					if (__copy_from_user(p, up, num_xfer))
+						return -EFAULT;
 					return 0;
+				}
+				if (__copy_from_user(p, up, ksglen))
+					return -EFAULT;
+				up += ksglen;
+				usglen -= ksglen;
 			}
+			++k;
+			if (k >= schp->k_use_sg)
+				return 0;
 		}
 	}
+
 	return 0;
 }
 
@@ -2127,29 +2004,25 @@ sg_remove_scat(Sg_scatter_hold * schp)
 {
 	SCSI_LOG_TIMEOUT(4, printk("sg_remove_scat: k_use_sg=%d\n", schp->k_use_sg));
 	if (schp->buffer && (schp->sglist_len > 0)) {
-		struct scatterlist *sclp = (struct scatterlist *) schp->buffer;
+		struct scatterlist *sg = schp->buffer;
 
 		if (schp->dio_in_use) {
 #ifdef SG_ALLOW_DIO_CODE
-			st_unmap_user_pages(sclp, schp->k_use_sg, TRUE);
+			st_unmap_user_pages(sg, schp->k_use_sg, TRUE);
 #endif
 		} else {
 			int k;
 
-			for (k = 0; (k < schp->k_use_sg) && sg_scatg2virt(sclp);
-			     ++k, ++sclp) {
+			for (k = 0; (k < schp->k_use_sg) && sg->page;
+			     ++k, ++sg) {
 				SCSI_LOG_TIMEOUT(5, printk(
 				    "sg_remove_scat: k=%d, a=0x%p, len=%d\n",
-				    k, sg_scatg2virt(sclp), sclp->length));
-				sg_page_free(sg_scatg2virt(sclp), sclp->length);
-				sclp->page = NULL;
-				sclp->offset = 0;
-				sclp->length = 0;
+				    k, sg->page, sg->length));
+				sg_page_free(sg->page, sg->length);
 			}
 		}
-		sg_page_free(schp->buffer, schp->sglist_len);
-	} else if (schp->buffer)
-		sg_page_free(schp->buffer, schp->b_malloc_len);
+		kfree(schp->buffer);
+	}
 	memset(schp, 0, sizeof (*schp));
 }
 
@@ -2158,6 +2031,7 @@ sg_read_xfer(Sg_request * srp)
 {
 	sg_io_hdr_t *hp = &srp->header;
 	Sg_scatter_hold *schp = &srp->data;
+	struct scatterlist *sg = schp->buffer;
 	int num_xfer = 0;
 	int j, k, onum, usglen, ksglen, res;
 	int iovec_count = (int) hp->iovec_count;
@@ -2186,63 +2060,45 @@ sg_read_xfer(Sg_request * srp)
 	} else
 		onum = 1;
 
-	if (0 == schp->k_use_sg) {	/* kernel has single buffer */
-		for (j = 0, p = schp->buffer; j < onum; ++j) {
-			res = sg_u_iovec(hp, iovec_count, j, 0, &usglen, &up);
-			if (res)
-				return res;
-			usglen = (num_xfer > usglen) ? usglen : num_xfer;
-			if (__copy_to_user(up, p, usglen))
-				return -EFAULT;
-			p += usglen;
-			num_xfer -= usglen;
-			if (num_xfer <= 0)
-				return 0;
-		}
-	} else {		/* kernel using scatter gather list */
-		struct scatterlist *sclp = (struct scatterlist *) schp->buffer;
-
-		ksglen = (int) sclp->length;
-		p = sg_scatg2virt(sclp);
-		for (j = 0, k = 0; j < onum; ++j) {
-			res = sg_u_iovec(hp, iovec_count, j, 0, &usglen, &up);
-			if (res)
-				return res;
-
-			for (; p; ++sclp, ksglen = (int) sclp->length,
-				  p = sg_scatg2virt(sclp)) {
-				if (usglen <= 0)
-					break;
-				if (ksglen > usglen) {
-					if (usglen >= num_xfer) {
-						if (__copy_to_user
-						    (up, p, num_xfer))
-							return -EFAULT;
-						return 0;
-					}
-					if (__copy_to_user(up, p, usglen))
-						return -EFAULT;
-					p += usglen;
-					ksglen -= usglen;
-					break;
-				} else {
-					if (ksglen >= num_xfer) {
-						if (__copy_to_user
-						    (up, p, num_xfer))
-							return -EFAULT;
-						return 0;
-					}
-					if (__copy_to_user(up, p, ksglen))
+	p = page_address(sg->page);
+	ksglen = sg->length;
+	for (j = 0, k = 0; j < onum; ++j) {
+		res = sg_u_iovec(hp, iovec_count, j, 0, &usglen, &up);
+		if (res)
+			return res;
+
+		for (; p; ++sg, ksglen = sg->length,
+		     p = page_address(sg->page)) {
+			if (usglen <= 0)
+				break;
+			if (ksglen > usglen) {
+				if (usglen >= num_xfer) {
+					if (__copy_to_user(up, p, num_xfer))
 						return -EFAULT;
-					up += ksglen;
-					usglen -= ksglen;
+					return 0;
 				}
-				++k;
-				if (k >= schp->k_use_sg)
+				if (__copy_to_user(up, p, usglen))
+					return -EFAULT;
+				p += usglen;
+				ksglen -= usglen;
+				break;
+			} else {
+				if (ksglen >= num_xfer) {
+					if (__copy_to_user(up, p, num_xfer))
+						return -EFAULT;
 					return 0;
+				}
+				if (__copy_to_user(up, p, ksglen))
+					return -EFAULT;
+				up += ksglen;
+				usglen -= ksglen;
 			}
+			++k;
+			if (k >= schp->k_use_sg)
+				return 0;
 		}
 	}
+
 	return 0;
 }
 
@@ -2250,37 +2106,32 @@ static int
 sg_read_oxfer(Sg_request * srp, char __user *outp, int num_read_xfer)
 {
 	Sg_scatter_hold *schp = &srp->data;
+	struct scatterlist *sg = schp->buffer;
+	int k, num;
 
 	SCSI_LOG_TIMEOUT(4, printk("sg_read_oxfer: num_read_xfer=%d\n",
 				   num_read_xfer));
 	if ((!outp) || (num_read_xfer <= 0))
 		return 0;
-	if (schp->k_use_sg > 0) {
-		int k, num;
-		struct scatterlist *sclp = (struct scatterlist *) schp->buffer;
-
-		for (k = 0; (k < schp->k_use_sg) && sg_scatg2virt(sclp);
-		     ++k, ++sclp) {
-			num = (int) sclp->length;
-			if (num > num_read_xfer) {
-				if (__copy_to_user
-				    (outp, sg_scatg2virt(sclp), num_read_xfer))
-					return -EFAULT;
+
+	for (k = 0; (k < schp->k_use_sg) && sg->page; ++k, ++sg) {
+		num = sg->length;
+		if (num > num_read_xfer) {
+			if (__copy_to_user(outp, page_address(sg->page),
+					   num_read_xfer))
+				return -EFAULT;
+			break;
+		} else {
+			if (__copy_to_user(outp, page_address(sg->page),
+					   num))
+				return -EFAULT;
+			num_read_xfer -= num;
+			if (num_read_xfer <= 0)
 				break;
-			} else {
-				if (__copy_to_user
-				    (outp, sg_scatg2virt(sclp), num))
-					return -EFAULT;
-				num_read_xfer -= num;
-				if (num_read_xfer <= 0)
-					break;
-				outp += num;
-			}
+			outp += num;
 		}
-	} else {
-		if (__copy_to_user(outp, schp->buffer, num_read_xfer))
-			return -EFAULT;
 	}
+
 	return 0;
 }
 
@@ -2306,44 +2157,31 @@ sg_link_reserve(Sg_fd * sfp, Sg_request * srp, int size)
 {
 	Sg_scatter_hold *req_schp = &srp->data;
 	Sg_scatter_hold *rsv_schp = &sfp->reserve;
+	struct scatterlist *sg = rsv_schp->buffer;
+	int k, num, rem;
 
 	srp->res_used = 1;
 	SCSI_LOG_TIMEOUT(4, printk("sg_link_reserve: size=%d\n", size));
-	size = (size + 1) & (~1);	/* round to even for aha1542 */
-	if (rsv_schp->k_use_sg > 0) {
-		int k, num;
-		int rem = size;
-		struct scatterlist *sclp =
-		    (struct scatterlist *) rsv_schp->buffer;
-
-		for (k = 0; k < rsv_schp->k_use_sg; ++k, ++sclp) {
-			num = (int) sclp->length;
-			if (rem <= num) {
-				if (0 == k) {
-					req_schp->k_use_sg = 0;
-					req_schp->buffer = sg_scatg2virt(sclp);
-				} else {
-					sfp->save_scat_len = num;
-					sclp->length = (unsigned) rem;
-					req_schp->k_use_sg = k + 1;
-					req_schp->sglist_len =
-					    rsv_schp->sglist_len;
-					req_schp->buffer = rsv_schp->buffer;
-				}
-				req_schp->bufflen = size;
-				req_schp->b_malloc_len = rsv_schp->b_malloc_len;
-				break;
-			} else
-				rem -= num;
-		}
-		if (k >= rsv_schp->k_use_sg)
-			SCSI_LOG_TIMEOUT(1, printk("sg_link_reserve: BAD size\n"));
-	} else {
-		req_schp->k_use_sg = 0;
-		req_schp->bufflen = size;
-		req_schp->buffer = rsv_schp->buffer;
-		req_schp->b_malloc_len = rsv_schp->b_malloc_len;
+	rem = size = (size + 1) & (~1);	/* round to even for aha1542 */
+
+	for (k = 0; k < rsv_schp->k_use_sg; ++k, ++sg) {
+		num = sg->length;
+		if (rem <= num) {
+			sfp->save_scat_len = num;
+			sg->length = rem;
+			req_schp->k_use_sg = k + 1;
+			req_schp->sglist_len = rsv_schp->sglist_len;
+			req_schp->buffer = rsv_schp->buffer;
+
+			req_schp->bufflen = size;
+			req_schp->b_malloc_len = rsv_schp->b_malloc_len;
+			break;
+		} else
+			rem -= num;
 	}
+
+	if (k >= rsv_schp->k_use_sg)
+		SCSI_LOG_TIMEOUT(1, printk("sg_link_reserve: BAD size\n"));
 }
 
 static void
@@ -2355,11 +2193,10 @@ sg_unlink_reserve(Sg_fd * sfp, Sg_request * srp)
 	SCSI_LOG_TIMEOUT(4, printk("sg_unlink_reserve: req->k_use_sg=%d\n",
 				   (int) req_schp->k_use_sg));
 	if ((rsv_schp->k_use_sg > 0) && (req_schp->k_use_sg > 0)) {
-		struct scatterlist *sclp =
-		    (struct scatterlist *) rsv_schp->buffer;
+		struct scatterlist *sg = rsv_schp->buffer;
 
 		if (sfp->save_scat_len > 0)
-			(sclp + (req_schp->k_use_sg - 1))->length =
+			(sg + (req_schp->k_use_sg - 1))->length =
 			    (unsigned) sfp->save_scat_len;
 		else
 			SCSI_LOG_TIMEOUT(1, printk ("sg_unlink_reserve: BAD save_scat_len\n"));
@@ -2445,7 +2282,6 @@ sg_add_request(Sg_fd * sfp)
 	if (resp) {
 		resp->nextrp = NULL;
 		resp->header.duration = jiffies_to_msecs(jiffies);
-		resp->my_cmdp = NULL;
 	}
 	write_unlock_irqrestore(&sfp->rq_list_lock, iflags);
 	return resp;
@@ -2463,8 +2299,6 @@ sg_remove_request(Sg_fd * sfp, Sg_request * srp)
 	if ((!sfp) || (!srp) || (!sfp->headrp))
 		return res;
 	write_lock_irqsave(&sfp->rq_list_lock, iflags);
-	if (srp->my_cmdp)
-		srp->my_cmdp->upper_private_data = NULL;
 	prev_rp = sfp->headrp;
 	if (srp == prev_rp) {
 		sfp->headrp = prev_rp->nextrp;
@@ -2507,10 +2341,10 @@ sg_add_sfp(Sg_device * sdp, int dev)
 	Sg_fd *sfp;
 	unsigned long iflags;
 
-	sfp = (Sg_fd *) sg_page_malloc(sizeof (Sg_fd), 0, NULL);
+	sfp = kzalloc(sizeof(*sfp), GFP_ATOMIC | __GFP_NOWARN);
 	if (!sfp)
 		return NULL;
-	memset(sfp, 0, sizeof (Sg_fd));
+
 	init_waitqueue_head(&sfp->read_wait);
 	rwlock_init(&sfp->rq_list_lock);
 
@@ -2567,7 +2401,7 @@ __sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp)
 	}
 	sfp->parentdp = NULL;
 	SCSI_LOG_TIMEOUT(6, printk("__sg_remove_sfp:    sfp=0x%p\n", sfp));
-	sg_page_free((char *) sfp, sizeof (Sg_fd));
+	kfree(sfp);
 }
 
 /* Returns 0 in normal case, 1 when detached and sdp object removed */
@@ -2632,10 +2466,10 @@ sg_res_in_use(Sg_fd * sfp)
 }
 
 /* If retSzp==NULL want exact size or fail */
-static char *
+static struct page *
 sg_page_malloc(int rqSz, int lowDma, int *retSzp)
 {
-	char *resp = NULL;
+	struct page *resp = NULL;
 	gfp_t page_mask;
 	int order, a_size;
 	int resSz = rqSz;
@@ -2650,11 +2484,11 @@ sg_page_malloc(int rqSz, int lowDma, int *retSzp)
 
 	for (order = 0, a_size = PAGE_SIZE; a_size < rqSz;
 	     order++, a_size <<= 1) ;
-	resp = (char *) __get_free_pages(page_mask, order);
+	resp = alloc_pages(page_mask, order);
 	while ((!resp) && order && retSzp) {
 		--order;
 		a_size >>= 1;	/* divide by 2, until PAGE_SIZE */
-		resp = (char *) __get_free_pages(page_mask, order);	/* try half */
+		resp =  alloc_pages(page_mask, order);	/* try half */
 		resSz = a_size;
 	}
 	if (resp) {
@@ -2667,15 +2501,15 @@ sg_page_malloc(int rqSz, int lowDma, int *retSzp)
 }
 
 static void
-sg_page_free(char *buff, int size)
+sg_page_free(struct page *page, int size)
 {
 	int order, a_size;
 
-	if (!buff)
+	if (!page)
 		return;
 	for (order = 0, a_size = PAGE_SIZE; a_size < size;
 	     order++, a_size <<= 1) ;
-	free_pages((unsigned long) buff, order);
+	__free_pages(page, order);
 }
 
 #ifndef MAINTENANCE_IN_CMD
@@ -3067,13 +2901,11 @@ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp)
 					cp = "     ";
 			}
 			seq_printf(s, cp);
-			blen = srp->my_cmdp ? 
-				srp->my_cmdp->sr_bufflen : srp->data.bufflen;
-			usg = srp->my_cmdp ? 
-				srp->my_cmdp->sr_use_sg : srp->data.k_use_sg;
+			blen = srp->data.bufflen;
+			usg = srp->data.k_use_sg;
 			seq_printf(s, srp->done ? 
 				   ((1 == srp->done) ?  "rcv:" : "fin:")
-				   : (srp->my_cmdp ? "act:" : "prior:"));
+				   : "act:");
 			seq_printf(s, " id=%d blen=%d",
 				   srp->header.pack_id, blen);
 			if (srp->done)
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index fb4012b5c188..a4d9be7c6874 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -320,7 +320,7 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
 	 * these are already setup, just copy cdb basically
 	 */
 	if (SCpnt->request->flags & REQ_BLOCK_PC) {
-		scsi_setup_blk_pc_cmnd(SCpnt, MAX_RETRIES);
+		scsi_setup_blk_pc_cmnd(SCpnt);
 
 		if (SCpnt->timeout_per_command)
 			timeout = SCpnt->timeout_per_command;
@@ -716,7 +716,7 @@ static void get_capabilities(struct scsi_cd *cd)
 	unsigned int the_result;
 	int retries, rc, n;
 
-	static char *loadmech[] =
+	static const char *loadmech[] =
 	{
 		"caddy",
 		"tray",
diff --git a/drivers/scsi/sr_vendor.c b/drivers/scsi/sr_vendor.c
index 78274dc91f5c..9dde8df2f5c9 100644
--- a/drivers/scsi/sr_vendor.c
+++ b/drivers/scsi/sr_vendor.c
@@ -68,8 +68,8 @@ void sr_vendor_init(Scsi_CD *cd)
 #ifndef CONFIG_BLK_DEV_SR_VENDOR
 	cd->vendor = VENDOR_SCSI3;
 #else
-	char *vendor = cd->device->vendor;
-	char *model = cd->device->model;
+	const char *vendor = cd->device->vendor;
+	const char *model = cd->device->model;
 	
 	/* default */
 	cd->vendor = VENDOR_SCSI3;
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index dd592f6a2529..c4aade8f5345 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -17,7 +17,7 @@
    Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support
  */
 
-static char *verstr = "20050830";
+static const char *verstr = "20050830";
 
 #include <linux/module.h>
 
@@ -50,7 +50,6 @@ static char *verstr = "20050830";
 #include <scsi/scsi_eh.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_ioctl.h>
-#include <scsi/scsi_request.h>
 #include <scsi/sg.h>
 
 
@@ -134,7 +133,7 @@ static struct st_dev_parm {
 #endif
 /* Bit reversed order to get same names for same minors with all
    mode counts */
-static char *st_formats[] = {
+static const char *st_formats[] = {
 	"",  "r", "k", "s", "l", "t", "o", "u",
 	"m", "v", "p", "x", "a", "y", "q", "z"}; 
 
@@ -188,8 +187,6 @@ static int from_buffer(struct st_buffer *, char __user *, int);
 static void move_buffer_data(struct st_buffer *, int);
 static void buf_to_sg(struct st_buffer *, unsigned int);
 
-static int st_map_user_pages(struct scatterlist *, const unsigned int, 
-			     unsigned long, size_t, int, unsigned long);
 static int sgl_map_user_pages(struct scatterlist *, const unsigned int, 
 			      unsigned long, size_t, int);
 static int sgl_unmap_user_pages(struct scatterlist *, const unsigned int, int);
@@ -313,12 +310,13 @@ static inline char *tape_name(struct scsi_tape *tape)
 }
 
 
-static void st_analyze_sense(struct scsi_request *SRpnt, struct st_cmdstatus *s)
+static void st_analyze_sense(struct st_request *SRpnt, struct st_cmdstatus *s)
 {
 	const u8 *ucp;
-	const u8 *sense = SRpnt->sr_sense_buffer;
+	const u8 *sense = SRpnt->sense;
 
-	s->have_sense = scsi_request_normalize_sense(SRpnt, &s->sense_hdr);
+	s->have_sense = scsi_normalize_sense(SRpnt->sense,
+				SCSI_SENSE_BUFFERSIZE, &s->sense_hdr);
 	s->flags = 0;
 
 	if (s->have_sense) {
@@ -345,9 +343,9 @@ static void st_analyze_sense(struct scsi_request *SRpnt, struct st_cmdstatus *s)
 
 
 /* Convert the result to success code */
-static int st_chk_result(struct scsi_tape *STp, struct scsi_request * SRpnt)
+static int st_chk_result(struct scsi_tape *STp, struct st_request * SRpnt)
 {
-	int result = SRpnt->sr_result;
+	int result = SRpnt->result;
 	u8 scode;
 	DEB(const char *stp;)
 	char *name = tape_name(STp);
@@ -366,13 +364,12 @@ static int st_chk_result(struct scsi_tape *STp, struct scsi_request * SRpnt)
 
         DEB(
         if (debugging) {
-                printk(ST_DEB_MSG "%s: Error: %x, cmd: %x %x %x %x %x %x Len: %d\n",
+                printk(ST_DEB_MSG "%s: Error: %x, cmd: %x %x %x %x %x %x\n",
 		       name, result,
-		       SRpnt->sr_cmnd[0], SRpnt->sr_cmnd[1], SRpnt->sr_cmnd[2],
-		       SRpnt->sr_cmnd[3], SRpnt->sr_cmnd[4], SRpnt->sr_cmnd[5],
-		       SRpnt->sr_bufflen);
+		       SRpnt->cmd[0], SRpnt->cmd[1], SRpnt->cmd[2],
+		       SRpnt->cmd[3], SRpnt->cmd[4], SRpnt->cmd[5]);
 		if (cmdstatp->have_sense)
-			scsi_print_req_sense("st", SRpnt);
+			 __scsi_print_sense("st", SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
 	} ) /* end DEB */
 	if (!debugging) { /* Abnormal conditions for tape */
 		if (!cmdstatp->have_sense)
@@ -386,20 +383,21 @@ static int st_chk_result(struct scsi_tape *STp, struct scsi_request * SRpnt)
 			 /* scode != UNIT_ATTENTION && */
 			 scode != BLANK_CHECK &&
 			 scode != VOLUME_OVERFLOW &&
-			 SRpnt->sr_cmnd[0] != MODE_SENSE &&
-			 SRpnt->sr_cmnd[0] != TEST_UNIT_READY) {
+			 SRpnt->cmd[0] != MODE_SENSE &&
+			 SRpnt->cmd[0] != TEST_UNIT_READY) {
 				printk(KERN_WARNING "%s: Error with sense data: ", name);
-				scsi_print_req_sense("st", SRpnt);
+				__scsi_print_sense("st", SRpnt->sense,
+						   SCSI_SENSE_BUFFERSIZE);
 		}
 	}
 
 	if (cmdstatp->fixed_format &&
 	    STp->cln_mode >= EXTENDED_SENSE_START) {  /* Only fixed format sense */
 		if (STp->cln_sense_value)
-			STp->cleaning_req |= ((SRpnt->sr_sense_buffer[STp->cln_mode] &
+			STp->cleaning_req |= ((SRpnt->sense[STp->cln_mode] &
 					       STp->cln_sense_mask) == STp->cln_sense_value);
 		else
-			STp->cleaning_req |= ((SRpnt->sr_sense_buffer[STp->cln_mode] &
+			STp->cleaning_req |= ((SRpnt->sense[STp->cln_mode] &
 					       STp->cln_sense_mask) != 0);
 	}
 	if (cmdstatp->have_sense &&
@@ -411,8 +409,8 @@ static int st_chk_result(struct scsi_tape *STp, struct scsi_request * SRpnt)
 	if (cmdstatp->have_sense &&
 	    scode == RECOVERED_ERROR
 #if ST_RECOVERED_WRITE_FATAL
-	    && SRpnt->sr_cmnd[0] != WRITE_6
-	    && SRpnt->sr_cmnd[0] != WRITE_FILEMARKS
+	    && SRpnt->cmd[0] != WRITE_6
+	    && SRpnt->cmd[0] != WRITE_FILEMARKS
 #endif
 	    ) {
 		STp->recover_count++;
@@ -420,9 +418,9 @@ static int st_chk_result(struct scsi_tape *STp, struct scsi_request * SRpnt)
 
                 DEB(
 		if (debugging) {
-			if (SRpnt->sr_cmnd[0] == READ_6)
+			if (SRpnt->cmd[0] == READ_6)
 				stp = "read";
-			else if (SRpnt->sr_cmnd[0] == WRITE_6)
+			else if (SRpnt->cmd[0] == WRITE_6)
 				stp = "write";
 			else
 				stp = "ioctl";
@@ -438,28 +436,37 @@ static int st_chk_result(struct scsi_tape *STp, struct scsi_request * SRpnt)
 
 
 /* Wakeup from interrupt */
-static void st_sleep_done(struct scsi_cmnd * SCpnt)
+static void st_sleep_done(void *data, char *sense, int result, int resid)
 {
-	struct scsi_tape *STp = container_of(SCpnt->request->rq_disk->private_data,
-					     struct scsi_tape, driver);
+	struct st_request *SRpnt = data;
+	struct scsi_tape *STp = SRpnt->stp;
 
-	(STp->buffer)->cmdstat.midlevel_result = SCpnt->result;
-	SCpnt->request->rq_status = RQ_SCSI_DONE;
+	memcpy(SRpnt->sense, sense, SCSI_SENSE_BUFFERSIZE);
+	(STp->buffer)->cmdstat.midlevel_result = SRpnt->result = result;
 	DEB( STp->write_pending = 0; )
 
-	if (SCpnt->request->waiting)
-		complete(SCpnt->request->waiting);
+	if (SRpnt->waiting)
+		complete(SRpnt->waiting);
+}
+
+static struct st_request *st_allocate_request(void)
+{
+	return kzalloc(sizeof(struct st_request), GFP_KERNEL);
+}
+
+static void st_release_request(struct st_request *streq)
+{
+	kfree(streq);
 }
 
 /* Do the scsi command. Waits until command performed if do_wait is true.
    Otherwise write_behind_check() is used to check that the command
    has finished. */
-static struct scsi_request *
-st_do_scsi(struct scsi_request * SRpnt, struct scsi_tape * STp, unsigned char *cmd,
+static struct st_request *
+st_do_scsi(struct st_request * SRpnt, struct scsi_tape * STp, unsigned char *cmd,
 	   int bytes, int direction, int timeout, int retries, int do_wait)
 {
 	struct completion *waiting;
-	unsigned char *bp;
 
 	/* if async, make sure there's no command outstanding */
 	if (!do_wait && ((STp->buffer)->last_SRpnt)) {
@@ -473,7 +480,7 @@ st_do_scsi(struct scsi_request * SRpnt, struct scsi_tape * STp, unsigned char *c
 	}
 
 	if (SRpnt == NULL) {
-		SRpnt = scsi_allocate_request(STp->device, GFP_ATOMIC);
+		SRpnt = st_allocate_request();
 		if (SRpnt == NULL) {
 			DEBC( printk(KERN_ERR "%s: Can't get SCSI request.\n",
 				     tape_name(STp)); );
@@ -483,6 +490,7 @@ st_do_scsi(struct scsi_request * SRpnt, struct scsi_tape * STp, unsigned char *c
 				(STp->buffer)->syscall_result = (-EBUSY);
 			return NULL;
 		}
+		SRpnt->stp = STp;
 	}
 
 	/* If async IO, set last_SRpnt. This ptr tells write_behind_check
@@ -492,32 +500,28 @@ st_do_scsi(struct scsi_request * SRpnt, struct scsi_tape * STp, unsigned char *c
 
 	waiting = &STp->wait;
 	init_completion(waiting);
-	SRpnt->sr_use_sg = STp->buffer->do_dio || (bytes > (STp->buffer)->frp[0].length);
-	if (SRpnt->sr_use_sg) {
-		if (!STp->buffer->do_dio)
-			buf_to_sg(STp->buffer, bytes);
-		SRpnt->sr_use_sg = (STp->buffer)->sg_segs;
-		bp = (char *) &((STp->buffer)->sg[0]);
-	} else
-		bp = (STp->buffer)->b_data;
-	SRpnt->sr_data_direction = direction;
-	SRpnt->sr_cmd_len = 0;
-	SRpnt->sr_request->waiting = waiting;
-	SRpnt->sr_request->rq_status = RQ_SCSI_BUSY;
-	SRpnt->sr_request->rq_disk = STp->disk;
-	SRpnt->sr_request->end_io = blk_end_sync_rq;
-	STp->buffer->cmdstat.have_sense = 0;
+	SRpnt->waiting = waiting;
 
-	scsi_do_req(SRpnt, (void *) cmd, bp, bytes,
-		    st_sleep_done, timeout, retries);
+	if (!STp->buffer->do_dio)
+		buf_to_sg(STp->buffer, bytes);
 
-	if (do_wait) {
+	memcpy(SRpnt->cmd, cmd, sizeof(SRpnt->cmd));
+	STp->buffer->cmdstat.have_sense = 0;
+	STp->buffer->syscall_result = 0;
+
+	if (scsi_execute_async(STp->device, cmd, direction,
+			&((STp->buffer)->sg[0]), bytes, (STp->buffer)->sg_segs,
+			       timeout, retries, SRpnt, st_sleep_done, GFP_KERNEL)) {
+		/* could not allocate the buffer or request was too large */
+		(STp->buffer)->syscall_result = (-EBUSY);
+		(STp->buffer)->last_SRpnt = NULL;
+	}
+	else if (do_wait) {
 		wait_for_completion(waiting);
-		SRpnt->sr_request->waiting = NULL;
-		if (SRpnt->sr_request->rq_status != RQ_SCSI_DONE)
-			SRpnt->sr_result |= (DRIVER_ERROR << 24);
+		SRpnt->waiting = NULL;
 		(STp->buffer)->syscall_result = st_chk_result(STp, SRpnt);
 	}
+
 	return SRpnt;
 }
 
@@ -532,7 +536,7 @@ static int write_behind_check(struct scsi_tape * STp)
 	struct st_buffer *STbuffer;
 	struct st_partstat *STps;
 	struct st_cmdstatus *cmdstatp;
-	struct scsi_request *SRpnt;
+	struct st_request *SRpnt;
 
 	STbuffer = STp->buffer;
 	if (!STbuffer->writing)
@@ -548,12 +552,10 @@ static int write_behind_check(struct scsi_tape * STp)
 	wait_for_completion(&(STp->wait));
 	SRpnt = STbuffer->last_SRpnt;
 	STbuffer->last_SRpnt = NULL;
-	SRpnt->sr_request->waiting = NULL;
-	if (SRpnt->sr_request->rq_status != RQ_SCSI_DONE)
-		SRpnt->sr_result |= (DRIVER_ERROR << 24);
+	SRpnt->waiting = NULL;
 
 	(STp->buffer)->syscall_result = st_chk_result(STp, SRpnt);
-	scsi_release_request(SRpnt);
+	st_release_request(SRpnt);
 
 	STbuffer->buffer_bytes -= STbuffer->writing;
 	STps = &(STp->ps[STp->partition]);
@@ -593,7 +595,7 @@ static int write_behind_check(struct scsi_tape * STp)
    it messes up the block number). */
 static int cross_eof(struct scsi_tape * STp, int forward)
 {
-	struct scsi_request *SRpnt;
+	struct st_request *SRpnt;
 	unsigned char cmd[MAX_COMMAND_SIZE];
 
 	cmd[0] = SPACE;
@@ -613,7 +615,7 @@ static int cross_eof(struct scsi_tape * STp, int forward)
 	if (!SRpnt)
 		return (STp->buffer)->syscall_result;
 
-	scsi_release_request(SRpnt);
+	st_release_request(SRpnt);
 	SRpnt = NULL;
 
 	if ((STp->buffer)->cmdstat.midlevel_result != 0)
@@ -630,7 +632,7 @@ static int flush_write_buffer(struct scsi_tape * STp)
 	int offset, transfer, blks;
 	int result;
 	unsigned char cmd[MAX_COMMAND_SIZE];
-	struct scsi_request *SRpnt;
+	struct st_request *SRpnt;
 	struct st_partstat *STps;
 
 	result = write_behind_check(STp);
@@ -688,7 +690,7 @@ static int flush_write_buffer(struct scsi_tape * STp)
 			STp->dirty = 0;
 			(STp->buffer)->buffer_bytes = 0;
 		}
-		scsi_release_request(SRpnt);
+		st_release_request(SRpnt);
 		SRpnt = NULL;
 	}
 	return result;
@@ -785,7 +787,7 @@ static int set_mode_densblk(struct scsi_tape * STp, struct st_modedef * STm)
 }
 
 
-/* Lock or unlock the drive door. Don't use when scsi_request allocated. */
+/* Lock or unlock the drive door. Don't use when st_request allocated. */
 static int do_door_lock(struct scsi_tape * STp, int do_lock)
 {
 	int retval, cmd;
@@ -844,7 +846,7 @@ static int test_ready(struct scsi_tape *STp, int do_wait)
 	int attentions, waits, max_wait, scode;
 	int retval = CHKRES_READY, new_session = 0;
 	unsigned char cmd[MAX_COMMAND_SIZE];
-	struct scsi_request *SRpnt = NULL;
+	struct st_request *SRpnt = NULL;
 	struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat;
 
 	max_wait = do_wait ? ST_BLOCK_SECONDS : 0;
@@ -903,7 +905,7 @@ static int test_ready(struct scsi_tape *STp, int do_wait)
 	}
 
 	if (SRpnt != NULL)
-		scsi_release_request(SRpnt);
+		st_release_request(SRpnt);
 	return retval;
 }
 
@@ -918,7 +920,7 @@ static int check_tape(struct scsi_tape *STp, struct file *filp)
 	int i, retval, new_session = 0, do_wait;
 	unsigned char cmd[MAX_COMMAND_SIZE], saved_cleaning;
 	unsigned short st_flags = filp->f_flags;
-	struct scsi_request *SRpnt = NULL;
+	struct st_request *SRpnt = NULL;
 	struct st_modedef *STm;
 	struct st_partstat *STps;
 	char *name = tape_name(STp);
@@ -993,7 +995,7 @@ static int check_tape(struct scsi_tape *STp, struct file *filp)
 			goto err_out;
 		}
 
-		if (!SRpnt->sr_result && !STp->buffer->cmdstat.have_sense) {
+		if (!SRpnt->result && !STp->buffer->cmdstat.have_sense) {
 			STp->max_block = ((STp->buffer)->b_data[1] << 16) |
 			    ((STp->buffer)->b_data[2] << 8) | (STp->buffer)->b_data[3];
 			STp->min_block = ((STp->buffer)->b_data[4] << 8) |
@@ -1045,7 +1047,7 @@ static int check_tape(struct scsi_tape *STp, struct file *filp)
 		}
 		STp->drv_write_prot = ((STp->buffer)->b_data[2] & 0x80) != 0;
 	}
-	scsi_release_request(SRpnt);
+	st_release_request(SRpnt);
 	SRpnt = NULL;
         STp->inited = 1;
 
@@ -1196,7 +1198,7 @@ static int st_flush(struct file *filp)
 {
 	int result = 0, result2;
 	unsigned char cmd[MAX_COMMAND_SIZE];
-	struct scsi_request *SRpnt;
+	struct st_request *SRpnt;
 	struct scsi_tape *STp = filp->private_data;
 	struct st_modedef *STm = &(STp->modes[STp->current_mode]);
 	struct st_partstat *STps = &(STp->ps[STp->partition]);
@@ -1249,7 +1251,7 @@ static int st_flush(struct file *filp)
 		      cmdstatp->sense_hdr.sense_key == RECOVERED_ERROR) &&
 		     (!cmdstatp->remainder_valid || cmdstatp->uremainder64 == 0))) {
 			/* Write successful at EOM */
-			scsi_release_request(SRpnt);
+			st_release_request(SRpnt);
 			SRpnt = NULL;
 			if (STps->drv_file >= 0)
 				STps->drv_file++;
@@ -1259,7 +1261,7 @@ static int st_flush(struct file *filp)
 			STps->eof = ST_FM;
 		}
 		else { /* Write error */
-			scsi_release_request(SRpnt);
+			st_release_request(SRpnt);
 			SRpnt = NULL;
 			printk(KERN_ERR "%s: Error on write filemark.\n", name);
 			if (result == 0)
@@ -1400,11 +1402,11 @@ static int setup_buffering(struct scsi_tape *STp, const char __user *buf,
 		i = STp->try_dio && try_rdio;
 	else
 		i = STp->try_dio && try_wdio;
+
 	if (i && ((unsigned long)buf & queue_dma_alignment(
 					STp->device->request_queue)) == 0) {
-		i = st_map_user_pages(&(STbp->sg[0]), STbp->use_sg,
-				      (unsigned long)buf, count, (is_read ? READ : WRITE),
-				      STp->max_pfn);
+		i = sgl_map_user_pages(&(STbp->sg[0]), STbp->use_sg,
+				      (unsigned long)buf, count, (is_read ? READ : WRITE));
 		if (i > 0) {
 			STbp->do_dio = i;
 			STbp->buffer_bytes = 0;   /* can be used as transfer counter */
@@ -1449,14 +1451,15 @@ static int setup_buffering(struct scsi_tape *STp, const char __user *buf,
 
 
 /* Can be called more than once after each setup_buffer() */
-static void release_buffering(struct scsi_tape *STp)
+static void release_buffering(struct scsi_tape *STp, int is_read)
 {
 	struct st_buffer *STbp;
 
 	STbp = STp->buffer;
 	if (STbp->do_dio) {
-		sgl_unmap_user_pages(&(STbp->sg[0]), STbp->do_dio, 0);
+		sgl_unmap_user_pages(&(STbp->sg[0]), STbp->do_dio, is_read);
 		STbp->do_dio = 0;
+		STbp->sg_segs = 0;
 	}
 }
 
@@ -1472,7 +1475,7 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
 	int async_write;
 	unsigned char cmd[MAX_COMMAND_SIZE];
 	const char __user *b_point;
-	struct scsi_request *SRpnt = NULL;
+	struct st_request *SRpnt = NULL;
 	struct scsi_tape *STp = filp->private_data;
 	struct st_modedef *STm;
 	struct st_partstat *STps;
@@ -1624,7 +1627,7 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
 			retval = STbp->syscall_result;
 			goto out;
 		}
-		if (async_write) {
+		if (async_write && !STbp->syscall_result) {
 			STbp->writing = transfer;
 			STp->dirty = !(STbp->writing ==
 				       STbp->buffer_bytes);
@@ -1698,7 +1701,7 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
 			} else {
 				count += do_count;
 				STps->drv_block = (-1);		/* Too cautious? */
-				retval = (-EIO);
+				retval = STbp->syscall_result;
 			}
 
 		}
@@ -1728,8 +1731,8 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
 
  out:
 	if (SRpnt != NULL)
-		scsi_release_request(SRpnt);
-	release_buffering(STp);
+		st_release_request(SRpnt);
+	release_buffering(STp, 0);
 	up(&STp->lock);
 
 	return retval;
@@ -1742,11 +1745,11 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
    Does release user buffer mapping if it is set.
 */
 static long read_tape(struct scsi_tape *STp, long count,
-		      struct scsi_request ** aSRpnt)
+		      struct st_request ** aSRpnt)
 {
 	int transfer, blks, bytes;
 	unsigned char cmd[MAX_COMMAND_SIZE];
-	struct scsi_request *SRpnt;
+	struct st_request *SRpnt;
 	struct st_modedef *STm;
 	struct st_partstat *STps;
 	struct st_buffer *STbp;
@@ -1787,7 +1790,7 @@ static long read_tape(struct scsi_tape *STp, long count,
 	SRpnt = *aSRpnt;
 	SRpnt = st_do_scsi(SRpnt, STp, cmd, bytes, DMA_FROM_DEVICE,
 			   STp->device->timeout, MAX_RETRIES, 1);
-	release_buffering(STp);
+	release_buffering(STp, 1);
 	*aSRpnt = SRpnt;
 	if (!SRpnt)
 		return STbp->syscall_result;
@@ -1802,10 +1805,10 @@ static long read_tape(struct scsi_tape *STp, long count,
 		retval = 1;
 		DEBC(printk(ST_DEB_MSG "%s: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",
                             name,
-                            SRpnt->sr_sense_buffer[0], SRpnt->sr_sense_buffer[1],
-                            SRpnt->sr_sense_buffer[2], SRpnt->sr_sense_buffer[3],
-                            SRpnt->sr_sense_buffer[4], SRpnt->sr_sense_buffer[5],
-                            SRpnt->sr_sense_buffer[6], SRpnt->sr_sense_buffer[7]));
+                            SRpnt->sense[0], SRpnt->sense[1],
+                            SRpnt->sense[2], SRpnt->sense[3],
+                            SRpnt->sense[4], SRpnt->sense[5],
+                            SRpnt->sense[6], SRpnt->sense[7]));
 		if (cmdstatp->have_sense) {
 
 			if (cmdstatp->sense_hdr.sense_key == BLANK_CHECK)
@@ -1835,7 +1838,7 @@ static long read_tape(struct scsi_tape *STp, long count,
 						}
 						STbp->buffer_bytes = bytes - transfer;
 					} else {
-						scsi_release_request(SRpnt);
+						st_release_request(SRpnt);
 						SRpnt = *aSRpnt = NULL;
 						if (transfer == blks) {	/* We did not get anything, error */
 							printk(KERN_NOTICE "%s: Incorrect block size.\n", name);
@@ -1929,7 +1932,7 @@ st_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos)
 	ssize_t retval = 0;
 	ssize_t i, transfer;
 	int special, do_dio = 0;
-	struct scsi_request *SRpnt = NULL;
+	struct st_request *SRpnt = NULL;
 	struct scsi_tape *STp = filp->private_data;
 	struct st_modedef *STm;
 	struct st_partstat *STps;
@@ -2054,11 +2057,11 @@ st_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos)
 
  out:
 	if (SRpnt != NULL) {
-		scsi_release_request(SRpnt);
+		st_release_request(SRpnt);
 		SRpnt = NULL;
 	}
 	if (do_dio) {
-		release_buffering(STp);
+		release_buffering(STp, 1);
 		STbp->buffer_bytes = 0;
 	}
 	up(&STp->lock);
@@ -2284,7 +2287,7 @@ static int st_set_options(struct scsi_tape *STp, long options)
 static int read_mode_page(struct scsi_tape *STp, int page, int omit_block_descs)
 {
 	unsigned char cmd[MAX_COMMAND_SIZE];
-	struct scsi_request *SRpnt = NULL;
+	struct st_request *SRpnt = NULL;
 
 	memset(cmd, 0, MAX_COMMAND_SIZE);
 	cmd[0] = MODE_SENSE;
@@ -2298,7 +2301,7 @@ static int read_mode_page(struct scsi_tape *STp, int page, int omit_block_descs)
 	if (SRpnt == NULL)
 		return (STp->buffer)->syscall_result;
 
-	scsi_release_request(SRpnt);
+	st_release_request(SRpnt);
 
 	return (STp->buffer)->syscall_result;
 }
@@ -2310,7 +2313,7 @@ static int write_mode_page(struct scsi_tape *STp, int page, int slow)
 {
 	int pgo;
 	unsigned char cmd[MAX_COMMAND_SIZE];
-	struct scsi_request *SRpnt = NULL;
+	struct st_request *SRpnt = NULL;
 
 	memset(cmd, 0, MAX_COMMAND_SIZE);
 	cmd[0] = MODE_SELECT;
@@ -2329,7 +2332,7 @@ static int write_mode_page(struct scsi_tape *STp, int page, int slow)
 	if (SRpnt == NULL)
 		return (STp->buffer)->syscall_result;
 
-	scsi_release_request(SRpnt);
+	st_release_request(SRpnt);
 
 	return (STp->buffer)->syscall_result;
 }
@@ -2412,7 +2415,7 @@ static int do_load_unload(struct scsi_tape *STp, struct file *filp, int load_cod
 	DEB( char *name = tape_name(STp); )
 	unsigned char cmd[MAX_COMMAND_SIZE];
 	struct st_partstat *STps;
-	struct scsi_request *SRpnt;
+	struct st_request *SRpnt;
 
 	if (STp->ready != ST_READY && !load_code) {
 		if (STp->ready == ST_NO_TAPE)
@@ -2455,7 +2458,7 @@ static int do_load_unload(struct scsi_tape *STp, struct file *filp, int load_cod
 		return (STp->buffer)->syscall_result;
 
 	retval = (STp->buffer)->syscall_result;
-	scsi_release_request(SRpnt);
+	st_release_request(SRpnt);
 
 	if (!retval) {	/* SCSI command successful */
 
@@ -2503,7 +2506,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon
 	int ioctl_result;
 	int chg_eof = 1;
 	unsigned char cmd[MAX_COMMAND_SIZE];
-	struct scsi_request *SRpnt;
+	struct st_request *SRpnt;
 	struct st_partstat *STps;
 	int fileno, blkno, at_sm, undone;
 	int datalen = 0, direction = DMA_NONE;
@@ -2757,7 +2760,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon
 	ioctl_result = (STp->buffer)->syscall_result;
 
 	if (!ioctl_result) {	/* SCSI command successful */
-		scsi_release_request(SRpnt);
+		st_release_request(SRpnt);
 		SRpnt = NULL;
 		STps->drv_block = blkno;
 		STps->drv_file = fileno;
@@ -2872,7 +2875,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon
 				/* Try the other possible state of Page Format if not
 				   already tried */
 				STp->use_pf = !STp->use_pf | PF_TESTED;
-				scsi_release_request(SRpnt);
+				st_release_request(SRpnt);
 				SRpnt = NULL;
 				return st_int_ioctl(STp, cmd_in, arg);
 			}
@@ -2882,7 +2885,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon
 		if (cmdstatp->sense_hdr.sense_key == BLANK_CHECK)
 			STps->eof = ST_EOD;
 
-		scsi_release_request(SRpnt);
+		st_release_request(SRpnt);
 		SRpnt = NULL;
 	}
 
@@ -2898,7 +2901,7 @@ static int get_location(struct scsi_tape *STp, unsigned int *block, int *partiti
 {
 	int result;
 	unsigned char scmd[MAX_COMMAND_SIZE];
-	struct scsi_request *SRpnt;
+	struct st_request *SRpnt;
 	DEB( char *name = tape_name(STp); )
 
 	if (STp->ready != ST_READY)
@@ -2944,7 +2947,7 @@ static int get_location(struct scsi_tape *STp, unsigned int *block, int *partiti
                 DEBC(printk(ST_DEB_MSG "%s: Got tape pos. blk %d part %d.\n", name,
                             *block, *partition));
 	}
-	scsi_release_request(SRpnt);
+	st_release_request(SRpnt);
 	SRpnt = NULL;
 
 	return result;
@@ -2961,7 +2964,7 @@ static int set_location(struct scsi_tape *STp, unsigned int block, int partition
 	unsigned int blk;
 	int timeout;
 	unsigned char scmd[MAX_COMMAND_SIZE];
-	struct scsi_request *SRpnt;
+	struct st_request *SRpnt;
 	DEB( char *name = tape_name(STp); )
 
 	if (STp->ready != ST_READY)
@@ -3047,7 +3050,7 @@ static int set_location(struct scsi_tape *STp, unsigned int block, int partition
 		result = 0;
 	}
 
-	scsi_release_request(SRpnt);
+	st_release_request(SRpnt);
 	SRpnt = NULL;
 
 	return result;
@@ -3577,7 +3580,7 @@ static long st_compat_ioctl(struct file *file, unsigned int cmd, unsigned long a
 static struct st_buffer *
  new_tape_buffer(int from_initialization, int need_dma, int max_sg)
 {
-	int i, got = 0, segs = 0;
+	int i, got = 0;
 	gfp_t priority;
 	struct st_buffer *tb;
 
@@ -3594,10 +3597,8 @@ static struct st_buffer *
 		return NULL;
 	}
 	memset(tb, 0, i);
-	tb->frp_segs = tb->orig_frp_segs = segs;
+	tb->frp_segs = tb->orig_frp_segs = 0;
 	tb->use_sg = max_sg;
-	if (segs > 0)
-		tb->b_data = page_address(tb->sg[0].page);
 	tb->frp = (struct st_buf_fragment *)(&(tb->sg[0]) + max_sg);
 
 	tb->in_use = 1;
@@ -3628,7 +3629,7 @@ static int enlarge_buffer(struct st_buffer * STbuffer, int new_size, int need_dm
 	priority = GFP_KERNEL | __GFP_NOWARN;
 	if (need_dma)
 		priority |= GFP_DMA;
-	for (b_size = PAGE_SIZE, order=0;
+	for (b_size = PAGE_SIZE, order=0; order <= 6 &&
 	     b_size < new_size - STbuffer->buffer_size;
 	     order++, b_size *= 2)
 		;  /* empty */
@@ -3670,6 +3671,7 @@ static void normalize_buffer(struct st_buffer * STbuffer)
 	}
 	STbuffer->frp_segs = STbuffer->orig_frp_segs;
 	STbuffer->frp_sg_current = 0;
+	STbuffer->sg_segs = 0;
 }
 
 
@@ -3882,7 +3884,6 @@ static int st_probe(struct device *dev)
 	struct st_buffer *buffer;
 	int i, j, mode, dev_num, error;
 	char *stp;
-	u64 bounce_limit;
 
 	if (SDp->type != TYPE_TAPE)
 		return -ENODEV;
@@ -3892,7 +3893,8 @@ static int st_probe(struct device *dev)
 		return -ENODEV;
 	}
 
-	i = SDp->host->sg_tablesize;
+	i = min(SDp->request_queue->max_hw_segments,
+		SDp->request_queue->max_phys_segments);
 	if (st_max_sg_segs < i)
 		i = st_max_sg_segs;
 	buffer = new_tape_buffer(1, (SDp->host)->unchecked_isa_dma, i);
@@ -3994,11 +3996,6 @@ static int st_probe(struct device *dev)
 	tpnt->long_timeout = ST_LONG_TIMEOUT;
 	tpnt->try_dio = try_direct_io && !SDp->host->unchecked_isa_dma;
 
-	bounce_limit = scsi_calculate_bounce_limit(SDp->host) >> PAGE_SHIFT;
-	if (bounce_limit > ULONG_MAX)
-		bounce_limit = ULONG_MAX;
-	tpnt->max_pfn = bounce_limit;
-
 	for (i = 0; i < ST_NBR_MODES; i++) {
 		STm = &(tpnt->modes[i]);
 		STm->defined = 0;
@@ -4077,9 +4074,9 @@ static int st_probe(struct device *dev)
 
 	sdev_printk(KERN_WARNING, SDp,
 		    "Attached scsi tape %s", tape_name(tpnt));
-	printk(KERN_WARNING "%s: try direct i/o: %s (alignment %d B), max page reachable by HBA %lu\n",
+	printk(KERN_WARNING "%s: try direct i/o: %s (alignment %d B)\n",
 	       tape_name(tpnt), tpnt->try_dio ? "yes" : "no",
-	       queue_dma_alignment(SDp->request_queue) + 1, tpnt->max_pfn);
+	       queue_dma_alignment(SDp->request_queue) + 1);
 
 	return 0;
 
@@ -4185,7 +4182,11 @@ static void scsi_tape_release(struct kref *kref)
 
 static void st_intr(struct scsi_cmnd *SCpnt)
 {
-	scsi_io_completion(SCpnt, (SCpnt->result ? 0: SCpnt->bufflen), 1);
+	/*
+	 * The caller should be checking the request's errors
+	 * value.
+	 */
+	scsi_io_completion(SCpnt, SCpnt->bufflen, 0);
 }
 
 /*
@@ -4197,7 +4198,7 @@ static int st_init_command(struct scsi_cmnd *SCpnt)
 	if (!(SCpnt->request->flags & REQ_BLOCK_PC))
 		return 0;
 
-	scsi_setup_blk_pc_cmnd(SCpnt, 0);
+	scsi_setup_blk_pc_cmnd(SCpnt);
 	SCpnt->done = st_intr;
 	return 1;
 }
@@ -4390,34 +4391,6 @@ static void do_create_class_files(struct scsi_tape *STp, int dev_num, int mode)
 	return;
 }
 
-
-/* Pin down user pages and put them into a scatter gather list. Returns <= 0 if
-   - mapping of all pages not successful
-   - any page is above max_pfn
-   (i.e., either completely successful or fails)
-*/
-static int st_map_user_pages(struct scatterlist *sgl, const unsigned int max_pages, 
-			     unsigned long uaddr, size_t count, int rw,
-			     unsigned long max_pfn)
-{
-	int i, nr_pages;
-
-	nr_pages = sgl_map_user_pages(sgl, max_pages, uaddr, count, rw);
-	if (nr_pages <= 0)
-		return nr_pages;
-
-	for (i=0; i < nr_pages; i++) {
-		if (page_to_pfn(sgl[i].page) > max_pfn)
-			goto out_unmap;
-	}
-	return nr_pages;
-
- out_unmap:
-	sgl_unmap_user_pages(sgl, nr_pages, 0);
-	return 0;
-}
-
-
 /* The following functions may be useful for a larger audience. */
 static int sgl_map_user_pages(struct scatterlist *sgl, const unsigned int max_pages, 
 			      unsigned long uaddr, size_t count, int rw)
diff --git a/drivers/scsi/st.h b/drivers/scsi/st.h
index 790acac160bc..411209048d74 100644
--- a/drivers/scsi/st.h
+++ b/drivers/scsi/st.h
@@ -4,6 +4,7 @@
 
 #include <linux/completion.h>
 #include <linux/kref.h>
+#include <scsi/scsi_cmnd.h>
 
 /* Descriptor for analyzed sense data */
 struct st_cmdstatus {
@@ -17,6 +18,17 @@ struct st_cmdstatus {
 	u8 deferred;
 };
 
+struct scsi_tape;
+
+/* scsi tape command */
+struct st_request {
+	unsigned char cmd[MAX_COMMAND_SIZE];
+	unsigned char sense[SCSI_SENSE_BUFFERSIZE];
+	int result;
+	struct scsi_tape *stp;
+	struct completion *waiting;
+};
+
 /* The tape buffer descriptor. */
 struct st_buffer {
 	unsigned char in_use;
@@ -28,7 +40,7 @@ struct st_buffer {
 	int read_pointer;
 	int writing;
 	int syscall_result;
-	struct scsi_request *last_SRpnt;
+	struct st_request *last_SRpnt;
 	struct st_cmdstatus cmdstat;
 	unsigned char *b_data;
 	unsigned short use_sg;	/* zero or max number of s/g segments for this adapter */
diff --git a/drivers/scsi/sun3_NCR5380.c b/drivers/scsi/sun3_NCR5380.c
index c041bfd56e12..25cced91c8a6 100644
--- a/drivers/scsi/sun3_NCR5380.c
+++ b/drivers/scsi/sun3_NCR5380.c
@@ -70,6 +70,7 @@
  *
  */
 #include <scsi/scsi_dbg.h>
+#include <scsi/scsi_transport_spi.h>
 
 /*
  * Further development / testing that should be done : 
@@ -2378,7 +2379,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance)
  * 3..length+1	arguments
  *
  * Start the extended message buffer with the EXTENDED_MESSAGE
- * byte, since scsi_print_msg() wants the whole thing.  
+ * byte, since spi_print_msg() wants the whole thing.  
  */
 		    extended_msg[0] = EXTENDED_MESSAGE;
 		    /* Accept first byte by clearing ACK */
@@ -2431,7 +2432,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance)
 		default:
 		    if (!tmp) {
 			printk(KERN_DEBUG "scsi%d: rejecting message ", HOSTNO);
-			scsi_print_msg (extended_msg);
+			spi_print_msg(extended_msg);
 			printk("\n");
 		    } else if (tmp != EXTENDED_MESSAGE)
 			printk(KERN_DEBUG "scsi%d: rejecting unknown "
@@ -2566,7 +2567,7 @@ static void NCR5380_reselect (struct Scsi_Host *instance)
 
     if (!(msg[0] & 0x80)) {
 	printk(KERN_DEBUG "scsi%d: expecting IDENTIFY message, got ", HOSTNO);
-	scsi_print_msg(msg);
+	spi_print_msg(msg);
 	do_abort(instance);
 	return;
     }
diff --git a/drivers/scsi/sym53c8xx_2/sym_defs.h b/drivers/scsi/sym53c8xx_2/sym_defs.h
index 2d9437d7242b..3659dd7b9d76 100644
--- a/drivers/scsi/sym53c8xx_2/sym_defs.h
+++ b/drivers/scsi/sym53c8xx_2/sym_defs.h
@@ -40,7 +40,7 @@
 #ifndef SYM_DEFS_H
 #define SYM_DEFS_H
 
-#define SYM_VERSION "2.2.1"
+#define SYM_VERSION "2.2.2"
 #define SYM_DRIVER_NAME	"sym-" SYM_VERSION
 
 /*
diff --git a/drivers/scsi/sym53c8xx_2/sym_fw.c b/drivers/scsi/sym53c8xx_2/sym_fw.c
index fd36cf9858cb..9916a2a22558 100644
--- a/drivers/scsi/sym53c8xx_2/sym_fw.c
+++ b/drivers/scsi/sym53c8xx_2/sym_fw.c
@@ -37,11 +37,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#ifdef __FreeBSD__
-#include <dev/sym/sym_glue.h>
-#else
 #include "sym_glue.h"
-#endif
 
 /*
  *  Macros used for all firmwares.
@@ -60,19 +56,12 @@
 #define	SYM_FWA_SCR		sym_fw1a_scr
 #define	SYM_FWB_SCR		sym_fw1b_scr
 #define	SYM_FWZ_SCR		sym_fw1z_scr
-#ifdef __FreeBSD__
-#include <dev/sym/sym_fw1.h>
-#else
 #include "sym_fw1.h"
-#endif
 static struct sym_fwa_ofs sym_fw1a_ofs = {
 	SYM_GEN_FW_A(struct SYM_FWA_SCR)
 };
 static struct sym_fwb_ofs sym_fw1b_ofs = {
 	SYM_GEN_FW_B(struct SYM_FWB_SCR)
-#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
-	SYM_GEN_B(struct SYM_FWB_SCR, data_io)
-#endif
 };
 static struct sym_fwz_ofs sym_fw1z_ofs = {
 	SYM_GEN_FW_Z(struct SYM_FWZ_SCR)
@@ -88,19 +77,12 @@ static struct sym_fwz_ofs sym_fw1z_ofs = {
 #define	SYM_FWA_SCR		sym_fw2a_scr
 #define	SYM_FWB_SCR		sym_fw2b_scr
 #define	SYM_FWZ_SCR		sym_fw2z_scr
-#ifdef __FreeBSD__
-#include <dev/sym/sym_fw2.h>
-#else
 #include "sym_fw2.h"
-#endif
 static struct sym_fwa_ofs sym_fw2a_ofs = {
 	SYM_GEN_FW_A(struct SYM_FWA_SCR)
 };
 static struct sym_fwb_ofs sym_fw2b_ofs = {
 	SYM_GEN_FW_B(struct SYM_FWB_SCR)
-#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
-	SYM_GEN_B(struct SYM_FWB_SCR, data_io)
-#endif
 	SYM_GEN_B(struct SYM_FWB_SCR, start64)
 	SYM_GEN_B(struct SYM_FWB_SCR, pm_handle)
 };
diff --git a/drivers/scsi/sym53c8xx_2/sym_fw.h b/drivers/scsi/sym53c8xx_2/sym_fw.h
index 43f6810a4045..66ec35beab5b 100644
--- a/drivers/scsi/sym53c8xx_2/sym_fw.h
+++ b/drivers/scsi/sym53c8xx_2/sym_fw.h
@@ -92,9 +92,6 @@ struct sym_fwa_ofs {
 };
 struct sym_fwb_ofs {
 	SYM_GEN_FW_B(u_short)
-#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
-	SYM_GEN_B(u_short, data_io)
-#endif
 	SYM_GEN_B(u_short, start64)
 	SYM_GEN_B(u_short, pm_handle)
 };
@@ -111,9 +108,6 @@ struct sym_fwa_ba {
 };
 struct sym_fwb_ba {
 	SYM_GEN_FW_B(u32)
-#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
-	SYM_GEN_B(u32, data_io)
-#endif
 	SYM_GEN_B(u32, start64);
 	SYM_GEN_B(u32, pm_handle);
 };
diff --git a/drivers/scsi/sym53c8xx_2/sym_fw1.h b/drivers/scsi/sym53c8xx_2/sym_fw1.h
index cdd92d82f4b2..7b39f4a35e98 100644
--- a/drivers/scsi/sym53c8xx_2/sym_fw1.h
+++ b/drivers/scsi/sym53c8xx_2/sym_fw1.h
@@ -197,12 +197,6 @@ struct SYM_FWB_SCR {
 	u32 bad_status		[  7];
 	u32 wsr_ma_helper	[  4];
 
-#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
-	/* Unknown direction handling */
-	u32 data_io		[  2];
-	u32 data_io_com		[  8];
-	u32 data_io_out		[  7];
-#endif
 	/* Data area */
 	u32 zero		[  1];
 	u32 scratch		[  1];
@@ -1747,48 +1741,6 @@ static struct SYM_FWB_SCR SYM_FWB_SCR = {
 	SCR_JUMP,
 		PADDR_A (dispatch),
 
-#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
-}/*-------------------------< DATA_IO >--------------------------*/,{
-	/*
-	 *  We jump here if the data direction was unknown at the 
-	 *  time we had to queue the command to the scripts processor.
-	 *  Pointers had been set as follow in this situation:
-	 *    savep   -->   DATA_IO
-	 *    lastp   -->   start pointer when DATA_IN
-	 *    wlastp  -->   start pointer when DATA_OUT
-	 *  This script sets savep and lastp according to the 
-	 *  direction chosen by the target.
-	 */
-	SCR_JUMP ^ IFTRUE (WHEN (SCR_DATA_OUT)),
-		PADDR_B (data_io_out),
-}/*-------------------------< DATA_IO_COM >----------------------*/,{
-	/*
-	 *  Direction is DATA IN.
-	 */
-	SCR_COPY  (4),
-		HADDR_1 (ccb_head.lastp),
-		HADDR_1 (ccb_head.savep),
-	/*
-	 *  Jump to the SCRIPTS according to actual direction.
-	 */
-	SCR_COPY  (4),
-		HADDR_1 (ccb_head.savep),
-		RADDR_1 (temp),
-	SCR_RETURN,
-		0,
-}/*-------------------------< DATA_IO_OUT >----------------------*/,{
-	/*
-	 *  Direction is DATA OUT.
-	 */
-	SCR_REG_REG (HF_REG, SCR_AND, (~HF_DATA_IN)),
-		0,
-	SCR_COPY  (4),
-		HADDR_1 (ccb_head.wlastp),
-		HADDR_1 (ccb_head.lastp),
-	SCR_JUMP,
-		PADDR_B(data_io_com),
-#endif /* SYM_OPT_HANDLE_DIR_UNKNOWN */
-
 }/*-------------------------< ZERO >-----------------------------*/,{
 	SCR_DATA_ZERO,
 }/*-------------------------< SCRATCH >--------------------------*/,{
diff --git a/drivers/scsi/sym53c8xx_2/sym_fw2.h b/drivers/scsi/sym53c8xx_2/sym_fw2.h
index 7ea7151f5d1d..851f2706f220 100644
--- a/drivers/scsi/sym53c8xx_2/sym_fw2.h
+++ b/drivers/scsi/sym53c8xx_2/sym_fw2.h
@@ -191,13 +191,6 @@ struct SYM_FWB_SCR {
 	u32 pm_wsr_handle	[ 38];
 	u32 wsr_ma_helper	[  4];
 
-#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
-	/* Unknown direction handling */
-	u32 data_io		[  2];
-	u32 data_io_in		[  2];
-	u32 data_io_com		[  6];
-	u32 data_io_out		[  8];
-#endif
 	/* Data area */
 	u32 zero		[  1];
 	u32 scratch		[  1];
@@ -1838,51 +1831,6 @@ static struct SYM_FWB_SCR SYM_FWB_SCR = {
 	SCR_JUMP,
 		PADDR_A (dispatch),
 
-#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
-}/*-------------------------< DATA_IO >--------------------------*/,{
-	/*
-	 *  We jump here if the data direction was unknown at the 
-	 *  time we had to queue the command to the scripts processor.
-	 *  Pointers had been set as follow in this situation:
-	 *    savep   -->   DATA_IO
-	 *    lastp   -->   start pointer when DATA_IN
-	 *    wlastp  -->   start pointer when DATA_OUT
-	 *  This script sets savep and lastp according to the 
-	 *  direction chosen by the target.
-	 */
-	SCR_JUMP ^ IFTRUE (WHEN (SCR_DATA_OUT)),
-		PADDR_B (data_io_out),
-}/*-------------------------< DATA_IO_IN >-----------------------*/,{
-	/*
-	 *  Direction is DATA IN.
-	 */
-	SCR_LOAD_REL  (scratcha, 4),
-		offsetof (struct sym_ccb, phys.head.lastp),
-}/*-------------------------< DATA_IO_COM >----------------------*/,{
-	SCR_STORE_REL (scratcha, 4),
-		offsetof (struct sym_ccb, phys.head.savep),
-
-	/*
-	 *  Jump to the SCRIPTS according to actual direction.
-	 */
-	SCR_LOAD_REL  (temp, 4),
-		offsetof (struct sym_ccb, phys.head.savep),
-	SCR_RETURN,
-		0,
-}/*-------------------------< DATA_IO_OUT >----------------------*/,{
-	/*
-	 *  Direction is DATA OUT.
-	 */
-	SCR_REG_REG (HF_REG, SCR_AND, (~HF_DATA_IN)),
-		0,
-	SCR_LOAD_REL  (scratcha, 4),
-		offsetof (struct sym_ccb, phys.head.wlastp),
-	SCR_STORE_REL (scratcha, 4),
-		offsetof (struct sym_ccb, phys.head.lastp),
-	SCR_JUMP,
-		PADDR_B(data_io_com),
-#endif /* SYM_OPT_HANDLE_DIR_UNKNOWN */
-
 }/*-------------------------< ZERO >-----------------------------*/,{
 	SCR_DATA_ZERO,
 }/*-------------------------< SCRATCH >--------------------------*/,{
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
index 7fc0b97173e1..1fffd2b3c654 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
@@ -514,9 +514,10 @@ static inline int sym_setup_cdb(struct sym_hcb *np, struct scsi_cmnd *cmd, struc
  */
 int sym_setup_data_and_start(struct sym_hcb *np, struct scsi_cmnd *cmd, struct sym_ccb *cp)
 {
-	int dir;
 	struct sym_tcb *tp = &np->target[cp->target];
 	struct sym_lcb *lp = sym_lp(tp, cp->lun);
+	u32 lastp, goalp;
+	int dir;
 
 	/*
 	 *  Build the CDB.
@@ -534,15 +535,47 @@ int sym_setup_data_and_start(struct sym_hcb *np, struct scsi_cmnd *cmd, struct s
 			sym_set_cam_status(cmd, DID_ERROR);
 			goto out_abort;
 		}
+
+		/*
+		 *  No segments means no data.
+		 */
+		if (!cp->segments)
+			dir = DMA_NONE;
 	} else {
 		cp->data_len = 0;
 		cp->segments = 0;
 	}
 
 	/*
-	 *  Set data pointers.
+	 *  Set the data pointer.
 	 */
-	sym_setup_data_pointers(np, cp, dir);
+	switch (dir) {
+	case DMA_BIDIRECTIONAL:
+		printk("%s: got DMA_BIDIRECTIONAL command", sym_name(np));
+		sym_set_cam_status(cmd, DID_ERROR);
+		goto out_abort;
+	case DMA_TO_DEVICE:
+		goalp = SCRIPTA_BA(np, data_out2) + 8;
+		lastp = goalp - 8 - (cp->segments * (2*4));
+		break;
+	case DMA_FROM_DEVICE:
+		cp->host_flags |= HF_DATA_IN;
+		goalp = SCRIPTA_BA(np, data_in2) + 8;
+		lastp = goalp - 8 - (cp->segments * (2*4));
+		break;
+	case DMA_NONE:
+	default:
+		lastp = goalp = SCRIPTB_BA(np, no_data);
+		break;
+	}
+
+	/*
+	 *  Set all pointers values needed by SCRIPTS.
+	 */
+	cp->phys.head.lastp = cpu_to_scr(lastp);
+	cp->phys.head.savep = cpu_to_scr(lastp);
+	cp->startp	    = cp->phys.head.savep;
+	cp->goalp	    = cpu_to_scr(goalp);
 
 	/*
 	 *  When `#ifed 1', the code below makes the driver 
@@ -563,10 +596,7 @@ int sym_setup_data_and_start(struct sym_hcb *np, struct scsi_cmnd *cmd, struct s
 	/*
 	 *	activate this job.
 	 */
-	if (lp)
-		sym_start_next_ccbs(np, lp, 2);
-	else
-		sym_put_start_queue(np, cp);
+	sym_start_next_ccbs(np, lp, 2);
 	return 0;
 
 out_abort:
@@ -981,15 +1011,14 @@ static int device_queue_depth(struct sym_hcb *np, int target, int lun)
 
 static int sym53c8xx_slave_alloc(struct scsi_device *sdev)
 {
-	struct sym_hcb *np;
-	struct sym_tcb *tp;
+	struct sym_hcb *np = sym_get_hcb(sdev->host);
+	struct sym_tcb *tp = &np->target[sdev->id];
+	struct sym_lcb *lp;
 
 	if (sdev->id >= SYM_CONF_MAX_TARGET || sdev->lun >= SYM_CONF_MAX_LUN)
 		return -ENXIO;
 
-	np = sym_get_hcb(sdev->host);
-	tp = &np->target[sdev->id];
-
+	tp->starget = sdev->sdev_target;
 	/*
 	 * Fail the device init if the device is flagged NOSCAN at BOOT in
 	 * the NVRAM.  This may speed up boot and maintain coherency with
@@ -999,35 +1028,41 @@ static int sym53c8xx_slave_alloc(struct scsi_device *sdev)
 	 * lun devices behave badly when asked for a non zero LUN.
 	 */
 
-	if ((tp->usrflags & SYM_SCAN_BOOT_DISABLED) ||
-	    ((tp->usrflags & SYM_SCAN_LUNS_DISABLED) && sdev->lun != 0)) {
+	if (tp->usrflags & SYM_SCAN_BOOT_DISABLED) {
 		tp->usrflags &= ~SYM_SCAN_BOOT_DISABLED;
+		starget_printk(KERN_INFO, tp->starget,
+				"Scan at boot disabled in NVRAM\n");
 		return -ENXIO;
 	}
 
-	tp->starget = sdev->sdev_target;
+	if (tp->usrflags & SYM_SCAN_LUNS_DISABLED) {
+		if (sdev->lun != 0)
+			return -ENXIO;
+		starget_printk(KERN_INFO, tp->starget,
+				"Multiple LUNs disabled in NVRAM\n");
+	}
+
+	lp = sym_alloc_lcb(np, sdev->id, sdev->lun);
+	if (!lp)
+		return -ENOMEM;
+
+	spi_min_period(tp->starget) = tp->usr_period;
+	spi_max_width(tp->starget) = tp->usr_width;
+
 	return 0;
 }
 
 /*
  * Linux entry point for device queue sizing.
  */
-static int sym53c8xx_slave_configure(struct scsi_device *device)
+static int sym53c8xx_slave_configure(struct scsi_device *sdev)
 {
-	struct sym_hcb *np = sym_get_hcb(device->host);
-	struct sym_tcb *tp = &np->target[device->id];
-	struct sym_lcb *lp;
+	struct sym_hcb *np = sym_get_hcb(sdev->host);
+	struct sym_tcb *tp = &np->target[sdev->id];
+	struct sym_lcb *lp = sym_lp(tp, sdev->lun);
 	int reqtags, depth_to_use;
 
 	/*
-	 *  Allocate the LCB if not yet.
-	 *  If it fail, we may well be in the sh*t. :)
-	 */
-	lp = sym_alloc_lcb(np, device->id, device->lun);
-	if (!lp)
-		return -ENOMEM;
-
-	/*
 	 *  Get user flags.
 	 */
 	lp->curr_flags = lp->user_flags;
@@ -1038,10 +1073,10 @@ static int sym53c8xx_slave_configure(struct scsi_device *device)
 	 *  Use at least 2.
 	 *  Donnot use more than our maximum.
 	 */
-	reqtags = device_queue_depth(np, device->id, device->lun);
+	reqtags = device_queue_depth(np, sdev->id, sdev->lun);
 	if (reqtags > tp->usrtags)
 		reqtags = tp->usrtags;
-	if (!device->tagged_supported)
+	if (!sdev->tagged_supported)
 		reqtags = 0;
 #if 1 /* Avoid to locally queue commands for no good reasons */
 	if (reqtags > SYM_CONF_MAX_TAG)
@@ -1050,19 +1085,30 @@ static int sym53c8xx_slave_configure(struct scsi_device *device)
 #else
 	depth_to_use = (reqtags ? SYM_CONF_MAX_TAG : 2);
 #endif
-	scsi_adjust_queue_depth(device,
-				(device->tagged_supported ?
+	scsi_adjust_queue_depth(sdev,
+				(sdev->tagged_supported ?
 				 MSG_SIMPLE_TAG : 0),
 				depth_to_use);
 	lp->s.scdev_depth = depth_to_use;
-	sym_tune_dev_queuing(tp, device->lun, reqtags);
+	sym_tune_dev_queuing(tp, sdev->lun, reqtags);
 
-	if (!spi_initial_dv(device->sdev_target))
-		spi_dv_device(device);
+	if (!spi_initial_dv(sdev->sdev_target))
+		spi_dv_device(sdev);
 
 	return 0;
 }
 
+static void sym53c8xx_slave_destroy(struct scsi_device *sdev)
+{
+	struct sym_hcb *np = sym_get_hcb(sdev->host);
+	struct sym_lcb *lp = sym_lp(&np->target[sdev->id], sdev->lun);
+
+	if (lp->itlq_tbl)
+		sym_mfree_dma(lp->itlq_tbl, SYM_CONF_MAX_TASK * 4, "ITLQ_TBL");
+	kfree(lp->cb_tags);
+	sym_mfree_dma(lp, sizeof(*lp), "LCB");
+}
+
 /*
  *  Linux entry point for info() function
  */
@@ -1497,7 +1543,7 @@ static int sym_setup_bus_dma_mask(struct sym_hcb *np)
 {
 #if SYM_CONF_DMA_ADDRESSING_MODE > 0
 #if   SYM_CONF_DMA_ADDRESSING_MODE == 1
-#define	DMA_DAC_MASK	0x000000ffffffffffULL /* 40-bit */
+#define	DMA_DAC_MASK	DMA_40BIT_MASK
 #elif SYM_CONF_DMA_ADDRESSING_MODE == 2
 #define	DMA_DAC_MASK	DMA_64BIT_MASK
 #endif
@@ -1926,6 +1972,7 @@ static struct scsi_host_template sym2_template = {
 	.queuecommand		= sym53c8xx_queue_command,
 	.slave_alloc		= sym53c8xx_slave_alloc,
 	.slave_configure	= sym53c8xx_slave_configure,
+	.slave_destroy		= sym53c8xx_slave_destroy,
 	.eh_abort_handler	= sym53c8xx_eh_abort_handler,
 	.eh_device_reset_handler = sym53c8xx_eh_device_reset_handler,
 	.eh_bus_reset_handler	= sym53c8xx_eh_bus_reset_handler,
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.h b/drivers/scsi/sym53c8xx_2/sym_glue.h
index d3d52f14d7c0..cc92d0c70cd7 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.h
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.h
@@ -68,7 +68,6 @@
  */
 #define	SYM_CONF_TIMER_INTERVAL		((HZ+1)/2)
 
-#define SYM_OPT_HANDLE_DIR_UNKNOWN
 #define SYM_OPT_HANDLE_DEVICE_QUEUEING
 #define SYM_OPT_LIMIT_COMMAND_REORDERING
 
@@ -268,6 +267,5 @@ void sym_xpt_async_bus_reset(struct sym_hcb *np);
 void sym_xpt_async_sent_bdr(struct sym_hcb *np, int target);
 int  sym_setup_data_and_start (struct sym_hcb *np, struct scsi_cmnd *csio, struct sym_ccb *cp);
 void sym_log_bus_error(struct sym_hcb *np);
-void sym_sniff_inquiry(struct sym_hcb *np, struct scsi_cmnd *cmd, int resid);
 
 #endif /* SYM_GLUE_H */
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c
index 1564ca203a3e..8260f040d39c 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.c
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c
@@ -40,6 +40,7 @@
 
 #include <linux/slab.h>
 #include <asm/param.h>		/* for timeouts in units of HZ */
+#include <scsi/scsi_dbg.h>
 
 #include "sym_glue.h"
 #include "sym_nvram.h"
@@ -70,32 +71,12 @@ static void sym_printl_hex(u_char *p, int n)
 	printf (".\n");
 }
 
-/*
- *  Print out the content of a SCSI message.
- */
-static int sym_show_msg (u_char * msg)
-{
-	u_char i;
-	printf ("%x",*msg);
-	if (*msg==M_EXTENDED) {
-		for (i=1;i<8;i++) {
-			if (i-1>msg[1]) break;
-			printf ("-%x",msg[i]);
-		}
-		return (i+1);
-	} else if ((*msg & 0xf0) == 0x20) {
-		printf ("-%x",msg[1]);
-		return (2);
-	}
-	return (1);
-}
-
 static void sym_print_msg(struct sym_ccb *cp, char *label, u_char *msg)
 {
 	sym_print_addr(cp->cmd, "%s: ", label);
 
-	sym_show_msg(msg);
-	printf(".\n");
+	spi_print_msg(msg);
+	printf("\n");
 }
 
 static void sym_print_nego_msg(struct sym_hcb *np, int target, char *label, u_char *msg)
@@ -103,8 +84,8 @@ static void sym_print_nego_msg(struct sym_hcb *np, int target, char *label, u_ch
 	struct sym_tcb *tp = &np->target[target];
 	dev_info(&tp->starget->dev, "%s: ", label);
 
-	sym_show_msg(msg);
-	printf(".\n");
+	spi_print_msg(msg);
+	printf("\n");
 }
 
 /*
@@ -635,29 +616,6 @@ static __inline void sym_init_burst(struct sym_hcb *np, u_char bc)
 	}
 }
 
-
-/*
- * Print out the list of targets that have some flag disabled by user.
- */
-static void sym_print_targets_flag(struct sym_hcb *np, int mask, char *msg)
-{
-	int cnt;
-	int i;
-
-	for (cnt = 0, i = 0 ; i < SYM_CONF_MAX_TARGET ; i++) {
-		if (i == np->myaddr)
-			continue;
-		if (np->target[i].usrflags & mask) {
-			if (!cnt++)
-				printf("%s: %s disabled for targets",
-					sym_name(np), msg);
-			printf(" %d", i);
-		}
-	}
-	if (cnt)
-		printf(".\n");
-}
-
 /*
  *  Save initial settings of some IO registers.
  *  Assumed to have been set by BIOS.
@@ -962,7 +920,7 @@ static int sym_prepare_setting(struct Scsi_Host *shost, struct sym_hcb *np, stru
 		tp->usrflags |= (SYM_DISC_ENABLED | SYM_TAGS_ENABLED);
 		tp->usrtags = SYM_SETUP_MAX_TAG;
 
-		sym_nvram_setup_target(np, i, nvram);
+		sym_nvram_setup_target(tp, i, nvram);
 
 		if (!tp->usrtags)
 			tp->usrflags &= ~SYM_TAGS_ENABLED;
@@ -1005,13 +963,6 @@ static int sym_prepare_setting(struct Scsi_Host *shost, struct sym_hcb *np, stru
 			sym_name(np), np->rv_scntl3, np->rv_dmode, np->rv_dcntl,
 			np->rv_ctest3, np->rv_ctest4, np->rv_ctest5);
 	}
-	/*
-	 *  Let user be aware of targets that have some disable flags set.
-	 */
-	sym_print_targets_flag(np, SYM_SCAN_BOOT_DISABLED, "SCAN AT BOOT");
-	if (sym_verbose)
-		sym_print_targets_flag(np, SYM_SCAN_LUNS_DISABLED,
-				       "SCAN FOR LUNS");
 
 	return 0;
 }
@@ -1523,7 +1474,7 @@ static int sym_prepare_nego(struct sym_hcb *np, struct sym_ccb *cp, u_char *msgp
 /*
  *  Insert a job into the start queue.
  */
-void sym_put_start_queue(struct sym_hcb *np, struct sym_ccb *cp)
+static void sym_put_start_queue(struct sym_hcb *np, struct sym_ccb *cp)
 {
 	u_short	qidx;
 
@@ -3654,7 +3605,7 @@ static int sym_evaluate_dp(struct sym_hcb *np, struct sym_ccb *cp, u32 scr, int
 	 *  If result is dp_sg = SYM_CONF_MAX_SG, then we are at the 
 	 *  end of the data.
 	 */
-	tmp = scr_to_cpu(sym_goalp(cp));
+	tmp = scr_to_cpu(cp->goalp);
 	dp_sg = SYM_CONF_MAX_SG;
 	if (dp_scr != tmp)
 		dp_sg -= (tmp - 8 - (int)dp_scr) / (2*4);
@@ -3761,7 +3712,7 @@ static void sym_modify_dp(struct sym_hcb *np, struct sym_tcb *tp, struct sym_ccb
 	 *  And our alchemy:) allows to easily calculate the data 
 	 *  script address we want to return for the next data phase.
 	 */
-	dp_ret = cpu_to_scr(sym_goalp(cp));
+	dp_ret = cpu_to_scr(cp->goalp);
 	dp_ret = dp_ret - 8 - (SYM_CONF_MAX_SG - dp_sg) * (2*4);
 
 	/*
@@ -3857,7 +3808,7 @@ int sym_compute_residual(struct sym_hcb *np, struct sym_ccb *cp)
 	 *  If all data has been transferred,
 	 *  there is no residual.
 	 */
-	if (cp->phys.head.lastp == sym_goalp(cp))
+	if (cp->phys.head.lastp == cp->goalp)
 		return resid;
 
 	/*
@@ -4664,30 +4615,7 @@ struct sym_ccb *sym_get_ccb (struct sym_hcb *np, struct scsi_cmnd *cmd, u_char t
 		goto out;
 	cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);
 
-#ifndef SYM_OPT_HANDLE_DEVICE_QUEUEING
-	/*
-	 *  If the LCB is not yet available and the LUN
-	 *  has been probed ok, try to allocate the LCB.
-	 */
-	if (!lp && sym_is_bit(tp->lun_map, ln)) {
-		lp = sym_alloc_lcb(np, tn, ln);
-		if (!lp)
-			goto out_free;
-	}
-#endif
-
-	/*
-	 *  If the LCB is not available here, then the 
-	 *  logical unit is not yet discovered. For those 
-	 *  ones only accept 1 SCSI IO per logical unit, 
-	 *  since we cannot allow disconnections.
-	 */
-	if (!lp) {
-		if (!sym_is_bit(tp->busy0_map, ln))
-			sym_set_bit(tp->busy0_map, ln);
-		else
-			goto out_free;
-	} else {
+	{
 		/*
 		 *  If we have been asked for a tagged command.
 		 */
@@ -4840,12 +4768,6 @@ void sym_free_ccb (struct sym_hcb *np, struct sym_ccb *cp)
 			lp->head.resel_sa =
 				cpu_to_scr(SCRIPTB_BA(np, resel_bad_lun));
 	}
-	/*
-	 *  Otherwise, we only accept 1 IO per LUN.
-	 *  Clear the bit that keeps track of this IO.
-	 */
-	else
-		sym_clr_bit(tp->busy0_map, cp->lun);
 
 	/*
 	 *  We donnot queue more than 1 ccb per target 
@@ -4997,20 +4919,7 @@ static void sym_init_tcb (struct sym_hcb *np, u_char tn)
 struct sym_lcb *sym_alloc_lcb (struct sym_hcb *np, u_char tn, u_char ln)
 {
 	struct sym_tcb *tp = &np->target[tn];
-	struct sym_lcb *lp = sym_lp(tp, ln);
-
-	/*
-	 *  Already done, just return.
-	 */
-	if (lp)
-		return lp;
-
-	/*
-	 *  Donnot allow LUN control block 
-	 *  allocation for not probed LUNs.
-	 */
-	if (!sym_is_bit(tp->lun_map, ln))
-		return NULL;
+	struct sym_lcb *lp = NULL;
 
 	/*
 	 *  Initialize the target control block if not yet.
@@ -5082,13 +4991,7 @@ struct sym_lcb *sym_alloc_lcb (struct sym_hcb *np, u_char tn, u_char ln)
 	lp->started_max   = SYM_CONF_MAX_TASK;
 	lp->started_limit = SYM_CONF_MAX_TASK;
 #endif
-	/*
-	 *  If we are busy, count the IO.
-	 */
-	if (sym_is_bit(tp->busy0_map, ln)) {
-		lp->busy_itl = 1;
-		sym_clr_bit(tp->busy0_map, ln);
-	}
+
 fail:
 	return lp;
 }
@@ -5103,12 +5006,6 @@ static void sym_alloc_lcb_tags (struct sym_hcb *np, u_char tn, u_char ln)
 	int i;
 
 	/*
-	 *  If LCB not available, try to allocate it.
-	 */
-	if (!lp && !(lp = sym_alloc_lcb(np, tn, ln)))
-		goto fail;
-
-	/*
 	 *  Allocate the task table and and the tag allocation 
 	 *  circular buffer. We want both or none.
 	 */
@@ -5481,8 +5378,7 @@ finish:
 	/*
 	 *  Donnot start more than 1 command after an error.
 	 */
-	if (lp)
-		sym_start_next_ccbs(np, lp, 1);
+	sym_start_next_ccbs(np, lp, 1);
 #endif
 }
 
@@ -5521,17 +5417,11 @@ void sym_complete_ok (struct sym_hcb *np, struct sym_ccb *cp)
 	lp = sym_lp(tp, cp->lun);
 
 	/*
-	 *  Assume device discovered on first success.
-	 */
-	if (!lp)
-		sym_set_bit(tp->lun_map, cp->lun);
-
-	/*
 	 *  If all data have been transferred, given than no
 	 *  extended error did occur, there is no residual.
 	 */
 	resid = 0;
-	if (cp->phys.head.lastp != sym_goalp(cp))
+	if (cp->phys.head.lastp != cp->goalp)
 		resid = sym_compute_residual(np, cp);
 
 	/*
@@ -5551,15 +5441,6 @@ if (resid)
 	 */
 	sym_set_cam_result_ok(cp, cmd, resid);
 
-#ifdef	SYM_OPT_SNIFF_INQUIRY
-	/*
-	 *  On standard INQUIRY response (EVPD and CmDt 
-	 *  not set), sniff out device capabilities.
-	 */
-	if (cp->cdb_buf[0] == INQUIRY && !(cp->cdb_buf[1] & 0x3))
-		sym_sniff_inquiry(np, cmd, resid);
-#endif
-
 #ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
 	/*
 	 *  If max number of started ccbs had been reduced,
@@ -5587,7 +5468,7 @@ if (resid)
 	/*
 	 *  Requeue a couple of awaiting scsi commands.
 	 */
-	if (lp && !sym_que_empty(&lp->waiting_ccbq))
+	if (!sym_que_empty(&lp->waiting_ccbq))
 		sym_start_next_ccbs(np, lp, 2);
 #endif
 	/*
@@ -5830,8 +5711,7 @@ void sym_hcb_free(struct sym_hcb *np)
 	SYM_QUEHEAD *qp;
 	struct sym_ccb *cp;
 	struct sym_tcb *tp;
-	struct sym_lcb *lp;
-	int target, lun;
+	int target;
 
 	if (np->scriptz0)
 		sym_mfree_dma(np->scriptz0, np->scriptz_sz, "SCRIPTZ0");
@@ -5857,16 +5737,6 @@ void sym_hcb_free(struct sym_hcb *np)
 
 	for (target = 0; target < SYM_CONF_MAX_TARGET ; target++) {
 		tp = &np->target[target];
-		for (lun = 0 ; lun < SYM_CONF_MAX_LUN ; lun++) {
-			lp = sym_lp(tp, lun);
-			if (!lp)
-				continue;
-			if (lp->itlq_tbl)
-				sym_mfree_dma(lp->itlq_tbl, SYM_CONF_MAX_TASK*4,
-				       "ITLQ_TBL");
-			kfree(lp->cb_tags);
-			sym_mfree_dma(lp, sizeof(*lp), "LCB");
-		}
 #if SYM_CONF_MAX_LUN > 1
 		kfree(tp->lunmp);
 #endif 
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.h b/drivers/scsi/sym53c8xx_2/sym_hipd.h
index 3a264a408216..2456090bb241 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.h
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.h
@@ -48,12 +48,6 @@
  *  They may be defined in platform specific headers, if they 
  *  are useful.
  *
- *    SYM_OPT_HANDLE_DIR_UNKNOWN
- *        When this option is set, the SCRIPTS used by the driver 
- *        are able to handle SCSI transfers with direction not 
- *        supplied by user.
- *        (set for Linux-2.0.X)
- *
  *    SYM_OPT_HANDLE_DEVICE_QUEUEING
  *        When this option is set, the driver will use a queue per 
  *        device and handle QUEUE FULL status requeuing internally.
@@ -64,7 +58,6 @@
  *        (set for Linux)
  */
 #if 0
-#define SYM_OPT_HANDLE_DIR_UNKNOWN
 #define SYM_OPT_HANDLE_DEVICE_QUEUEING
 #define SYM_OPT_LIMIT_COMMAND_REORDERING
 #endif
@@ -416,19 +409,6 @@ struct sym_tcb {
 	struct sym_lcb **lunmp;		/* Other LCBs [1..MAX_LUN]	*/
 #endif
 
-	/*
-	 *  Bitmap that tells about LUNs that succeeded at least 
-	 *  1 IO and therefore assumed to be a real device.
-	 *  Avoid useless allocation of the LCB structure.
-	 */
-	u32	lun_map[(SYM_CONF_MAX_LUN+31)/32];
-
-	/*
-	 *  Bitmap that tells about LUNs that haven't yet an LCB 
-	 *  allocated (not discovered or LCB allocation failed).
-	 */
-	u32	busy0_map[(SYM_CONF_MAX_LUN+31)/32];
-
 #ifdef	SYM_HAVE_STCB
 	/*
 	 *  O/S specific data structure.
@@ -454,8 +434,10 @@ struct sym_tcb {
 	 *  Other user settable limits and options.
 	 *  These limits are read from the NVRAM if present.
 	 */
-	u_char	usrflags;
-	u_short	usrtags;
+	unsigned char	usrflags;
+	unsigned char	usr_period;
+	unsigned char	usr_width;
+	unsigned short	usrtags;
 	struct scsi_target *starget;
 };
 
@@ -672,9 +654,6 @@ struct sym_ccbh {
 	 */
 	u32	savep;		/* Jump address to saved data pointer	*/
 	u32	lastp;		/* SCRIPTS address at end of data	*/
-#ifdef	SYM_OPT_HANDLE_DIR_UNKNOWN
-	u32	wlastp;
-#endif
 
 	/*
 	 *  Status fields.
@@ -804,9 +783,6 @@ struct sym_ccb {
 	SYM_QUEHEAD link_ccbq;	/* Link to free/busy CCB queue	*/
 	u32	startp;		/* Initial data pointer		*/
 	u32	goalp;		/* Expected last data pointer	*/
-#ifdef	SYM_OPT_HANDLE_DIR_UNKNOWN
-	u32	wgoalp;
-#endif
 	int	ext_sg;		/* Extreme data pointer, used	*/
 	int	ext_ofs;	/*  to calculate the residual.	*/
 #ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
@@ -821,12 +797,6 @@ struct sym_ccb {
 
 #define CCB_BA(cp,lbl)	cpu_to_scr(cp->ccb_ba + offsetof(struct sym_ccb, lbl))
 
-#ifdef	SYM_OPT_HANDLE_DIR_UNKNOWN
-#define	sym_goalp(cp) ((cp->host_flags & HF_DATA_IN) ? cp->goalp : cp->wgoalp)
-#else
-#define	sym_goalp(cp) (cp->goalp)
-#endif
-
 typedef struct device *m_pool_ident_t;
 
 /*
@@ -1077,7 +1047,6 @@ char *sym_driver_name(void);
 void sym_print_xerr(struct scsi_cmnd *cmd, int x_status);
 int sym_reset_scsi_bus(struct sym_hcb *np, int enab_int);
 struct sym_chip *sym_lookup_chip_table(u_short device_id, u_char revision);
-void sym_put_start_queue(struct sym_hcb *np, struct sym_ccb *cp);
 #ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
 void sym_start_next_ccbs(struct sym_hcb *np, struct sym_lcb *lp, int maxn);
 #endif
@@ -1136,71 +1105,6 @@ bad:
 #endif
 
 /*
- *  Set up data pointers used by SCRIPTS.
- *  Called from O/S specific code.
- */
-static inline void sym_setup_data_pointers(struct sym_hcb *np,
-		struct sym_ccb *cp, int dir)
-{
-	u32 lastp, goalp;
-
-	/*
-	 *  No segments means no data.
-	 */
-	if (!cp->segments)
-		dir = DMA_NONE;
-
-	/*
-	 *  Set the data pointer.
-	 */
-	switch(dir) {
-#ifdef	SYM_OPT_HANDLE_DIR_UNKNOWN
-	case DMA_BIDIRECTIONAL:
-#endif
-	case DMA_TO_DEVICE:
-		goalp = SCRIPTA_BA(np, data_out2) + 8;
-		lastp = goalp - 8 - (cp->segments * (2*4));
-#ifdef	SYM_OPT_HANDLE_DIR_UNKNOWN
-		cp->wgoalp = cpu_to_scr(goalp);
-		if (dir != DMA_BIDIRECTIONAL)
-			break;
-		cp->phys.head.wlastp = cpu_to_scr(lastp);
-		/* fall through */
-#else
-		break;
-#endif
-	case DMA_FROM_DEVICE:
-		cp->host_flags |= HF_DATA_IN;
-		goalp = SCRIPTA_BA(np, data_in2) + 8;
-		lastp = goalp - 8 - (cp->segments * (2*4));
-		break;
-	case DMA_NONE:
-	default:
-#ifdef	SYM_OPT_HANDLE_DIR_UNKNOWN
-		cp->host_flags |= HF_DATA_IN;
-#endif
-		lastp = goalp = SCRIPTB_BA(np, no_data);
-		break;
-	}
-
-	/*
-	 *  Set all pointers values needed by SCRIPTS.
-	 */
-	cp->phys.head.lastp = cpu_to_scr(lastp);
-	cp->phys.head.savep = cpu_to_scr(lastp);
-	cp->startp	    = cp->phys.head.savep;
-	cp->goalp	    = cpu_to_scr(goalp);
-
-#ifdef	SYM_OPT_HANDLE_DIR_UNKNOWN
-	/*
-	 *  If direction is unknown, start at data_io.
-	 */
-	if (dir == DMA_BIDIRECTIONAL)
-		cp->phys.head.savep = cpu_to_scr(SCRIPTB_BA(np, data_io));
-#endif
-}
-
-/*
  *  MEMORY ALLOCATOR.
  */
 
diff --git a/drivers/scsi/sym53c8xx_2/sym_malloc.c b/drivers/scsi/sym53c8xx_2/sym_malloc.c
index a34d403ccc6c..92bf9b14a7a2 100644
--- a/drivers/scsi/sym53c8xx_2/sym_malloc.c
+++ b/drivers/scsi/sym53c8xx_2/sym_malloc.c
@@ -37,11 +37,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#ifdef __FreeBSD__
-#include <dev/sym/sym_glue.h>
-#else
 #include "sym_glue.h"
-#endif
 
 /*
  *  Simple power of two buddy-like generic allocator.
diff --git a/drivers/scsi/sym53c8xx_2/sym_nvram.c b/drivers/scsi/sym53c8xx_2/sym_nvram.c
index 994b7566bcac..15d69298ab6e 100644
--- a/drivers/scsi/sym53c8xx_2/sym_nvram.c
+++ b/drivers/scsi/sym53c8xx_2/sym_nvram.c
@@ -92,29 +92,32 @@ void sym_nvram_setup_host(struct Scsi_Host *shost, struct sym_hcb *np, struct sy
  *  Get target set-up from Symbios format NVRAM.
  */
 static void
-sym_Symbios_setup_target(struct sym_hcb *np, int target, Symbios_nvram *nvram)
+sym_Symbios_setup_target(struct sym_tcb *tp, int target, Symbios_nvram *nvram)
 {
-	struct sym_tcb *tp = &np->target[target];
 	Symbios_target *tn = &nvram->target[target];
 
-	tp->usrtags =
-		(tn->flags & SYMBIOS_QUEUE_TAGS_ENABLED)? SYM_SETUP_MAX_TAG : 0;
-
+	if (!(tn->flags & SYMBIOS_QUEUE_TAGS_ENABLED))
+		tp->usrtags = 0;
 	if (!(tn->flags & SYMBIOS_DISCONNECT_ENABLE))
 		tp->usrflags &= ~SYM_DISC_ENABLED;
 	if (!(tn->flags & SYMBIOS_SCAN_AT_BOOT_TIME))
 		tp->usrflags |= SYM_SCAN_BOOT_DISABLED;
 	if (!(tn->flags & SYMBIOS_SCAN_LUNS))
 		tp->usrflags |= SYM_SCAN_LUNS_DISABLED;
+	tp->usr_period = (tn->sync_period + 3) / 4;
+	tp->usr_width = (tn->bus_width == 0x8) ? 0 : 1;
 }
 
+static const unsigned char Tekram_sync[16] = {
+	25, 31, 37, 43, 50, 62, 75, 125, 12, 15, 18, 21, 6, 7, 9, 10
+};
+
 /*
  *  Get target set-up from Tekram format NVRAM.
  */
 static void
-sym_Tekram_setup_target(struct sym_hcb *np, int target, Tekram_nvram *nvram)
+sym_Tekram_setup_target(struct sym_tcb *tp, int target, Tekram_nvram *nvram)
 {
-	struct sym_tcb *tp = &np->target[target];
 	struct Tekram_target *tn = &nvram->target[target];
 
 	if (tn->flags & TEKRAM_TAGGED_COMMANDS) {
@@ -124,22 +127,22 @@ sym_Tekram_setup_target(struct sym_hcb *np, int target, Tekram_nvram *nvram)
 	if (tn->flags & TEKRAM_DISCONNECT_ENABLE)
 		tp->usrflags |= SYM_DISC_ENABLED;
  
-	/* If any device does not support parity, we will not use this option */
-	if (!(tn->flags & TEKRAM_PARITY_CHECK))
-		np->rv_scntl0  &= ~0x0a; /* SCSI parity checking disabled */
+	if (tn->flags & TEKRAM_SYNC_NEGO)
+		tp->usr_period = Tekram_sync[tn->sync_index & 0xf];
+	tp->usr_width = (tn->flags & TEKRAM_WIDE_NEGO) ? 1 : 0;
 }
 
 /*
  *  Get target setup from NVRAM.
  */
-void sym_nvram_setup_target(struct sym_hcb *np, int target, struct sym_nvram *nvp)
+void sym_nvram_setup_target(struct sym_tcb *tp, int target, struct sym_nvram *nvp)
 {
 	switch (nvp->type) {
 	case SYM_SYMBIOS_NVRAM:
-		sym_Symbios_setup_target(np, target, &nvp->data.Symbios);
+		sym_Symbios_setup_target(tp, target, &nvp->data.Symbios);
 		break;
 	case SYM_TEKRAM_NVRAM:
-		sym_Tekram_setup_target(np, target, &nvp->data.Tekram);
+		sym_Tekram_setup_target(tp, target, &nvp->data.Tekram);
 		break;
 	default:
 		break;
diff --git a/drivers/scsi/sym53c8xx_2/sym_nvram.h b/drivers/scsi/sym53c8xx_2/sym_nvram.h
index 1538bede5277..bdfbbb083b69 100644
--- a/drivers/scsi/sym53c8xx_2/sym_nvram.h
+++ b/drivers/scsi/sym53c8xx_2/sym_nvram.h
@@ -194,12 +194,12 @@ struct sym_nvram {
 
 #if SYM_CONF_NVRAM_SUPPORT
 void sym_nvram_setup_host(struct Scsi_Host *shost, struct sym_hcb *np, struct sym_nvram *nvram);
-void sym_nvram_setup_target (struct sym_hcb *np, int target, struct sym_nvram *nvp);
+void sym_nvram_setup_target (struct sym_tcb *tp, int target, struct sym_nvram *nvp);
 int sym_read_nvram (struct sym_device *np, struct sym_nvram *nvp);
 char *sym_nvram_type(struct sym_nvram *nvp);
 #else
 static inline void sym_nvram_setup_host(struct Scsi_Host *shost, struct sym_hcb *np, struct sym_nvram *nvram) { }
-static inline void sym_nvram_setup_target(struct sym_hcb *np, struct sym_nvram *nvram) { }
+static inline void sym_nvram_setup_target(struct sym_tcb *tp, struct sym_nvram *nvram) { }
 static inline int sym_read_nvram(struct sym_device *np, struct sym_nvram *nvp)
 {
 	nvp->type = 0;
diff --git a/drivers/scsi/sym53c8xx_comm.h b/drivers/scsi/sym53c8xx_comm.h
deleted file mode 100644
index 20ae2b17df58..000000000000
--- a/drivers/scsi/sym53c8xx_comm.h
+++ /dev/null
@@ -1,792 +0,0 @@
-/******************************************************************************
-**  High Performance device driver for the Symbios 53C896 controller.
-**
-**  Copyright (C) 1998-2001  Gerard Roudier <groudier@free.fr>
-**
-**  This driver also supports all the Symbios 53C8XX controller family, 
-**  except 53C810 revisions < 16, 53C825 revisions < 16 and all 
-**  revisions of 53C815 controllers.
-**
-**  This driver is based on the Linux port of the FreeBSD ncr driver.
-** 
-**  Copyright (C) 1994  Wolfgang Stanglmeier
-**  
-**-----------------------------------------------------------------------------
-**  
-**  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.
-**
-**-----------------------------------------------------------------------------
-**
-**  The Linux port of the FreeBSD ncr driver has been achieved in 
-**  november 1995 by:
-**
-**          Gerard Roudier              <groudier@free.fr>
-**
-**  Being given that this driver originates from the FreeBSD version, and
-**  in order to keep synergy on both, any suggested enhancements and corrections
-**  received on Linux are automatically a potential candidate for the FreeBSD 
-**  version.
-**
-**  The original driver has been written for 386bsd and FreeBSD by
-**          Wolfgang Stanglmeier        <wolf@cologne.de>
-**          Stefan Esser                <se@mi.Uni-Koeln.de>
-**
-**-----------------------------------------------------------------------------
-**
-**  Major contributions:
-**  --------------------
-**
-**  NVRAM detection and reading.
-**    Copyright (C) 1997 Richard Waltham <dormouse@farsrobt.demon.co.uk>
-**
-*******************************************************************************
-*/
-
-/*==========================================================
-**
-**	Debugging tags
-**
-**==========================================================
-*/
-
-#define DEBUG_ALLOC    (0x0001)
-#define DEBUG_PHASE    (0x0002)
-#define DEBUG_QUEUE    (0x0008)
-#define DEBUG_RESULT   (0x0010)
-#define DEBUG_POINTER  (0x0020)
-#define DEBUG_SCRIPT   (0x0040)
-#define DEBUG_TINY     (0x0080)
-#define DEBUG_TIMING   (0x0100)
-#define DEBUG_NEGO     (0x0200)
-#define DEBUG_TAGS     (0x0400)
-#define DEBUG_SCATTER  (0x0800)
-#define DEBUG_IC        (0x1000)
-
-/*
-**    Enable/Disable debug messages.
-**    Can be changed at runtime too.
-*/
-
-#ifdef SCSI_NCR_DEBUG_INFO_SUPPORT
-static int ncr_debug = SCSI_NCR_DEBUG_FLAGS;
-	#define DEBUG_FLAGS ncr_debug
-#else
-	#define DEBUG_FLAGS	SCSI_NCR_DEBUG_FLAGS
-#endif
-
-static inline struct list_head *ncr_list_pop(struct list_head *head)
-{
-	if (!list_empty(head)) {
-		struct list_head *elem = head->next;
-
-		list_del(elem);
-		return elem;
-	}
-
-	return NULL;
-}
-
-#ifdef __sparc__
-#include <asm/irq.h>
-#endif
-
-/*==========================================================
-**
-**	Simple power of two buddy-like allocator.
-**
-**	This simple code is not intended to be fast, but to 
-**	provide power of 2 aligned memory allocations.
-**	Since the SCRIPTS processor only supplies 8 bit 
-**	arithmetic, this allocator allows simple and fast 
-**	address calculations  from the SCRIPTS code.
-**	In addition, cache line alignment is guaranteed for 
-**	power of 2 cache line size.
-**	Enhanced in linux-2.3.44 to provide a memory pool 
-**	per pcidev to support dynamic dma mapping. (I would 
-**	have preferred a real bus astraction, btw).
-**
-**==========================================================
-*/
-
-#define MEMO_SHIFT	4	/* 16 bytes minimum memory chunk */
-#if PAGE_SIZE >= 8192
-#define MEMO_PAGE_ORDER	0	/* 1 PAGE  maximum */
-#else
-#define MEMO_PAGE_ORDER	1	/* 2 PAGES maximum */
-#endif
-#define MEMO_FREE_UNUSED	/* Free unused pages immediately */
-#define MEMO_WARN	1
-#define MEMO_GFP_FLAGS	GFP_ATOMIC
-#define MEMO_CLUSTER_SHIFT	(PAGE_SHIFT+MEMO_PAGE_ORDER)
-#define MEMO_CLUSTER_SIZE	(1UL << MEMO_CLUSTER_SHIFT)
-#define MEMO_CLUSTER_MASK	(MEMO_CLUSTER_SIZE-1)
-
-typedef u_long m_addr_t;	/* Enough bits to bit-hack addresses */
-typedef struct device *m_bush_t;	/* Something that addresses DMAable */
-
-typedef struct m_link {		/* Link between free memory chunks */
-	struct m_link *next;
-} m_link_s;
-
-typedef struct m_vtob {		/* Virtual to Bus address translation */
-	struct m_vtob *next;
-	m_addr_t vaddr;
-	m_addr_t baddr;
-} m_vtob_s;
-#define VTOB_HASH_SHIFT		5
-#define VTOB_HASH_SIZE		(1UL << VTOB_HASH_SHIFT)
-#define VTOB_HASH_MASK		(VTOB_HASH_SIZE-1)
-#define VTOB_HASH_CODE(m)	\
-	((((m_addr_t) (m)) >> MEMO_CLUSTER_SHIFT) & VTOB_HASH_MASK)
-
-typedef struct m_pool {		/* Memory pool of a given kind */
-	m_bush_t bush;
-	m_addr_t (*getp)(struct m_pool *);
-	void (*freep)(struct m_pool *, m_addr_t);
-	int nump;
-	m_vtob_s *(vtob[VTOB_HASH_SIZE]);
-	struct m_pool *next;
-	struct m_link h[PAGE_SHIFT-MEMO_SHIFT+MEMO_PAGE_ORDER+1];
-} m_pool_s;
-
-static void *___m_alloc(m_pool_s *mp, int size)
-{
-	int i = 0;
-	int s = (1 << MEMO_SHIFT);
-	int j;
-	m_addr_t a;
-	m_link_s *h = mp->h;
-
-	if (size > (PAGE_SIZE << MEMO_PAGE_ORDER))
-		return NULL;
-
-	while (size > s) {
-		s <<= 1;
-		++i;
-	}
-
-	j = i;
-	while (!h[j].next) {
-		if (s == (PAGE_SIZE << MEMO_PAGE_ORDER)) {
-			h[j].next = (m_link_s *)mp->getp(mp);
-			if (h[j].next)
-				h[j].next->next = NULL;
-			break;
-		}
-		++j;
-		s <<= 1;
-	}
-	a = (m_addr_t) h[j].next;
-	if (a) {
-		h[j].next = h[j].next->next;
-		while (j > i) {
-			j -= 1;
-			s >>= 1;
-			h[j].next = (m_link_s *) (a+s);
-			h[j].next->next = NULL;
-		}
-	}
-#ifdef DEBUG
-	printk("___m_alloc(%d) = %p\n", size, (void *) a);
-#endif
-	return (void *) a;
-}
-
-static void ___m_free(m_pool_s *mp, void *ptr, int size)
-{
-	int i = 0;
-	int s = (1 << MEMO_SHIFT);
-	m_link_s *q;
-	m_addr_t a, b;
-	m_link_s *h = mp->h;
-
-#ifdef DEBUG
-	printk("___m_free(%p, %d)\n", ptr, size);
-#endif
-
-	if (size > (PAGE_SIZE << MEMO_PAGE_ORDER))
-		return;
-
-	while (size > s) {
-		s <<= 1;
-		++i;
-	}
-
-	a = (m_addr_t) ptr;
-
-	while (1) {
-#ifdef MEMO_FREE_UNUSED
-		if (s == (PAGE_SIZE << MEMO_PAGE_ORDER)) {
-			mp->freep(mp, a);
-			break;
-		}
-#endif
-		b = a ^ s;
-		q = &h[i];
-		while (q->next && q->next != (m_link_s *) b) {
-			q = q->next;
-		}
-		if (!q->next) {
-			((m_link_s *) a)->next = h[i].next;
-			h[i].next = (m_link_s *) a;
-			break;
-		}
-		q->next = q->next->next;
-		a = a & b;
-		s <<= 1;
-		++i;
-	}
-}
-
-static DEFINE_SPINLOCK(ncr53c8xx_lock);
-
-static void *__m_calloc2(m_pool_s *mp, int size, char *name, int uflags)
-{
-	void *p;
-
-	p = ___m_alloc(mp, size);
-
-	if (DEBUG_FLAGS & DEBUG_ALLOC)
-		printk ("new %-10s[%4d] @%p.\n", name, size, p);
-
-	if (p)
-		memset(p, 0, size);
-	else if (uflags & MEMO_WARN)
-		printk (NAME53C8XX ": failed to allocate %s[%d]\n", name, size);
-
-	return p;
-}
-
-#define __m_calloc(mp, s, n)	__m_calloc2(mp, s, n, MEMO_WARN)
-
-static void __m_free(m_pool_s *mp, void *ptr, int size, char *name)
-{
-	if (DEBUG_FLAGS & DEBUG_ALLOC)
-		printk ("freeing %-10s[%4d] @%p.\n", name, size, ptr);
-
-	___m_free(mp, ptr, size);
-
-}
-
-/*
- * With pci bus iommu support, we use a default pool of unmapped memory 
- * for memory we donnot need to DMA from/to and one pool per pcidev for 
- * memory accessed by the PCI chip. `mp0' is the default not DMAable pool.
- */
-
-static m_addr_t ___mp0_getp(m_pool_s *mp)
-{
-	m_addr_t m = __get_free_pages(MEMO_GFP_FLAGS, MEMO_PAGE_ORDER);
-	if (m)
-		++mp->nump;
-	return m;
-}
-
-static void ___mp0_freep(m_pool_s *mp, m_addr_t m)
-{
-	free_pages(m, MEMO_PAGE_ORDER);
-	--mp->nump;
-}
-
-static m_pool_s mp0 = {NULL, ___mp0_getp, ___mp0_freep};
-
-/*
- * DMAable pools.
- */
-
-/*
- * With pci bus iommu support, we maintain one pool per pcidev and a 
- * hashed reverse table for virtual to bus physical address translations.
- */
-static m_addr_t ___dma_getp(m_pool_s *mp)
-{
-	m_addr_t vp;
-	m_vtob_s *vbp;
-
-	vbp = __m_calloc(&mp0, sizeof(*vbp), "VTOB");
-	if (vbp) {
-		dma_addr_t daddr;
-		vp = (m_addr_t) dma_alloc_coherent(mp->bush,
-						PAGE_SIZE<<MEMO_PAGE_ORDER,
-						&daddr, GFP_ATOMIC);
-		if (vp) {
-			int hc = VTOB_HASH_CODE(vp);
-			vbp->vaddr = vp;
-			vbp->baddr = daddr;
-			vbp->next = mp->vtob[hc];
-			mp->vtob[hc] = vbp;
-			++mp->nump;
-			return vp;
-		}
-	}
-	if (vbp)
-		__m_free(&mp0, vbp, sizeof(*vbp), "VTOB");
-	return 0;
-}
-
-static void ___dma_freep(m_pool_s *mp, m_addr_t m)
-{
-	m_vtob_s **vbpp, *vbp;
-	int hc = VTOB_HASH_CODE(m);
-
-	vbpp = &mp->vtob[hc];
-	while (*vbpp && (*vbpp)->vaddr != m)
-		vbpp = &(*vbpp)->next;
-	if (*vbpp) {
-		vbp = *vbpp;
-		*vbpp = (*vbpp)->next;
-		dma_free_coherent(mp->bush, PAGE_SIZE<<MEMO_PAGE_ORDER,
-				  (void *)vbp->vaddr, (dma_addr_t)vbp->baddr);
-		__m_free(&mp0, vbp, sizeof(*vbp), "VTOB");
-		--mp->nump;
-	}
-}
-
-static inline m_pool_s *___get_dma_pool(m_bush_t bush)
-{
-	m_pool_s *mp;
-	for (mp = mp0.next; mp && mp->bush != bush; mp = mp->next);
-	return mp;
-}
-
-static m_pool_s *___cre_dma_pool(m_bush_t bush)
-{
-	m_pool_s *mp;
-	mp = __m_calloc(&mp0, sizeof(*mp), "MPOOL");
-	if (mp) {
-		memset(mp, 0, sizeof(*mp));
-		mp->bush = bush;
-		mp->getp = ___dma_getp;
-		mp->freep = ___dma_freep;
-		mp->next = mp0.next;
-		mp0.next = mp;
-	}
-	return mp;
-}
-
-static void ___del_dma_pool(m_pool_s *p)
-{
-	struct m_pool **pp = &mp0.next;
-
-	while (*pp && *pp != p)
-		pp = &(*pp)->next;
-	if (*pp) {
-		*pp = (*pp)->next;
-		__m_free(&mp0, p, sizeof(*p), "MPOOL");
-	}
-}
-
-static void *__m_calloc_dma(m_bush_t bush, int size, char *name)
-{
-	u_long flags;
-	struct m_pool *mp;
-	void *m = NULL;
-
-	spin_lock_irqsave(&ncr53c8xx_lock, flags);
-	mp = ___get_dma_pool(bush);
-	if (!mp)
-		mp = ___cre_dma_pool(bush);
-	if (mp)
-		m = __m_calloc(mp, size, name);
-	if (mp && !mp->nump)
-		___del_dma_pool(mp);
-	spin_unlock_irqrestore(&ncr53c8xx_lock, flags);
-
-	return m;
-}
-
-static void __m_free_dma(m_bush_t bush, void *m, int size, char *name)
-{
-	u_long flags;
-	struct m_pool *mp;
-
-	spin_lock_irqsave(&ncr53c8xx_lock, flags);
-	mp = ___get_dma_pool(bush);
-	if (mp)
-		__m_free(mp, m, size, name);
-	if (mp && !mp->nump)
-		___del_dma_pool(mp);
-	spin_unlock_irqrestore(&ncr53c8xx_lock, flags);
-}
-
-static m_addr_t __vtobus(m_bush_t bush, void *m)
-{
-	u_long flags;
-	m_pool_s *mp;
-	int hc = VTOB_HASH_CODE(m);
-	m_vtob_s *vp = NULL;
-	m_addr_t a = ((m_addr_t) m) & ~MEMO_CLUSTER_MASK;
-
-	spin_lock_irqsave(&ncr53c8xx_lock, flags);
-	mp = ___get_dma_pool(bush);
-	if (mp) {
-		vp = mp->vtob[hc];
-		while (vp && (m_addr_t) vp->vaddr != a)
-			vp = vp->next;
-	}
-	spin_unlock_irqrestore(&ncr53c8xx_lock, flags);
-	return vp ? vp->baddr + (((m_addr_t) m) - a) : 0;
-}
-
-#define _m_calloc_dma(np, s, n)		__m_calloc_dma(np->dev, s, n)
-#define _m_free_dma(np, p, s, n)	__m_free_dma(np->dev, p, s, n)
-#define m_calloc_dma(s, n)		_m_calloc_dma(np, s, n)
-#define m_free_dma(p, s, n)		_m_free_dma(np, p, s, n)
-#define _vtobus(np, p)			__vtobus(np->dev, p)
-#define vtobus(p)			_vtobus(np, p)
-
-/*
- *  Deal with DMA mapping/unmapping.
- */
-
-/* To keep track of the dma mapping (sg/single) that has been set */
-#define __data_mapped	SCp.phase
-#define __data_mapping	SCp.have_data_in
-
-static void __unmap_scsi_data(struct device *dev, struct scsi_cmnd *cmd)
-{
-	switch(cmd->__data_mapped) {
-	case 2:
-		dma_unmap_sg(dev, cmd->buffer, cmd->use_sg,
-				cmd->sc_data_direction);
-		break;
-	case 1:
-		dma_unmap_single(dev, cmd->__data_mapping,
-				 cmd->request_bufflen,
-				 cmd->sc_data_direction);
-		break;
-	}
-	cmd->__data_mapped = 0;
-}
-
-static u_long __map_scsi_single_data(struct device *dev, struct scsi_cmnd *cmd)
-{
-	dma_addr_t mapping;
-
-	if (cmd->request_bufflen == 0)
-		return 0;
-
-	mapping = dma_map_single(dev, cmd->request_buffer,
-				 cmd->request_bufflen,
-				 cmd->sc_data_direction);
-	cmd->__data_mapped = 1;
-	cmd->__data_mapping = mapping;
-
-	return mapping;
-}
-
-static int __map_scsi_sg_data(struct device *dev, struct scsi_cmnd *cmd)
-{
-	int use_sg;
-
-	if (cmd->use_sg == 0)
-		return 0;
-
-	use_sg = dma_map_sg(dev, cmd->buffer, cmd->use_sg,
-			cmd->sc_data_direction);
-	cmd->__data_mapped = 2;
-	cmd->__data_mapping = use_sg;
-
-	return use_sg;
-}
-
-#define unmap_scsi_data(np, cmd)	__unmap_scsi_data(np->dev, cmd)
-#define map_scsi_single_data(np, cmd)	__map_scsi_single_data(np->dev, cmd)
-#define map_scsi_sg_data(np, cmd)	__map_scsi_sg_data(np->dev, cmd)
-
-/*==========================================================
-**
-**	Driver setup.
-**
-**	This structure is initialized from linux config 
-**	options. It can be overridden at boot-up by the boot 
-**	command line.
-**
-**==========================================================
-*/
-static struct ncr_driver_setup
-	driver_setup			= SCSI_NCR_DRIVER_SETUP;
-
-#ifdef	SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT
-static struct ncr_driver_setup
-	driver_safe_setup __initdata	= SCSI_NCR_DRIVER_SAFE_SETUP;
-#endif
-
-#define initverbose (driver_setup.verbose)
-#define bootverbose (np->verbose)
-
-
-/*===================================================================
-**
-**	Driver setup from the boot command line
-**
-**===================================================================
-*/
-
-#ifdef MODULE
-#define	ARG_SEP	' '
-#else
-#define	ARG_SEP	','
-#endif
-
-#define OPT_TAGS		1
-#define OPT_MASTER_PARITY	2
-#define OPT_SCSI_PARITY		3
-#define OPT_DISCONNECTION	4
-#define OPT_SPECIAL_FEATURES	5
-#define OPT_UNUSED_1		6
-#define OPT_FORCE_SYNC_NEGO	7
-#define OPT_REVERSE_PROBE	8
-#define OPT_DEFAULT_SYNC	9
-#define OPT_VERBOSE		10
-#define OPT_DEBUG		11
-#define OPT_BURST_MAX		12
-#define OPT_LED_PIN		13
-#define OPT_MAX_WIDE		14
-#define OPT_SETTLE_DELAY	15
-#define OPT_DIFF_SUPPORT	16
-#define OPT_IRQM		17
-#define OPT_PCI_FIX_UP		18
-#define OPT_BUS_CHECK		19
-#define OPT_OPTIMIZE		20
-#define OPT_RECOVERY		21
-#define OPT_SAFE_SETUP		22
-#define OPT_USE_NVRAM		23
-#define OPT_EXCLUDE		24
-#define OPT_HOST_ID		25
-
-#ifdef SCSI_NCR_IARB_SUPPORT
-#define OPT_IARB		26
-#endif
-
-static char setup_token[] __initdata = 
-	"tags:"   "mpar:"
-	"spar:"   "disc:"
-	"specf:"  "ultra:"
-	"fsn:"    "revprob:"
-	"sync:"   "verb:"
-	"debug:"  "burst:"
-	"led:"    "wide:"
-	"settle:" "diff:"
-	"irqm:"   "pcifix:"
-	"buschk:" "optim:"
-	"recovery:"
-	"safe:"   "nvram:"
-	"excl:"   "hostid:"
-#ifdef SCSI_NCR_IARB_SUPPORT
-	"iarb:"
-#endif
-	;	/* DONNOT REMOVE THIS ';' */
-
-#ifdef MODULE
-#define	ARG_SEP	' '
-#else
-#define	ARG_SEP	','
-#endif
-
-static int __init get_setup_token(char *p)
-{
-	char *cur = setup_token;
-	char *pc;
-	int i = 0;
-
-	while (cur != NULL && (pc = strchr(cur, ':')) != NULL) {
-		++pc;
-		++i;
-		if (!strncmp(p, cur, pc - cur))
-			return i;
-		cur = pc;
-	}
-	return 0;
-}
-
-
-static int __init sym53c8xx__setup(char *str)
-{
-#ifdef SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT
-	char *cur = str;
-	char *pc, *pv;
-	int i, val, c;
-	int xi = 0;
-
-	while (cur != NULL && (pc = strchr(cur, ':')) != NULL) {
-		char *pe;
-
-		val = 0;
-		pv = pc;
-		c = *++pv;
-
-		if	(c == 'n')
-			val = 0;
-		else if	(c == 'y')
-			val = 1;
-		else
-			val = (int) simple_strtoul(pv, &pe, 0);
-
-		switch (get_setup_token(cur)) {
-		case OPT_TAGS:
-			driver_setup.default_tags = val;
-			if (pe && *pe == '/') {
-				i = 0;
-				while (*pe && *pe != ARG_SEP && 
-					i < sizeof(driver_setup.tag_ctrl)-1) {
-					driver_setup.tag_ctrl[i++] = *pe++;
-				}
-				driver_setup.tag_ctrl[i] = '\0';
-			}
-			break;
-		case OPT_MASTER_PARITY:
-			driver_setup.master_parity = val;
-			break;
-		case OPT_SCSI_PARITY:
-			driver_setup.scsi_parity = val;
-			break;
-		case OPT_DISCONNECTION:
-			driver_setup.disconnection = val;
-			break;
-		case OPT_SPECIAL_FEATURES:
-			driver_setup.special_features = val;
-			break;
-		case OPT_FORCE_SYNC_NEGO:
-			driver_setup.force_sync_nego = val;
-			break;
-		case OPT_REVERSE_PROBE:
-			driver_setup.reverse_probe = val;
-			break;
-		case OPT_DEFAULT_SYNC:
-			driver_setup.default_sync = val;
-			break;
-		case OPT_VERBOSE:
-			driver_setup.verbose = val;
-			break;
-		case OPT_DEBUG:
-			driver_setup.debug = val;
-			break;
-		case OPT_BURST_MAX:
-			driver_setup.burst_max = val;
-			break;
-		case OPT_LED_PIN:
-			driver_setup.led_pin = val;
-			break;
-		case OPT_MAX_WIDE:
-			driver_setup.max_wide = val? 1:0;
-			break;
-		case OPT_SETTLE_DELAY:
-			driver_setup.settle_delay = val;
-			break;
-		case OPT_DIFF_SUPPORT:
-			driver_setup.diff_support = val;
-			break;
-		case OPT_IRQM:
-			driver_setup.irqm = val;
-			break;
-		case OPT_PCI_FIX_UP:
-			driver_setup.pci_fix_up	= val;
-			break;
-		case OPT_BUS_CHECK:
-			driver_setup.bus_check = val;
-			break;
-		case OPT_OPTIMIZE:
-			driver_setup.optimize = val;
-			break;
-		case OPT_RECOVERY:
-			driver_setup.recovery = val;
-			break;
-		case OPT_USE_NVRAM:
-			driver_setup.use_nvram = val;
-			break;
-		case OPT_SAFE_SETUP:
-			memcpy(&driver_setup, &driver_safe_setup,
-				sizeof(driver_setup));
-			break;
-		case OPT_EXCLUDE:
-			if (xi < SCSI_NCR_MAX_EXCLUDES)
-				driver_setup.excludes[xi++] = val;
-			break;
-		case OPT_HOST_ID:
-			driver_setup.host_id = val;
-			break;
-#ifdef SCSI_NCR_IARB_SUPPORT
-		case OPT_IARB:
-			driver_setup.iarb = val;
-			break;
-#endif
-		default:
-			printk("sym53c8xx_setup: unexpected boot option '%.*s' ignored\n", (int)(pc-cur+1), cur);
-			break;
-		}
-
-		if ((cur = strchr(cur, ARG_SEP)) != NULL)
-			++cur;
-	}
-#endif /* SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT */
-	return 1;
-}
-
-/*===================================================================
-**
-**	Get device queue depth from boot command line.
-**
-**===================================================================
-*/
-#define DEF_DEPTH	(driver_setup.default_tags)
-#define ALL_TARGETS	-2
-#define NO_TARGET	-1
-#define ALL_LUNS	-2
-#define NO_LUN		-1
-
-static int device_queue_depth(int unit, int target, int lun)
-{
-	int c, h, t, u, v;
-	char *p = driver_setup.tag_ctrl;
-	char *ep;
-
-	h = -1;
-	t = NO_TARGET;
-	u = NO_LUN;
-	while ((c = *p++) != 0) {
-		v = simple_strtoul(p, &ep, 0);
-		switch(c) {
-		case '/':
-			++h;
-			t = ALL_TARGETS;
-			u = ALL_LUNS;
-			break;
-		case 't':
-			if (t != target)
-				t = (target == v) ? v : NO_TARGET;
-			u = ALL_LUNS;
-			break;
-		case 'u':
-			if (u != lun)
-				u = (lun == v) ? v : NO_LUN;
-			break;
-		case 'q':
-			if (h == unit &&
-				(t == ALL_TARGETS || t == target) &&
-				(u == ALL_LUNS    || u == lun))
-				return v;
-			break;
-		case '-':
-			t = ALL_TARGETS;
-			u = ALL_LUNS;
-			break;
-		default:
-			break;
-		}
-		p = ep;
-	}
-	return DEF_DEPTH;
-}
diff --git a/drivers/scsi/sym53c8xx_defs.h b/drivers/scsi/sym53c8xx_defs.h
deleted file mode 100644
index 139cd0e12e62..000000000000
--- a/drivers/scsi/sym53c8xx_defs.h
+++ /dev/null
@@ -1,1320 +0,0 @@
-/******************************************************************************
-**  High Performance device driver for the Symbios 53C896 controller.
-**
-**  Copyright (C) 1998-2001  Gerard Roudier <groudier@free.fr>
-**
-**  This driver also supports all the Symbios 53C8XX controller family, 
-**  except 53C810 revisions < 16, 53C825 revisions < 16 and all 
-**  revisions of 53C815 controllers.
-**
-**  This driver is based on the Linux port of the FreeBSD ncr driver.
-** 
-**  Copyright (C) 1994  Wolfgang Stanglmeier
-**  
-**-----------------------------------------------------------------------------
-**  
-**  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.
-**
-**-----------------------------------------------------------------------------
-**
-**  The Linux port of the FreeBSD ncr driver has been achieved in 
-**  november 1995 by:
-**
-**          Gerard Roudier              <groudier@free.fr>
-**
-**  Being given that this driver originates from the FreeBSD version, and
-**  in order to keep synergy on both, any suggested enhancements and corrections
-**  received on Linux are automatically a potential candidate for the FreeBSD 
-**  version.
-**
-**  The original driver has been written for 386bsd and FreeBSD by
-**          Wolfgang Stanglmeier        <wolf@cologne.de>
-**          Stefan Esser                <se@mi.Uni-Koeln.de>
-**
-**-----------------------------------------------------------------------------
-**
-**  Major contributions:
-**  --------------------
-**
-**  NVRAM detection and reading.
-**    Copyright (C) 1997 Richard Waltham <dormouse@farsrobt.demon.co.uk>
-**
-**  Added support for MIPS big endian systems.
-**    Carsten Langgaard, carstenl@mips.com
-**    Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
-**
-**  Added support for HP PARISC big endian systems.
-**    Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
-**
-*******************************************************************************
-*/
-
-#ifndef SYM53C8XX_DEFS_H
-#define SYM53C8XX_DEFS_H
-
-#include <linux/config.h>
-
-/*
-**	If you want a driver as small as possible, donnot define the 
-**	following options.
-*/
-#define SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT
-#define SCSI_NCR_DEBUG_INFO_SUPPORT
-
-/*
-**	To disable integrity checking, do not define the 
-**	following option.
-*/
-#ifdef	CONFIG_SCSI_NCR53C8XX_INTEGRITY_CHECK
-#	define SCSI_NCR_ENABLE_INTEGRITY_CHECK
-#endif
-
-/* ---------------------------------------------------------------------
-** Take into account kernel configured parameters.
-** Most of these options can be overridden at startup by a command line.
-** ---------------------------------------------------------------------
-*/
-
-/*
- * For Ultra2 and Ultra3 SCSI support option, use special features. 
- *
- * Value (default) means:
- *	bit 0 : all features enabled, except:
- *		bit 1 : PCI Write And Invalidate.
- *		bit 2 : Data Phase Mismatch handling from SCRIPTS.
- *
- * Use boot options ncr53c8xx=specf:1 if you want all chip features to be 
- * enabled by the driver.
- */
-#define	SCSI_NCR_SETUP_SPECIAL_FEATURES		(3)
-
-#define SCSI_NCR_MAX_SYNC			(80)
-
-/*
- * Allow tags from 2 to 256, default 8
- */
-#ifdef	CONFIG_SCSI_NCR53C8XX_MAX_TAGS
-#if	CONFIG_SCSI_NCR53C8XX_MAX_TAGS < 2
-#define SCSI_NCR_MAX_TAGS	(2)
-#elif	CONFIG_SCSI_NCR53C8XX_MAX_TAGS > 256
-#define SCSI_NCR_MAX_TAGS	(256)
-#else
-#define	SCSI_NCR_MAX_TAGS	CONFIG_SCSI_NCR53C8XX_MAX_TAGS
-#endif
-#else
-#define SCSI_NCR_MAX_TAGS	(8)
-#endif
-
-/*
- * Allow tagged command queuing support if configured with default number 
- * of tags set to max (see above).
- */
-#ifdef	CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS
-#define	SCSI_NCR_SETUP_DEFAULT_TAGS	CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS
-#elif	defined CONFIG_SCSI_NCR53C8XX_TAGGED_QUEUE
-#define	SCSI_NCR_SETUP_DEFAULT_TAGS	SCSI_NCR_MAX_TAGS
-#else
-#define	SCSI_NCR_SETUP_DEFAULT_TAGS	(0)
-#endif
-
-/*
- * Immediate arbitration
- */
-#if defined(CONFIG_SCSI_NCR53C8XX_IARB)
-#define SCSI_NCR_IARB_SUPPORT
-#endif
-
-/*
- * Sync transfer frequency at startup.
- * Allow from 5Mhz to 80Mhz default 20 Mhz.
- */
-#ifndef	CONFIG_SCSI_NCR53C8XX_SYNC
-#define	CONFIG_SCSI_NCR53C8XX_SYNC	(20)
-#elif	CONFIG_SCSI_NCR53C8XX_SYNC > SCSI_NCR_MAX_SYNC
-#undef	CONFIG_SCSI_NCR53C8XX_SYNC
-#define	CONFIG_SCSI_NCR53C8XX_SYNC	SCSI_NCR_MAX_SYNC
-#endif
-
-#if	CONFIG_SCSI_NCR53C8XX_SYNC == 0
-#define	SCSI_NCR_SETUP_DEFAULT_SYNC	(255)
-#elif	CONFIG_SCSI_NCR53C8XX_SYNC <= 5
-#define	SCSI_NCR_SETUP_DEFAULT_SYNC	(50)
-#elif	CONFIG_SCSI_NCR53C8XX_SYNC <= 20
-#define	SCSI_NCR_SETUP_DEFAULT_SYNC	(250/(CONFIG_SCSI_NCR53C8XX_SYNC))
-#elif	CONFIG_SCSI_NCR53C8XX_SYNC <= 33
-#define	SCSI_NCR_SETUP_DEFAULT_SYNC	(11)
-#elif	CONFIG_SCSI_NCR53C8XX_SYNC <= 40
-#define	SCSI_NCR_SETUP_DEFAULT_SYNC	(10)
-#else
-#define	SCSI_NCR_SETUP_DEFAULT_SYNC 	(9)
-#endif
-
-/*
- * Disallow disconnections at boot-up
- */
-#ifdef CONFIG_SCSI_NCR53C8XX_NO_DISCONNECT
-#define SCSI_NCR_SETUP_DISCONNECTION	(0)
-#else
-#define SCSI_NCR_SETUP_DISCONNECTION	(1)
-#endif
-
-/*
- * Force synchronous negotiation for all targets
- */
-#ifdef CONFIG_SCSI_NCR53C8XX_FORCE_SYNC_NEGO
-#define SCSI_NCR_SETUP_FORCE_SYNC_NEGO	(1)
-#else
-#define SCSI_NCR_SETUP_FORCE_SYNC_NEGO	(0)
-#endif
-
-/*
- * Disable master parity checking (flawed hardwares need that)
- */
-#ifdef CONFIG_SCSI_NCR53C8XX_DISABLE_MPARITY_CHECK
-#define SCSI_NCR_SETUP_MASTER_PARITY	(0)
-#else
-#define SCSI_NCR_SETUP_MASTER_PARITY	(1)
-#endif
-
-/*
- * Disable scsi parity checking (flawed devices may need that)
- */
-#ifdef CONFIG_SCSI_NCR53C8XX_DISABLE_PARITY_CHECK
-#define SCSI_NCR_SETUP_SCSI_PARITY	(0)
-#else
-#define SCSI_NCR_SETUP_SCSI_PARITY	(1)
-#endif
-
-/*
- * Settle time after reset at boot-up
- */
-#define SCSI_NCR_SETUP_SETTLE_TIME	(2)
-
-/*
-**	Bridge quirks work-around option defaulted to 1.
-*/
-#ifndef	SCSI_NCR_PCIQ_WORK_AROUND_OPT
-#define	SCSI_NCR_PCIQ_WORK_AROUND_OPT	1
-#endif
-
-/*
-**	Work-around common bridge misbehaviour.
-**
-**	- Do not flush posted writes in the opposite 
-**	  direction on read.
-**	- May reorder DMA writes to memory.
-**
-**	This option should not affect performances 
-**	significantly, so it is the default.
-*/
-#if	SCSI_NCR_PCIQ_WORK_AROUND_OPT == 1
-#define	SCSI_NCR_PCIQ_MAY_NOT_FLUSH_PW_UPSTREAM
-#define	SCSI_NCR_PCIQ_MAY_REORDER_WRITES
-#define	SCSI_NCR_PCIQ_MAY_MISS_COMPLETIONS
-
-/*
-**	Same as option 1, but also deal with 
-**	misconfigured interrupts.
-**
-**	- Edge triggerred instead of level sensitive.
-**	- No interrupt line connected.
-**	- IRQ number misconfigured.
-**	
-**	If no interrupt is delivered, the driver will 
-**	catch the interrupt conditions 10 times per 
-**	second. No need to say that this option is 
-**	not recommended.
-*/
-#elif	SCSI_NCR_PCIQ_WORK_AROUND_OPT == 2
-#define	SCSI_NCR_PCIQ_MAY_NOT_FLUSH_PW_UPSTREAM
-#define	SCSI_NCR_PCIQ_MAY_REORDER_WRITES
-#define	SCSI_NCR_PCIQ_MAY_MISS_COMPLETIONS
-#define	SCSI_NCR_PCIQ_BROKEN_INTR
-
-/*
-**	Some bridge designers decided to flush 
-**	everything prior to deliver the interrupt.
-**	This option tries to deal with such a 
-**	behaviour.
-*/
-#elif	SCSI_NCR_PCIQ_WORK_AROUND_OPT == 3
-#define	SCSI_NCR_PCIQ_SYNC_ON_INTR
-#endif
-
-/*
-**	Other parameters not configurable with "make config"
-**	Avoid to change these constants, unless you know what you are doing.
-*/
-
-#define SCSI_NCR_ALWAYS_SIMPLE_TAG
-#define SCSI_NCR_MAX_SCATTER	(127)
-#define SCSI_NCR_MAX_TARGET	(16)
-
-/*
-**   Compute some desirable value for CAN_QUEUE 
-**   and CMD_PER_LUN.
-**   The driver will use lower values if these 
-**   ones appear to be too large.
-*/
-#define SCSI_NCR_CAN_QUEUE	(8*SCSI_NCR_MAX_TAGS + 2*SCSI_NCR_MAX_TARGET)
-#define SCSI_NCR_CMD_PER_LUN	(SCSI_NCR_MAX_TAGS)
-
-#define SCSI_NCR_SG_TABLESIZE	(SCSI_NCR_MAX_SCATTER)
-#define SCSI_NCR_TIMER_INTERVAL	(HZ)
-
-#if 1 /* defined CONFIG_SCSI_MULTI_LUN */
-#define SCSI_NCR_MAX_LUN	(16)
-#else
-#define SCSI_NCR_MAX_LUN	(1)
-#endif
-
-/*
- *  IO functions definition for big/little endian CPU support.
- *  For now, the NCR is only supported in little endian addressing mode, 
- */
-
-#ifdef	__BIG_ENDIAN
-
-#define	inw_l2b		inw
-#define	inl_l2b		inl
-#define	outw_b2l	outw
-#define	outl_b2l	outl
-
-#define	readb_raw	readb
-#define	writeb_raw	writeb
-
-#if defined(SCSI_NCR_BIG_ENDIAN)
-#define	readw_l2b	__raw_readw
-#define	readl_l2b	__raw_readl
-#define	writew_b2l	__raw_writew
-#define	writel_b2l	__raw_writel
-#define	readw_raw	__raw_readw
-#define	readl_raw	__raw_readl
-#define	writew_raw	__raw_writew
-#define	writel_raw	__raw_writel
-#else	/* Other big-endian */
-#define	readw_l2b	readw
-#define	readl_l2b	readl
-#define	writew_b2l	writew
-#define	writel_b2l	writel
-#define	readw_raw	readw
-#define	readl_raw	readl
-#define	writew_raw	writew
-#define	writel_raw	writel
-#endif
-
-#else	/* little endian */
-
-#define	inw_raw		inw
-#define	inl_raw		inl
-#define	outw_raw	outw
-#define	outl_raw	outl
-
-#define	readb_raw	readb
-#define	readw_raw	readw
-#define	readl_raw	readl
-#define	writeb_raw	writeb
-#define	writew_raw	writew
-#define	writel_raw	writel
-
-#endif
-
-#if !defined(__hppa__) && !defined(__mips__)
-#ifdef	SCSI_NCR_BIG_ENDIAN
-#error	"The NCR in BIG ENDIAN addressing mode is not (yet) supported"
-#endif
-#endif
-
-#define MEMORY_BARRIER()	mb()
-
-
-/*
- *  If the NCR uses big endian addressing mode over the 
- *  PCI, actual io register addresses for byte and word 
- *  accesses must be changed according to lane routing.
- *  Btw, ncr_offb() and ncr_offw() macros only apply to 
- *  constants and so donnot generate bloated code.
- */
-
-#if	defined(SCSI_NCR_BIG_ENDIAN)
-
-#define ncr_offb(o)	(((o)&~3)+((~((o)&3))&3))
-#define ncr_offw(o)	(((o)&~3)+((~((o)&3))&2))
-
-#else
-
-#define ncr_offb(o)	(o)
-#define ncr_offw(o)	(o)
-
-#endif
-
-/*
- *  If the CPU and the NCR use same endian-ness addressing,
- *  no byte reordering is needed for script patching.
- *  Macro cpu_to_scr() is to be used for script patching.
- *  Macro scr_to_cpu() is to be used for getting a DWORD 
- *  from the script.
- */
-
-#if	defined(__BIG_ENDIAN) && !defined(SCSI_NCR_BIG_ENDIAN)
-
-#define cpu_to_scr(dw)	cpu_to_le32(dw)
-#define scr_to_cpu(dw)	le32_to_cpu(dw)
-
-#elif	defined(__LITTLE_ENDIAN) && defined(SCSI_NCR_BIG_ENDIAN)
-
-#define cpu_to_scr(dw)	cpu_to_be32(dw)
-#define scr_to_cpu(dw)	be32_to_cpu(dw)
-
-#else
-
-#define cpu_to_scr(dw)	(dw)
-#define scr_to_cpu(dw)	(dw)
-
-#endif
-
-/*
- *  Access to the controller chip.
- *
- *  If the CPU and the NCR use same endian-ness addressing,
- *  no byte reordering is needed for accessing chip io 
- *  registers. Functions suffixed by '_raw' are assumed 
- *  to access the chip over the PCI without doing byte 
- *  reordering. Functions suffixed by '_l2b' are 
- *  assumed to perform little-endian to big-endian byte 
- *  reordering, those suffixed by '_b2l' blah, blah,
- *  blah, ...
- */
-
-/*
- *  MEMORY mapped IO input / output
- */
-
-#define INB_OFF(o)		readb_raw((char __iomem *)np->reg + ncr_offb(o))
-#define OUTB_OFF(o, val)	writeb_raw((val), (char __iomem *)np->reg + ncr_offb(o))
-
-#if	defined(__BIG_ENDIAN) && !defined(SCSI_NCR_BIG_ENDIAN)
-
-#define INW_OFF(o)		readw_l2b((char __iomem *)np->reg + ncr_offw(o))
-#define INL_OFF(o)		readl_l2b((char __iomem *)np->reg + (o))
-
-#define OUTW_OFF(o, val)	writew_b2l((val), (char __iomem *)np->reg + ncr_offw(o))
-#define OUTL_OFF(o, val)	writel_b2l((val), (char __iomem *)np->reg + (o))
-
-#elif	defined(__LITTLE_ENDIAN) && defined(SCSI_NCR_BIG_ENDIAN)
-
-#define INW_OFF(o)		readw_b2l((char __iomem *)np->reg + ncr_offw(o))
-#define INL_OFF(o)		readl_b2l((char __iomem *)np->reg + (o))
-
-#define OUTW_OFF(o, val)	writew_l2b((val), (char __iomem *)np->reg + ncr_offw(o))
-#define OUTL_OFF(o, val)	writel_l2b((val), (char __iomem *)np->reg + (o))
-
-#else
-
-#ifdef CONFIG_SCSI_NCR53C8XX_NO_WORD_TRANSFERS
-/* Only 8 or 32 bit transfers allowed */
-#define INW_OFF(o)		(readb((char __iomem *)np->reg + ncr_offw(o)) << 8 | readb((char __iomem *)np->reg + ncr_offw(o) + 1))
-#else
-#define INW_OFF(o)		readw_raw((char __iomem *)np->reg + ncr_offw(o))
-#endif
-#define INL_OFF(o)		readl_raw((char __iomem *)np->reg + (o))
-
-#ifdef CONFIG_SCSI_NCR53C8XX_NO_WORD_TRANSFERS
-/* Only 8 or 32 bit transfers allowed */
-#define OUTW_OFF(o, val)	do { writeb((char)((val) >> 8), (char __iomem *)np->reg + ncr_offw(o)); writeb((char)(val), (char __iomem *)np->reg + ncr_offw(o) + 1); } while (0)
-#else
-#define OUTW_OFF(o, val)	writew_raw((val), (char __iomem *)np->reg + ncr_offw(o))
-#endif
-#define OUTL_OFF(o, val)	writel_raw((val), (char __iomem *)np->reg + (o))
-
-#endif
-
-#define INB(r)		INB_OFF (offsetof(struct ncr_reg,r))
-#define INW(r)		INW_OFF (offsetof(struct ncr_reg,r))
-#define INL(r)		INL_OFF (offsetof(struct ncr_reg,r))
-
-#define OUTB(r, val)	OUTB_OFF (offsetof(struct ncr_reg,r), (val))
-#define OUTW(r, val)	OUTW_OFF (offsetof(struct ncr_reg,r), (val))
-#define OUTL(r, val)	OUTL_OFF (offsetof(struct ncr_reg,r), (val))
-
-/*
- *  Set bit field ON, OFF 
- */
-
-#define OUTONB(r, m)	OUTB(r, INB(r) | (m))
-#define OUTOFFB(r, m)	OUTB(r, INB(r) & ~(m))
-#define OUTONW(r, m)	OUTW(r, INW(r) | (m))
-#define OUTOFFW(r, m)	OUTW(r, INW(r) & ~(m))
-#define OUTONL(r, m)	OUTL(r, INL(r) | (m))
-#define OUTOFFL(r, m)	OUTL(r, INL(r) & ~(m))
-
-/*
- *  We normally want the chip to have a consistent view
- *  of driver internal data structures when we restart it.
- *  Thus these macros.
- */
-#define OUTL_DSP(v)				\
-	do {					\
-		MEMORY_BARRIER();		\
-		OUTL (nc_dsp, (v));		\
-	} while (0)
-
-#define OUTONB_STD()				\
-	do {					\
-		MEMORY_BARRIER();		\
-		OUTONB (nc_dcntl, (STD|NOCOM));	\
-	} while (0)
-
-
-/*
-**   NCR53C8XX devices features table.
-*/
-struct ncr_chip {
-	unsigned short	revision_id;
-	unsigned char	burst_max;	/* log-base-2 of max burst */
-	unsigned char	offset_max;
-	unsigned char	nr_divisor;
-	unsigned int	features;
-#define FE_LED0		(1<<0)
-#define FE_WIDE		(1<<1)    /* Wide data transfers */
-#define FE_ULTRA	(1<<2)	  /* Ultra speed 20Mtrans/sec */
-#define FE_DBLR		(1<<4)	  /* Clock doubler present */
-#define FE_QUAD		(1<<5)	  /* Clock quadrupler present */
-#define FE_ERL		(1<<6)    /* Enable read line */
-#define FE_CLSE		(1<<7)    /* Cache line size enable */
-#define FE_WRIE		(1<<8)    /* Write & Invalidate enable */
-#define FE_ERMP		(1<<9)    /* Enable read multiple */
-#define FE_BOF		(1<<10)   /* Burst opcode fetch */
-#define FE_DFS		(1<<11)   /* DMA fifo size */
-#define FE_PFEN		(1<<12)   /* Prefetch enable */
-#define FE_LDSTR	(1<<13)   /* Load/Store supported */
-#define FE_RAM		(1<<14)   /* On chip RAM present */
-#define FE_VARCLK	(1<<15)   /* SCSI clock may vary */
-#define FE_RAM8K	(1<<16)   /* On chip RAM sized 8Kb */
-#define FE_64BIT	(1<<17)   /* Have a 64-bit PCI interface */
-#define FE_IO256	(1<<18)   /* Requires full 256 bytes in PCI space */
-#define FE_NOPM		(1<<19)   /* Scripts handles phase mismatch */
-#define FE_LEDC		(1<<20)   /* Hardware control of LED */
-#define FE_DIFF		(1<<21)   /* Support Differential SCSI */
-#define FE_66MHZ 	(1<<23)   /* 66MHz PCI Support */
-#define FE_DAC	 	(1<<24)   /* Support DAC cycles (64 bit addressing) */
-#define FE_ISTAT1 	(1<<25)   /* Have ISTAT1, MBOX0, MBOX1 registers */
-#define FE_DAC_IN_USE	(1<<26)	  /* Platform does DAC cycles */
-#define FE_EHP		(1<<27)   /* 720: Even host parity */
-#define FE_MUX		(1<<28)   /* 720: Multiplexed bus */
-#define FE_EA		(1<<29)   /* 720: Enable Ack */
-
-#define FE_CACHE_SET	(FE_ERL|FE_CLSE|FE_WRIE|FE_ERMP)
-#define FE_SCSI_SET	(FE_WIDE|FE_ULTRA|FE_DBLR|FE_QUAD|F_CLK80)
-#define FE_SPECIAL_SET	(FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM)
-};
-
-
-/*
-**	Driver setup structure.
-**
-**	This structure is initialized from linux config options.
-**	It can be overridden at boot-up by the boot command line.
-*/
-#define SCSI_NCR_MAX_EXCLUDES 8
-struct ncr_driver_setup {
-	u8	master_parity;
-	u8	scsi_parity;
-	u8	disconnection;
-	u8	special_features;
-	u8	force_sync_nego;
-	u8	reverse_probe;
-	u8	pci_fix_up;
-	u8	use_nvram;
-	u8	verbose;
-	u8	default_tags;
-	u16	default_sync;
-	u16	debug;
-	u8	burst_max;
-	u8	led_pin;
-	u8	max_wide;
-	u8	settle_delay;
-	u8	diff_support;
-	u8	irqm;
-	u8	bus_check;
-	u8	optimize;
-	u8	recovery;
-	u8	host_id;
-	u16	iarb;
-	u32	excludes[SCSI_NCR_MAX_EXCLUDES];
-	char	tag_ctrl[100];
-};
-
-/*
-**	Initial setup.
-**	Can be overriden at startup by a command line.
-*/
-#define SCSI_NCR_DRIVER_SETUP			\
-{						\
-	SCSI_NCR_SETUP_MASTER_PARITY,		\
-	SCSI_NCR_SETUP_SCSI_PARITY,		\
-	SCSI_NCR_SETUP_DISCONNECTION,		\
-	SCSI_NCR_SETUP_SPECIAL_FEATURES,	\
-	SCSI_NCR_SETUP_FORCE_SYNC_NEGO,		\
-	0,					\
-	0,					\
-	1,					\
-	0,					\
-	SCSI_NCR_SETUP_DEFAULT_TAGS,		\
-	SCSI_NCR_SETUP_DEFAULT_SYNC,		\
-	0x00,					\
-	7,					\
-	0,					\
-	1,					\
-	SCSI_NCR_SETUP_SETTLE_TIME,		\
-	0,					\
-	0,					\
-	1,					\
-	0,					\
-	0,					\
-	255,					\
-	0x00					\
-}
-
-/*
-**	Boot fail safe setup.
-**	Override initial setup from boot command line:
-**	ncr53c8xx=safe:y
-*/
-#define SCSI_NCR_DRIVER_SAFE_SETUP		\
-{						\
-	0,					\
-	1,					\
-	0,					\
-	0,					\
-	0,					\
-	0,					\
-	0,					\
-	1,					\
-	2,					\
-	0,					\
-	255,					\
-	0x00,					\
-	255,					\
-	0,					\
-	0,					\
-	10,					\
-	1,					\
-	1,					\
-	1,					\
-	0,					\
-	0,					\
-	255					\
-}
-
-/**************** ORIGINAL CONTENT of ncrreg.h from FreeBSD ******************/
-
-/*-----------------------------------------------------------------
-**
-**	The ncr 53c810 register structure.
-**
-**-----------------------------------------------------------------
-*/
-
-struct ncr_reg {
-/*00*/  u8	nc_scntl0;    /* full arb., ena parity, par->ATN  */
-
-/*01*/  u8	nc_scntl1;    /* no reset                         */
-        #define   ISCON   0x10  /* connected to scsi		    */
-        #define   CRST    0x08  /* force reset                      */
-        #define   IARB    0x02  /* immediate arbitration            */
-
-/*02*/  u8	nc_scntl2;    /* no disconnect expected           */
-	#define   SDU     0x80  /* cmd: disconnect will raise error */
-	#define   CHM     0x40  /* sta: chained mode                */
-	#define   WSS     0x08  /* sta: wide scsi send           [W]*/
-	#define   WSR     0x01  /* sta: wide scsi received       [W]*/
-
-/*03*/  u8	nc_scntl3;    /* cnf system clock dependent       */
-	#define   EWS     0x08  /* cmd: enable wide scsi         [W]*/
-	#define   ULTRA   0x80  /* cmd: ULTRA enable                */
-				/* bits 0-2, 7 rsvd for C1010       */
-
-/*04*/  u8	nc_scid;	/* cnf host adapter scsi address    */
-	#define   RRE     0x40  /* r/w:e enable response to resel.  */
-	#define   SRE     0x20  /* r/w:e enable response to select  */
-
-/*05*/  u8	nc_sxfer;	/* ### Sync speed and count         */
-				/* bits 6-7 rsvd for C1010          */
-
-/*06*/  u8	nc_sdid;	/* ### Destination-ID               */
-
-/*07*/  u8	nc_gpreg;	/* ??? IO-Pins                      */
-
-/*08*/  u8	nc_sfbr;	/* ### First byte in phase          */
-
-/*09*/  u8	nc_socl;
-	#define   CREQ	  0x80	/* r/w: SCSI-REQ                    */
-	#define   CACK	  0x40	/* r/w: SCSI-ACK                    */
-	#define   CBSY	  0x20	/* r/w: SCSI-BSY                    */
-	#define   CSEL	  0x10	/* r/w: SCSI-SEL                    */
-	#define   CATN	  0x08	/* r/w: SCSI-ATN                    */
-	#define   CMSG	  0x04	/* r/w: SCSI-MSG                    */
-	#define   CC_D	  0x02	/* r/w: SCSI-C_D                    */
-	#define   CI_O	  0x01	/* r/w: SCSI-I_O                    */
-
-/*0a*/  u8	nc_ssid;
-
-/*0b*/  u8	nc_sbcl;
-
-/*0c*/  u8	nc_dstat;
-        #define   DFE     0x80  /* sta: dma fifo empty              */
-        #define   MDPE    0x40  /* int: master data parity error    */
-        #define   BF      0x20  /* int: script: bus fault           */
-        #define   ABRT    0x10  /* int: script: command aborted     */
-        #define   SSI     0x08  /* int: script: single step         */
-        #define   SIR     0x04  /* int: script: interrupt instruct. */
-        #define   IID     0x01  /* int: script: illegal instruct.   */
-
-/*0d*/  u8	nc_sstat0;
-        #define   ILF     0x80  /* sta: data in SIDL register lsb   */
-        #define   ORF     0x40  /* sta: data in SODR register lsb   */
-        #define   OLF     0x20  /* sta: data in SODL register lsb   */
-        #define   AIP     0x10  /* sta: arbitration in progress     */
-        #define   LOA     0x08  /* sta: arbitration lost            */
-        #define   WOA     0x04  /* sta: arbitration won             */
-        #define   IRST    0x02  /* sta: scsi reset signal           */
-        #define   SDP     0x01  /* sta: scsi parity signal          */
-
-/*0e*/  u8	nc_sstat1;
-	#define   FF3210  0xf0	/* sta: bytes in the scsi fifo      */
-
-/*0f*/  u8	nc_sstat2;
-        #define   ILF1    0x80  /* sta: data in SIDL register msb[W]*/
-        #define   ORF1    0x40  /* sta: data in SODR register msb[W]*/
-        #define   OLF1    0x20  /* sta: data in SODL register msb[W]*/
-        #define   DM      0x04  /* sta: DIFFSENS mismatch (895/6 only) */
-        #define   LDSC    0x02  /* sta: disconnect & reconnect      */
-
-/*10*/  u8	nc_dsa;	/* --> Base page                    */
-/*11*/  u8	nc_dsa1;
-/*12*/  u8	nc_dsa2;
-/*13*/  u8	nc_dsa3;
-
-/*14*/  u8	nc_istat;	/* --> Main Command and status      */
-        #define   CABRT   0x80  /* cmd: abort current operation     */
-        #define   SRST    0x40  /* mod: reset chip                  */
-        #define   SIGP    0x20  /* r/w: message from host to ncr    */
-        #define   SEM     0x10  /* r/w: message between host + ncr  */
-        #define   CON     0x08  /* sta: connected to scsi           */
-        #define   INTF    0x04  /* sta: int on the fly (reset by wr)*/
-        #define   SIP     0x02  /* sta: scsi-interrupt              */
-        #define   DIP     0x01  /* sta: host/script interrupt       */
-
-/*15*/  u8	nc_istat1;	/* 896 and later cores only */
-        #define   FLSH    0x04  /* sta: chip is flushing            */
-        #define   SRUN    0x02  /* sta: scripts are running         */
-        #define   SIRQD   0x01  /* r/w: disable INT pin             */
-
-/*16*/  u8	nc_mbox0;	/* 896 and later cores only */
-/*17*/  u8	nc_mbox1;	/* 896 and later cores only */
-
-/*18*/	u8	nc_ctest0;
-	#define   EHP     0x04	/* 720 even host parity             */
-/*19*/  u8	nc_ctest1;
-
-/*1a*/  u8	nc_ctest2;
-	#define   CSIGP   0x40
-				/* bits 0-2,7 rsvd for C1010        */
-
-/*1b*/  u8	nc_ctest3;
-	#define   FLF     0x08  /* cmd: flush dma fifo              */
-	#define   CLF	  0x04	/* cmd: clear dma fifo		    */
-	#define   FM      0x02  /* mod: fetch pin mode              */
-	#define   WRIE    0x01  /* mod: write and invalidate enable */
-				/* bits 4-7 rsvd for C1010          */
-
-/*1c*/  u32    nc_temp;	/* ### Temporary stack              */
-
-/*20*/	u8	nc_dfifo;
-/*21*/  u8	nc_ctest4;
-	#define   MUX     0x80  /* 720 host bus multiplex mode      */
-	#define   BDIS    0x80  /* mod: burst disable               */
-	#define   MPEE    0x08  /* mod: master parity error enable  */
-
-/*22*/  u8	nc_ctest5;
-	#define   DFS     0x20  /* mod: dma fifo size               */
-				/* bits 0-1, 3-7 rsvd for C1010          */
-/*23*/  u8	nc_ctest6;
-
-/*24*/  u32    nc_dbc;	/* ### Byte count and command       */
-/*28*/  u32    nc_dnad;	/* ### Next command register        */
-/*2c*/  u32    nc_dsp;	/* --> Script Pointer               */
-/*30*/  u32    nc_dsps;	/* --> Script pointer save/opcode#2 */
-
-/*34*/  u8	nc_scratcha;  /* Temporary register a            */
-/*35*/  u8	nc_scratcha1;
-/*36*/  u8	nc_scratcha2;
-/*37*/  u8	nc_scratcha3;
-
-/*38*/  u8	nc_dmode;
-	#define   BL_2    0x80  /* mod: burst length shift value +2 */
-	#define   BL_1    0x40  /* mod: burst length shift value +1 */
-	#define   ERL     0x08  /* mod: enable read line            */
-	#define   ERMP    0x04  /* mod: enable read multiple        */
-	#define   BOF     0x02  /* mod: burst op code fetch         */
-
-/*39*/  u8	nc_dien;
-/*3a*/  u8	nc_sbr;
-
-/*3b*/  u8	nc_dcntl;	/* --> Script execution control     */
-	#define   CLSE    0x80  /* mod: cache line size enable      */
-	#define   PFF     0x40  /* cmd: pre-fetch flush             */
-	#define   PFEN    0x20  /* mod: pre-fetch enable            */
-	#define   EA      0x20  /* mod: 720 enable-ack              */
-	#define   SSM     0x10  /* mod: single step mode            */
-	#define   IRQM    0x08  /* mod: irq mode (1 = totem pole !) */
-	#define   STD     0x04  /* cmd: start dma mode              */
-	#define   IRQD    0x02  /* mod: irq disable                 */
- 	#define	  NOCOM   0x01	/* cmd: protect sfbr while reselect */
-				/* bits 0-1 rsvd for C1010          */
-
-/*3c*/  u32	nc_adder;
-
-/*40*/  u16	nc_sien;	/* -->: interrupt enable            */
-/*42*/  u16	nc_sist;	/* <--: interrupt status            */
-        #define   SBMC    0x1000/* sta: SCSI Bus Mode Change (895/6 only) */
-        #define   STO     0x0400/* sta: timeout (select)            */
-        #define   GEN     0x0200/* sta: timeout (general)           */
-        #define   HTH     0x0100/* sta: timeout (handshake)         */
-        #define   MA      0x80  /* sta: phase mismatch              */
-        #define   CMP     0x40  /* sta: arbitration complete        */
-        #define   SEL     0x20  /* sta: selected by another device  */
-        #define   RSL     0x10  /* sta: reselected by another device*/
-        #define   SGE     0x08  /* sta: gross error (over/underflow)*/
-        #define   UDC     0x04  /* sta: unexpected disconnect       */
-        #define   RST     0x02  /* sta: scsi bus reset detected     */
-        #define   PAR     0x01  /* sta: scsi parity error           */
-
-/*44*/  u8	nc_slpar;
-/*45*/  u8	nc_swide;
-/*46*/  u8	nc_macntl;
-/*47*/  u8	nc_gpcntl;
-/*48*/  u8	nc_stime0;    /* cmd: timeout for select&handshake*/
-/*49*/  u8	nc_stime1;    /* cmd: timeout user defined        */
-/*4a*/  u16   nc_respid;    /* sta: Reselect-IDs                */
-
-/*4c*/  u8	nc_stest0;
-
-/*4d*/  u8	nc_stest1;
-	#define   SCLK    0x80	/* Use the PCI clock as SCSI clock	*/
-	#define   DBLEN   0x08	/* clock doubler running		*/
-	#define   DBLSEL  0x04	/* clock doubler selected		*/
-  
-
-/*4e*/  u8	nc_stest2;
-	#define   ROF     0x40	/* reset scsi offset (after gross error!) */
-	#define   DIF     0x20  /* 720 SCSI differential mode             */
-	#define   EXT     0x02  /* extended filtering                     */
-
-/*4f*/  u8	nc_stest3;
-	#define   TE     0x80	/* c: tolerAnt enable */
-	#define   HSC    0x20	/* c: Halt SCSI Clock */
-	#define   CSF    0x02	/* c: clear scsi fifo */
-
-/*50*/  u16   nc_sidl;	/* Lowlevel: latched from scsi data */
-/*52*/  u8	nc_stest4;
-	#define   SMODE  0xc0	/* SCSI bus mode      (895/6 only) */
-	#define    SMODE_HVD 0x40	/* High Voltage Differential       */
-	#define    SMODE_SE  0x80	/* Single Ended                    */
-	#define    SMODE_LVD 0xc0	/* Low Voltage Differential        */
-	#define   LCKFRQ 0x20	/* Frequency Lock (895/6 only)     */
-				/* bits 0-5 rsvd for C1010          */
-
-/*53*/  u8	nc_53_;
-/*54*/  u16	nc_sodl;	/* Lowlevel: data out to scsi data  */
-/*56*/	u8	nc_ccntl0;	/* Chip Control 0 (896)             */
-	#define   ENPMJ  0x80	/* Enable Phase Mismatch Jump       */
-	#define   PMJCTL 0x40	/* Phase Mismatch Jump Control      */
-	#define   ENNDJ  0x20	/* Enable Non Data PM Jump          */
-	#define   DISFC  0x10	/* Disable Auto FIFO Clear          */
-	#define   DILS   0x02	/* Disable Internal Load/Store      */
-	#define   DPR    0x01	/* Disable Pipe Req                 */
-
-/*57*/	u8	nc_ccntl1;	/* Chip Control 1 (896)             */
-	#define   ZMOD   0x80	/* High Impedance Mode              */
-	#define	  DIC	 0x10	/* Disable Internal Cycles	    */
-	#define   DDAC   0x08	/* Disable Dual Address Cycle       */
-	#define   XTIMOD 0x04	/* 64-bit Table Ind. Indexing Mode  */
-	#define   EXTIBMV 0x02	/* Enable 64-bit Table Ind. BMOV    */
-	#define   EXDBMV 0x01	/* Enable 64-bit Direct BMOV        */
-
-/*58*/  u16	nc_sbdl;	/* Lowlevel: data from scsi data    */
-/*5a*/  u16	nc_5a_;
-
-/*5c*/  u8	nc_scr0;	/* Working register B               */
-/*5d*/  u8	nc_scr1;	/*                                  */
-/*5e*/  u8	nc_scr2;	/*                                  */
-/*5f*/  u8	nc_scr3;	/*                                  */
-
-/*60*/  u8	nc_scrx[64];	/* Working register C-R             */
-/*a0*/	u32	nc_mmrs;	/* Memory Move Read Selector        */
-/*a4*/	u32	nc_mmws;	/* Memory Move Write Selector       */
-/*a8*/	u32	nc_sfs;		/* Script Fetch Selector            */
-/*ac*/	u32	nc_drs;		/* DSA Relative Selector            */
-/*b0*/	u32	nc_sbms;	/* Static Block Move Selector       */
-/*b4*/	u32	nc_dbms;	/* Dynamic Block Move Selector      */
-/*b8*/	u32	nc_dnad64;	/* DMA Next Address 64              */
-/*bc*/	u16	nc_scntl4;	/* C1010 only                       */
-	#define   U3EN   0x80	/* Enable Ultra 3                   */
-	#define   AIPEN	 0x40   /* Allow check upper byte lanes     */
-	#define   XCLKH_DT 0x08 /* Extra clock of data hold on DT
-					transfer edge	            */
-	#define   XCLKH_ST 0x04 /* Extra clock of data hold on ST
-					transfer edge	            */
-
-/*be*/  u8	nc_aipcntl0;	/* Epat Control 1 C1010 only        */
-/*bf*/  u8	nc_aipcntl1;	/* AIP Control C1010_66 Only        */
-
-/*c0*/	u32	nc_pmjad1;	/* Phase Mismatch Jump Address 1    */
-/*c4*/	u32	nc_pmjad2;	/* Phase Mismatch Jump Address 2    */
-/*c8*/	u8	nc_rbc;		/* Remaining Byte Count             */
-/*c9*/	u8	nc_rbc1;	/*                                  */
-/*ca*/	u8	nc_rbc2;	/*                                  */
-/*cb*/	u8	nc_rbc3;	/*                                  */
-
-/*cc*/	u8	nc_ua;		/* Updated Address                  */
-/*cd*/	u8	nc_ua1;		/*                                  */
-/*ce*/	u8	nc_ua2;		/*                                  */
-/*cf*/	u8	nc_ua3;		/*                                  */
-/*d0*/	u32	nc_esa;		/* Entry Storage Address            */
-/*d4*/	u8	nc_ia;		/* Instruction Address              */
-/*d5*/	u8	nc_ia1;
-/*d6*/	u8	nc_ia2;
-/*d7*/	u8	nc_ia3;
-/*d8*/	u32	nc_sbc;		/* SCSI Byte Count (3 bytes only)   */
-/*dc*/	u32	nc_csbc;	/* Cumulative SCSI Byte Count       */
-
-				/* Following for C1010 only         */
-/*e0*/  u16	nc_crcpad;	/* CRC Value                        */
-/*e2*/  u8	nc_crccntl0;	/* CRC control register             */
-	#define   SNDCRC  0x10	/* Send CRC Request                 */
-/*e3*/  u8	nc_crccntl1;	/* CRC control register             */
-/*e4*/  u32	nc_crcdata;	/* CRC data register                */ 
-/*e8*/  u32	nc_e8_;		/* rsvd 			    */
-/*ec*/  u32	nc_ec_;		/* rsvd 			    */
-/*f0*/  u16	nc_dfbc;	/* DMA FIFO byte count              */ 
-
-};
-
-/*-----------------------------------------------------------
-**
-**	Utility macros for the script.
-**
-**-----------------------------------------------------------
-*/
-
-#define REGJ(p,r) (offsetof(struct ncr_reg, p ## r))
-#define REG(r) REGJ (nc_, r)
-
-typedef u32 ncrcmd;
-
-/*-----------------------------------------------------------
-**
-**	SCSI phases
-**
-**	DT phases illegal for ncr driver.
-**
-**-----------------------------------------------------------
-*/
-
-#define	SCR_DATA_OUT	0x00000000
-#define	SCR_DATA_IN	0x01000000
-#define	SCR_COMMAND	0x02000000
-#define	SCR_STATUS	0x03000000
-#define SCR_DT_DATA_OUT	0x04000000
-#define SCR_DT_DATA_IN	0x05000000
-#define SCR_MSG_OUT	0x06000000
-#define SCR_MSG_IN      0x07000000
-
-#define SCR_ILG_OUT	0x04000000
-#define SCR_ILG_IN	0x05000000
-
-/*-----------------------------------------------------------
-**
-**	Data transfer via SCSI.
-**
-**-----------------------------------------------------------
-**
-**	MOVE_ABS (LEN)
-**	<<start address>>
-**
-**	MOVE_IND (LEN)
-**	<<dnad_offset>>
-**
-**	MOVE_TBL
-**	<<dnad_offset>>
-**
-**-----------------------------------------------------------
-*/
-
-#define OPC_MOVE          0x08000000
-
-#define SCR_MOVE_ABS(l) ((0x00000000 | OPC_MOVE) | (l))
-#define SCR_MOVE_IND(l) ((0x20000000 | OPC_MOVE) | (l))
-#define SCR_MOVE_TBL     (0x10000000 | OPC_MOVE)
-
-#define SCR_CHMOV_ABS(l) ((0x00000000) | (l))
-#define SCR_CHMOV_IND(l) ((0x20000000) | (l))
-#define SCR_CHMOV_TBL     (0x10000000)
-
-struct scr_tblmove {
-        u32  size;
-        u32  addr;
-};
-
-/*-----------------------------------------------------------
-**
-**	Selection
-**
-**-----------------------------------------------------------
-**
-**	SEL_ABS | SCR_ID (0..15)    [ | REL_JMP]
-**	<<alternate_address>>
-**
-**	SEL_TBL | << dnad_offset>>  [ | REL_JMP]
-**	<<alternate_address>>
-**
-**-----------------------------------------------------------
-*/
-
-#define	SCR_SEL_ABS	0x40000000
-#define	SCR_SEL_ABS_ATN	0x41000000
-#define	SCR_SEL_TBL	0x42000000
-#define	SCR_SEL_TBL_ATN	0x43000000
-
-
-#ifdef SCSI_NCR_BIG_ENDIAN
-struct scr_tblsel {
-        u8	sel_scntl3;
-        u8	sel_id;
-        u8	sel_sxfer;
-        u8	sel_scntl4;	
-};
-#else
-struct scr_tblsel {
-        u8	sel_scntl4;	
-        u8	sel_sxfer;
-        u8	sel_id;
-        u8	sel_scntl3;
-};
-#endif
-
-#define SCR_JMP_REL     0x04000000
-#define SCR_ID(id)	(((u32)(id)) << 16)
-
-/*-----------------------------------------------------------
-**
-**	Waiting for Disconnect or Reselect
-**
-**-----------------------------------------------------------
-**
-**	WAIT_DISC
-**	dummy: <<alternate_address>>
-**
-**	WAIT_RESEL
-**	<<alternate_address>>
-**
-**-----------------------------------------------------------
-*/
-
-#define	SCR_WAIT_DISC	0x48000000
-#define SCR_WAIT_RESEL  0x50000000
-
-/*-----------------------------------------------------------
-**
-**	Bit Set / Reset
-**
-**-----------------------------------------------------------
-**
-**	SET (flags {|.. })
-**
-**	CLR (flags {|.. })
-**
-**-----------------------------------------------------------
-*/
-
-#define SCR_SET(f)     (0x58000000 | (f))
-#define SCR_CLR(f)     (0x60000000 | (f))
-
-#define	SCR_CARRY	0x00000400
-#define	SCR_TRG		0x00000200
-#define	SCR_ACK		0x00000040
-#define	SCR_ATN		0x00000008
-
-
-
-
-/*-----------------------------------------------------------
-**
-**	Memory to memory move
-**
-**-----------------------------------------------------------
-**
-**	COPY (bytecount)
-**	<< source_address >>
-**	<< destination_address >>
-**
-**	SCR_COPY   sets the NO FLUSH option by default.
-**	SCR_COPY_F does not set this option.
-**
-**	For chips which do not support this option,
-**	ncr_copy_and_bind() will remove this bit.
-**-----------------------------------------------------------
-*/
-
-#define SCR_NO_FLUSH 0x01000000
-
-#define SCR_COPY(n) (0xc0000000 | SCR_NO_FLUSH | (n))
-#define SCR_COPY_F(n) (0xc0000000 | (n))
-
-/*-----------------------------------------------------------
-**
-**	Register move and binary operations
-**
-**-----------------------------------------------------------
-**
-**	SFBR_REG (reg, op, data)        reg  = SFBR op data
-**	<< 0 >>
-**
-**	REG_SFBR (reg, op, data)        SFBR = reg op data
-**	<< 0 >>
-**
-**	REG_REG  (reg, op, data)        reg  = reg op data
-**	<< 0 >>
-**
-**-----------------------------------------------------------
-**	On 810A, 860, 825A, 875, 895 and 896 chips the content 
-**	of SFBR register can be used as data (SCR_SFBR_DATA).
-**	The 896 has additionnal IO registers starting at 
-**	offset 0x80. Bit 7 of register offset is stored in 
-**	bit 7 of the SCRIPTS instruction first DWORD.
-**-----------------------------------------------------------
-*/
-
-#define SCR_REG_OFS(ofs) ((((ofs) & 0x7f) << 16ul) + ((ofs) & 0x80)) 
-
-#define SCR_SFBR_REG(reg,op,data) \
-        (0x68000000 | (SCR_REG_OFS(REG(reg))) | (op) | (((data)&0xff)<<8ul))
-
-#define SCR_REG_SFBR(reg,op,data) \
-        (0x70000000 | (SCR_REG_OFS(REG(reg))) | (op) | (((data)&0xff)<<8ul))
-
-#define SCR_REG_REG(reg,op,data) \
-        (0x78000000 | (SCR_REG_OFS(REG(reg))) | (op) | (((data)&0xff)<<8ul))
-
-
-#define      SCR_LOAD   0x00000000
-#define      SCR_SHL    0x01000000
-#define      SCR_OR     0x02000000
-#define      SCR_XOR    0x03000000
-#define      SCR_AND    0x04000000
-#define      SCR_SHR    0x05000000
-#define      SCR_ADD    0x06000000
-#define      SCR_ADDC   0x07000000
-
-#define      SCR_SFBR_DATA   (0x00800000>>8ul)	/* Use SFBR as data */
-
-/*-----------------------------------------------------------
-**
-**	FROM_REG (reg)		  SFBR = reg
-**	<< 0 >>
-**
-**	TO_REG	 (reg)		  reg  = SFBR
-**	<< 0 >>
-**
-**	LOAD_REG (reg, data)	  reg  = <data>
-**	<< 0 >>
-**
-**	LOAD_SFBR(data) 	  SFBR = <data>
-**	<< 0 >>
-**
-**-----------------------------------------------------------
-*/
-
-#define	SCR_FROM_REG(reg) \
-	SCR_REG_SFBR(reg,SCR_OR,0)
-
-#define	SCR_TO_REG(reg) \
-	SCR_SFBR_REG(reg,SCR_OR,0)
-
-#define	SCR_LOAD_REG(reg,data) \
-	SCR_REG_REG(reg,SCR_LOAD,data)
-
-#define SCR_LOAD_SFBR(data) \
-        (SCR_REG_SFBR (gpreg, SCR_LOAD, data))
-
-/*-----------------------------------------------------------
-**
-**	LOAD  from memory   to register.
-**	STORE from register to memory.
-**
-**	Only supported by 810A, 860, 825A, 875, 895 and 896.
-**
-**-----------------------------------------------------------
-**
-**	LOAD_ABS (LEN)
-**	<<start address>>
-**
-**	LOAD_REL (LEN)        (DSA relative)
-**	<<dsa_offset>>
-**
-**-----------------------------------------------------------
-*/
-
-#define SCR_REG_OFS2(ofs) (((ofs) & 0xff) << 16ul)
-#define SCR_NO_FLUSH2	0x02000000
-#define SCR_DSA_REL2	0x10000000
-
-#define SCR_LOAD_R(reg, how, n) \
-        (0xe1000000 | how | (SCR_REG_OFS2(REG(reg))) | (n))
-
-#define SCR_STORE_R(reg, how, n) \
-        (0xe0000000 | how | (SCR_REG_OFS2(REG(reg))) | (n))
-
-#define SCR_LOAD_ABS(reg, n)	SCR_LOAD_R(reg, SCR_NO_FLUSH2, n)
-#define SCR_LOAD_REL(reg, n)	SCR_LOAD_R(reg, SCR_NO_FLUSH2|SCR_DSA_REL2, n)
-#define SCR_LOAD_ABS_F(reg, n)	SCR_LOAD_R(reg, 0, n)
-#define SCR_LOAD_REL_F(reg, n)	SCR_LOAD_R(reg, SCR_DSA_REL2, n)
-
-#define SCR_STORE_ABS(reg, n)	SCR_STORE_R(reg, SCR_NO_FLUSH2, n)
-#define SCR_STORE_REL(reg, n)	SCR_STORE_R(reg, SCR_NO_FLUSH2|SCR_DSA_REL2,n)
-#define SCR_STORE_ABS_F(reg, n)	SCR_STORE_R(reg, 0, n)
-#define SCR_STORE_REL_F(reg, n)	SCR_STORE_R(reg, SCR_DSA_REL2, n)
-
-
-/*-----------------------------------------------------------
-**
-**	Waiting for Disconnect or Reselect
-**
-**-----------------------------------------------------------
-**
-**	JUMP            [ | IFTRUE/IFFALSE ( ... ) ]
-**	<<address>>
-**
-**	JUMPR           [ | IFTRUE/IFFALSE ( ... ) ]
-**	<<distance>>
-**
-**	CALL            [ | IFTRUE/IFFALSE ( ... ) ]
-**	<<address>>
-**
-**	CALLR           [ | IFTRUE/IFFALSE ( ... ) ]
-**	<<distance>>
-**
-**	RETURN          [ | IFTRUE/IFFALSE ( ... ) ]
-**	<<dummy>>
-**
-**	INT             [ | IFTRUE/IFFALSE ( ... ) ]
-**	<<ident>>
-**
-**	INT_FLY         [ | IFTRUE/IFFALSE ( ... ) ]
-**	<<ident>>
-**
-**	Conditions:
-**	     WHEN (phase)
-**	     IF   (phase)
-**	     CARRYSET
-**	     DATA (data, mask)
-**
-**-----------------------------------------------------------
-*/
-
-#define SCR_NO_OP       0x80000000
-#define SCR_JUMP        0x80080000
-#define SCR_JUMP64      0x80480000
-#define SCR_JUMPR       0x80880000
-#define SCR_CALL        0x88080000
-#define SCR_CALLR       0x88880000
-#define SCR_RETURN      0x90080000
-#define SCR_INT         0x98080000
-#define SCR_INT_FLY     0x98180000
-
-#define IFFALSE(arg)   (0x00080000 | (arg))
-#define IFTRUE(arg)    (0x00000000 | (arg))
-
-#define WHEN(phase)    (0x00030000 | (phase))
-#define IF(phase)      (0x00020000 | (phase))
-
-#define DATA(D)        (0x00040000 | ((D) & 0xff))
-#define MASK(D,M)      (0x00040000 | (((M ^ 0xff) & 0xff) << 8ul)|((D) & 0xff))
-
-#define CARRYSET       (0x00200000)
-
-/*-----------------------------------------------------------
-**
-**	SCSI  constants.
-**
-**-----------------------------------------------------------
-*/
-
-/*
-**	Messages
-*/
-
-#define	M_COMPLETE	COMMAND_COMPLETE
-#define	M_EXTENDED	EXTENDED_MESSAGE
-#define	M_SAVE_DP	SAVE_POINTERS
-#define	M_RESTORE_DP	RESTORE_POINTERS
-#define	M_DISCONNECT	DISCONNECT
-#define	M_ID_ERROR	INITIATOR_ERROR
-#define	M_ABORT		ABORT_TASK_SET
-#define	M_REJECT	MESSAGE_REJECT
-#define	M_NOOP		NOP
-#define	M_PARITY	MSG_PARITY_ERROR
-#define	M_LCOMPLETE	LINKED_CMD_COMPLETE
-#define	M_FCOMPLETE	LINKED_FLG_CMD_COMPLETE
-#define	M_RESET		TARGET_RESET
-#define	M_ABORT_TAG	ABORT_TASK
-#define	M_CLEAR_QUEUE	CLEAR_TASK_SET
-#define	M_INIT_REC	INITIATE_RECOVERY
-#define	M_REL_REC	RELEASE_RECOVERY
-#define	M_TERMINATE	(0x11)
-#define	M_SIMPLE_TAG	SIMPLE_QUEUE_TAG
-#define	M_HEAD_TAG	HEAD_OF_QUEUE_TAG
-#define	M_ORDERED_TAG	ORDERED_QUEUE_TAG
-#define	M_IGN_RESIDUE	IGNORE_WIDE_RESIDUE
-#define	M_IDENTIFY   	(0x80)
-
-#define	M_X_MODIFY_DP	EXTENDED_MODIFY_DATA_POINTER
-#define	M_X_SYNC_REQ	EXTENDED_SDTR
-#define	M_X_WIDE_REQ	EXTENDED_WDTR
-#define	M_X_PPR_REQ	EXTENDED_PPR
-
-/*
-**	Status
-*/
-
-#define	S_GOOD		(0x00)
-#define	S_CHECK_COND	(0x02)
-#define	S_COND_MET	(0x04)
-#define	S_BUSY		(0x08)
-#define	S_INT		(0x10)
-#define	S_INT_COND_MET	(0x14)
-#define	S_CONFLICT	(0x18)
-#define	S_TERMINATED	(0x20)
-#define	S_QUEUE_FULL	(0x28)
-#define	S_ILLEGAL	(0xff)
-#define	S_SENSE		(0x80)
-
-/*
- * End of ncrreg from FreeBSD
- */
-
-#endif /* defined SYM53C8XX_DEFS_H */
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
index b8727d9bf690..1288d6203e94 100644
--- a/drivers/serial/mpc52xx_uart.c
+++ b/drivers/serial/mpc52xx_uart.c
@@ -37,11 +37,11 @@
  * by the bootloader or in the platform init code.
  *
  * The idx field must be equal to the PSC index ( e.g. 0 for PSC1, 1 for PSC2,
- * and so on). So the PSC1 is mapped to /dev/ttyS0, PSC2 to /dev/ttyS1 and so
- * on. But be warned, it's an ABSOLUTE REQUIREMENT ! This is needed mainly for
- * the console code : without this 1:1 mapping, at early boot time, when we are
- * parsing the kernel args console=ttyS?, we wouldn't know wich PSC it will be
- * mapped to.
+ * and so on). So the PSC1 is mapped to /dev/ttyPSC0, PSC2 to /dev/ttyPSC1 and
+ * so on. But be warned, it's an ABSOLUTE REQUIREMENT ! This is needed mainly
+ * fpr the console code : without this 1:1 mapping, at early boot time, when we
+ * are parsing the kernel args console=ttyPSC?, we wouldn't know wich PSC it
+ * will be mapped to.
  */
 
 #include <linux/config.h>
@@ -65,6 +65,10 @@
 #include <linux/serial_core.h>
 
 
+/* We've been assigned a range on the "Low-density serial ports" major */
+#define SERIAL_PSC_MAJOR	204
+#define SERIAL_PSC_MINOR	148
+
 
 #define ISR_PASS_LIMIT 256	/* Max number of iteration in the interrupt */
 
@@ -668,15 +672,15 @@ mpc52xx_console_setup(struct console *co, char *options)
 }
 
 
-extern struct uart_driver mpc52xx_uart_driver;
+static struct uart_driver mpc52xx_uart_driver;
 
 static struct console mpc52xx_console = {
-	.name	= "ttyS",
+	.name	= "ttyPSC",
 	.write	= mpc52xx_console_write,
 	.device	= uart_console_device,
 	.setup	= mpc52xx_console_setup,
 	.flags	= CON_PRINTBUFFER,
-	.index	= -1,	/* Specified on the cmdline (e.g. console=ttyS0 ) */
+	.index	= -1,	/* Specified on the cmdline (e.g. console=ttyPSC0 ) */
 	.data	= &mpc52xx_uart_driver,
 };
 
@@ -703,10 +707,10 @@ console_initcall(mpc52xx_console_init);
 static struct uart_driver mpc52xx_uart_driver = {
 	.owner		= THIS_MODULE,
 	.driver_name	= "mpc52xx_psc_uart",
-	.dev_name	= "ttyS",
-	.devfs_name	= "ttyS",
-	.major		= TTY_MAJOR,
-	.minor		= 64,
+	.dev_name	= "ttyPSC",
+	.devfs_name	= "ttyPSC",
+	.major		= SERIAL_PSC_MAJOR,
+	.minor		= SERIAL_PSC_MINOR,
 	.nr		= MPC52xx_PSC_MAXNUM,
 	.cons		= MPC52xx_PSC_CONSOLE,
 };
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index 7ce0c7e66d37..96969cb960a9 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -114,15 +114,7 @@ struct serial_cfg_mem {
 
 
 static void serial_config(dev_link_t * link);
-static int serial_event(event_t event, int priority,
-			event_callback_args_t * args);
 
-static dev_info_t dev_info = "serial_cs";
-
-static dev_link_t *serial_attach(void);
-static void serial_detach(dev_link_t *);
-
-static dev_link_t *dev_list = NULL;
 
 /*======================================================================
 
@@ -159,8 +151,9 @@ static void serial_remove(dev_link_t *link)
 	}
 }
 
-static void serial_suspend(dev_link_t *link)
+static int serial_suspend(struct pcmcia_device *dev)
 {
+	dev_link_t *link = dev_to_instance(dev);
 	link->state |= DEV_SUSPEND;
 
 	if (link->state & DEV_CONFIG) {
@@ -173,10 +166,13 @@ static void serial_suspend(dev_link_t *link)
 		if (!info->slave)
 			pcmcia_release_configuration(link->handle);
 	}
+
+	return 0;
 }
 
-static void serial_resume(dev_link_t *link)
+static int serial_resume(struct pcmcia_device *dev)
 {
+	dev_link_t *link = dev_to_instance(dev);
 	link->state &= ~DEV_SUSPEND;
 
 	if (DEV_OK(link)) {
@@ -189,6 +185,8 @@ static void serial_resume(dev_link_t *link)
 		for (i = 0; i < info->ndev; i++)
 			serial8250_resume_port(info->line[i]);
 	}
+
+	return 0;
 }
 
 /*======================================================================
@@ -199,19 +197,17 @@ static void serial_resume(dev_link_t *link)
 
 ======================================================================*/
 
-static dev_link_t *serial_attach(void)
+static int serial_probe(struct pcmcia_device *p_dev)
 {
 	struct serial_info *info;
-	client_reg_t client_reg;
 	dev_link_t *link;
-	int ret;
 
 	DEBUG(0, "serial_attach()\n");
 
 	/* Create new serial device */
 	info = kmalloc(sizeof (*info), GFP_KERNEL);
 	if (!info)
-		return NULL;
+		return -ENOMEM;
 	memset(info, 0, sizeof (*info));
 	link = &info->link;
 	link->priv = info;
@@ -227,20 +223,12 @@ static dev_link_t *serial_attach(void)
 	}
 	link->conf.IntType = INT_MEMORY_AND_IO;
 
-	/* Register with Card Services */
-	link->next = dev_list;
-	dev_list = link;
-	client_reg.dev_info = &dev_info;
-	client_reg.Version = 0x0210;
-	client_reg.event_callback_args.client_data = link;
-	ret = pcmcia_register_client(&link->handle, &client_reg);
-	if (ret != CS_SUCCESS) {
-		cs_error(link->handle, RegisterClient, ret);
-		serial_detach(link);
-		return NULL;
-	}
+	link->handle = p_dev;
+	p_dev->instance = link;
+	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+	serial_config(link);
 
-	return link;
+	return 0;
 }
 
 /*======================================================================
@@ -252,21 +240,13 @@ static dev_link_t *serial_attach(void)
 
 ======================================================================*/
 
-static void serial_detach(dev_link_t * link)
+static void serial_detach(struct pcmcia_device *p_dev)
 {
+	dev_link_t *link = dev_to_instance(p_dev);
 	struct serial_info *info = link->priv;
-	dev_link_t **linkp;
-	int ret;
 
 	DEBUG(0, "serial_detach(0x%p)\n", link);
 
-	/* Locate device structure */
-	for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
-		if (*linkp == link)
-			break;
-	if (*linkp == NULL)
-		return;
-
 	/*
 	 * Ensure any outstanding scheduled tasks are completed.
 	 */
@@ -277,14 +257,7 @@ static void serial_detach(dev_link_t * link)
 	 */
 	serial_remove(link);
 
-	if (link->handle) {
-		ret = pcmcia_deregister_client(link->handle);
-		if (ret != CS_SUCCESS)
-			cs_error(link->handle, DeregisterClient, ret);
-	}
-
-	/* Unlink device structure, free bits */
-	*linkp = link->next;
+	/* free bits */
 	kfree(info);
 }
 
@@ -718,54 +691,6 @@ void serial_config(dev_link_t * link)
 	kfree(cfg_mem);
 }
 
-/*======================================================================
-
-    The card status event handler.  Mostly, this schedules other
-    stuff to run after an event is received.  A CARD_REMOVAL event
-    also sets some flags to discourage the serial drivers from
-    talking to the ports.
-    
-======================================================================*/
-
-static int
-serial_event(event_t event, int priority, event_callback_args_t * args)
-{
-	dev_link_t *link = args->client_data;
-	struct serial_info *info = link->priv;
-
-	DEBUG(1, "serial_event(0x%06x)\n", event);
-
-	switch (event) {
-	case CS_EVENT_CARD_REMOVAL:
-		serial_remove(link);
-		break;
-
-	case CS_EVENT_CARD_INSERTION:
-		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-		serial_config(link);
-		break;
-
-	case CS_EVENT_PM_SUSPEND:
-		serial_suspend(link);
-		break;
-
-	case CS_EVENT_RESET_PHYSICAL:
-		if ((link->state & DEV_CONFIG) && !info->slave)
-			pcmcia_release_configuration(link->handle);
-		break;
-
-	case CS_EVENT_PM_RESUME:
-		serial_resume(link);
-		break;
-
-	case CS_EVENT_CARD_RESET:
-		if (DEV_OK(link) && !info->slave)
-			pcmcia_request_configuration(link->handle, &link->conf);
-		break;
-	}
-	return 0;
-}
-
 static struct pcmcia_device_id serial_ids[] = {
 	PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0057, 0x0021),
 	PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0089, 0x110a),
@@ -877,10 +802,11 @@ static struct pcmcia_driver serial_cs_driver = {
 	.drv		= {
 		.name	= "serial_cs",
 	},
-	.attach		= serial_attach,
-	.event		= serial_event,
-	.detach		= serial_detach,
+	.probe		= serial_probe,
+	.remove		= serial_detach,
 	.id_table	= serial_ids,
+	.suspend	= serial_suspend,
+	.resume		= serial_resume,
 };
 
 static int __init init_serial_cs(void)
@@ -891,7 +817,6 @@ static int __init init_serial_cs(void)
 static void __exit exit_serial_cs(void)
 {
 	pcmcia_unregister_driver(&serial_cs_driver);
-	BUG_ON(dev_list != NULL);
 }
 
 module_init(init_serial_cs);
diff --git a/drivers/telephony/ixj_pcmcia.c b/drivers/telephony/ixj_pcmcia.c
index 57c0c6e3fbed..d3a7b0c3d38b 100644
--- a/drivers/telephony/ixj_pcmcia.c
+++ b/drivers/telephony/ixj_pcmcia.c
@@ -34,24 +34,19 @@ typedef struct ixj_info_t {
 	struct ixj *port;
 } ixj_info_t;
 
-static dev_link_t *ixj_attach(void);
-static void ixj_detach(dev_link_t *);
+static void ixj_detach(struct pcmcia_device *p_dev);
 static void ixj_config(dev_link_t * link);
 static void ixj_cs_release(dev_link_t * link);
-static int ixj_event(event_t event, int priority, event_callback_args_t * args);
-static dev_info_t dev_info = "ixj_cs";
-static dev_link_t *dev_list = NULL;
 
-static dev_link_t *ixj_attach(void)
+static int ixj_attach(struct pcmcia_device *p_dev)
 {
-	client_reg_t client_reg;
 	dev_link_t *link;
-	int ret;
+
 	DEBUG(0, "ixj_attach()\n");
 	/* Create new ixj device */
 	link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
 	if (!link)
-		return NULL;
+		return -ENOMEM;
 	memset(link, 0, sizeof(struct dev_link_t));
 	link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
 	link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
@@ -61,44 +56,29 @@ static dev_link_t *ixj_attach(void)
 	link->priv = kmalloc(sizeof(struct ixj_info_t), GFP_KERNEL);
 	if (!link->priv) {
 		kfree(link);
-		return NULL;
+		return -ENOMEM;
 	}
 	memset(link->priv, 0, sizeof(struct ixj_info_t));
-	/* Register with Card Services */
-	link->next = dev_list;
-	dev_list = link;
-	client_reg.dev_info = &dev_info;
-	client_reg.Version = 0x0210;
-	client_reg.event_callback_args.client_data = link;
-	ret = pcmcia_register_client(&link->handle, &client_reg);
-	if (ret != CS_SUCCESS) {
-		cs_error(link->handle, RegisterClient, ret);
-		ixj_detach(link);
-		return NULL;
-	}
-	return link;
+
+	link->handle = p_dev;
+	p_dev->instance = link;
+
+	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+	ixj_config(link);
+
+	return 0;
 }
 
-static void ixj_detach(dev_link_t * link)
+static void ixj_detach(struct pcmcia_device *p_dev)
 {
-	dev_link_t **linkp;
-	int ret;
+	dev_link_t *link = dev_to_instance(p_dev);
+
 	DEBUG(0, "ixj_detach(0x%p)\n", link);
-	for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
-		if (*linkp == link)
-			break;
-	if (*linkp == NULL)
-		return;
+
 	link->state &= ~DEV_RELEASE_PENDING;
 	if (link->state & DEV_CONFIG)
 		ixj_cs_release(link);
-	if (link->handle) {
-		ret = pcmcia_deregister_client(link->handle);
-		if (ret != CS_SUCCESS)
-			cs_error(link->handle, DeregisterClient, ret);
-	}
-	/* Unlink device structure, free bits */
-	*linkp = link->next;
+
         kfree(link->priv);
         kfree(link);
 }
@@ -255,37 +235,25 @@ static void ixj_cs_release(dev_link_t *link)
 	link->state &= ~DEV_CONFIG;
 }
 
-static int ixj_event(event_t event, int priority, event_callback_args_t * args)
+static int ixj_suspend(struct pcmcia_device *dev)
 {
-	dev_link_t *link = args->client_data;
-	DEBUG(1, "ixj_event(0x%06x)\n", event);
-	switch (event) {
-	case CS_EVENT_CARD_REMOVAL:
-		link->state &= ~DEV_PRESENT;
-		if (link->state & DEV_CONFIG) {
-			link->state |= DEV_RELEASE_PENDING;
-			ixj_cs_release(link);
-		}
-		break;
-	case CS_EVENT_CARD_INSERTION:
-		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-		ixj_config(link);
-		break;
-	case CS_EVENT_PM_SUSPEND:
-		link->state |= DEV_SUSPEND;
-		/* Fall through... */
-	case CS_EVENT_RESET_PHYSICAL:
-		if (link->state & DEV_CONFIG)
-			pcmcia_release_configuration(link->handle);
-		break;
-	case CS_EVENT_PM_RESUME:
-		link->state &= ~DEV_SUSPEND;
-		/* Fall through... */
-	case CS_EVENT_CARD_RESET:
-		if (DEV_OK(link))
-			pcmcia_request_configuration(link->handle, &link->conf);
-		break;
-	}
+	dev_link_t *link = dev_to_instance(dev);
+
+	link->state |= DEV_SUSPEND;
+	if (link->state & DEV_CONFIG)
+		pcmcia_release_configuration(link->handle);
+
+	return 0;
+}
+
+static int ixj_resume(struct pcmcia_device *dev)
+{
+	dev_link_t *link = dev_to_instance(dev);
+
+	link->state &= ~DEV_SUSPEND;
+	if (DEV_OK(link))
+		pcmcia_request_configuration(link->handle, &link->conf);
+
 	return 0;
 }
 
@@ -300,10 +268,11 @@ static struct pcmcia_driver ixj_driver = {
 	.drv		= {
 		.name	= "ixj_cs",
 	},
-	.attach		= ixj_attach,
-	.event		= ixj_event,
-	.detach		= ixj_detach,
+	.probe		= ixj_attach,
+	.remove		= ixj_detach,
 	.id_table	= ixj_ids,
+	.suspend	= ixj_suspend,
+	.resume		= ixj_resume,
 };
 
 static int __init ixj_pcmcia_init(void)
@@ -314,7 +283,6 @@ static int __init ixj_pcmcia_init(void)
 static void ixj_pcmcia_exit(void)
 {
 	pcmcia_unregister_driver(&ixj_driver);
-	BUG_ON(dev_list != NULL);
 }
 
 module_init(ixj_pcmcia_init);
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index a50c2bc506f2..3639c3f8d357 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_USB_MIDI)		+= class/
 obj-$(CONFIG_USB_PRINTER)	+= class/
 
 obj-$(CONFIG_USB_STORAGE)	+= storage/
+obj-$(CONFIG_USB)		+= storage/
 
 obj-$(CONFIG_USB_AIPTEK)	+= input/
 obj-$(CONFIG_USB_ATI_REMOTE)	+= input/
diff --git a/drivers/usb/atm/Kconfig b/drivers/usb/atm/Kconfig
index f429862e0974..550ddfa71a43 100644
--- a/drivers/usb/atm/Kconfig
+++ b/drivers/usb/atm/Kconfig
@@ -44,6 +44,19 @@ config USB_CXACRU
 	  To compile this driver as a module, choose M here: the
 	  module will be called cxacru.
 
+config USB_UEAGLEATM
+	tristate "ADI 930 and eagle USB DSL modem"
+	depends on USB_ATM
+	select FW_LOADER
+	help
+	  Say Y here if you have an ADSL USB modem based on the ADI 930
+	  or eagle chipset. In order to use your modem you will need to
+	  install firmwares and CMV (Command Management Variables); see
+	  <https://gna.org/projects/ueagleatm/> for details.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ueagle-atm.
+
 config USB_XUSBATM
 	tristate "Other USB DSL modem support"
 	depends on USB_ATM
diff --git a/drivers/usb/atm/Makefile b/drivers/usb/atm/Makefile
index 85099718c683..4c4a776ab1cd 100644
--- a/drivers/usb/atm/Makefile
+++ b/drivers/usb/atm/Makefile
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_USB_CXACRU)	+= cxacru.o
 obj-$(CONFIG_USB_SPEEDTOUCH)	+= speedtch.o
+obj-$(CONFIG_USB_UEAGLEATM)	+= ueagle-atm.o
 obj-$(CONFIG_USB_ATM)		+= usbatm.o
 obj-$(CONFIG_USB_XUSBATM)	+= xusbatm.o
 
diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c
index 9d59dc62e6d2..af0a41e7870e 100644
--- a/drivers/usb/atm/cxacru.c
+++ b/drivers/usb/atm/cxacru.c
@@ -853,7 +853,6 @@ static int cxacru_usb_probe(struct usb_interface *intf, const struct usb_device_
 }
 
 static struct usb_driver cxacru_usb_driver = {
-	.owner		= THIS_MODULE,
 	.name		= cxacru_driver_name,
 	.probe		= cxacru_usb_probe,
 	.disconnect	= usbatm_usb_disconnect,
diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c
index d0cbbb7f0385..b28336148658 100644
--- a/drivers/usb/atm/speedtch.c
+++ b/drivers/usb/atm/speedtch.c
@@ -659,7 +659,6 @@ MODULE_DEVICE_TABLE(usb, speedtch_usb_ids);
 static int speedtch_usb_probe(struct usb_interface *, const struct usb_device_id *);
 
 static struct usb_driver speedtch_usb_driver = {
-	.owner		= THIS_MODULE,
 	.name		= speedtch_driver_name,
 	.probe		= speedtch_usb_probe,
 	.disconnect	= usbatm_usb_disconnect,
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c
new file mode 100644
index 000000000000..7d2a679989ed
--- /dev/null
+++ b/drivers/usb/atm/ueagle-atm.c
@@ -0,0 +1,1820 @@
+/*-
+ * Copyright (c) 2003, 2004
+ *	Damien Bergamini <damien.bergamini@free.fr>. All rights reserved.
+ *
+ * Copyright (c) 2005 Matthieu Castet <castet.matthieu@free.fr>
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice unmodified, this list of conditions, and the following
+ *    disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * GPL license :
+ * 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.
+ *
+ *
+ * HISTORY : some part of the code was base on ueagle 1.3 BSD driver,
+ * Damien Bergamini agree to put his code under a DUAL GPL/BSD license.
+ *
+ * The rest of the code was was rewritten from scratch.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/crc32.h>
+#include <linux/usb.h>
+#include <linux/firmware.h>
+#include <linux/ctype.h>
+#include <linux/kthread.h>
+#include <linux/version.h>
+#include <asm/unaligned.h>
+
+#include "usbatm.h"
+
+#define EAGLEUSBVERSION "ueagle 1.1"
+
+
+/*
+ * Debug macros
+ */
+#define uea_dbg(usb_dev, format, args...)	\
+	do { \
+		if (debug >= 1) \
+			dev_dbg(&(usb_dev)->dev, \
+				"[ueagle-atm dbg] %s: " format, \
+					__FUNCTION__, ##args); \
+       } while (0)
+
+#define uea_vdbg(usb_dev, format, args...)	\
+	do { \
+		if (debug >= 2) \
+			dev_dbg(&(usb_dev)->dev, \
+				"[ueagle-atm vdbg]  " format, ##args); \
+       } while (0)
+
+#define uea_enters(usb_dev) \
+	uea_vdbg(usb_dev, "entering %s\n", __FUNCTION__)
+
+#define uea_leaves(usb_dev) \
+	uea_vdbg(usb_dev, "leaving  %s\n", __FUNCTION__)
+
+#define uea_err(usb_dev, format,args...) \
+	dev_err(&(usb_dev)->dev ,"[UEAGLE-ATM] " format , ##args)
+
+#define uea_warn(usb_dev, format,args...) \
+	dev_warn(&(usb_dev)->dev ,"[Ueagle-atm] " format, ##args)
+
+#define uea_info(usb_dev, format,args...) \
+	dev_info(&(usb_dev)->dev ,"[ueagle-atm] " format, ##args)
+
+struct uea_cmvs {
+	u32 address;
+	u16 offset;
+	u32 data;
+} __attribute__ ((packed));
+
+struct uea_softc {
+	struct usb_device *usb_dev;
+	struct usbatm_data *usbatm;
+
+	int modem_index;
+	unsigned int driver_info;
+
+	int booting;
+	int reset;
+
+	wait_queue_head_t sync_q;
+
+	struct task_struct *kthread;
+	u32 data;
+	wait_queue_head_t cmv_ack_wait;
+	int cmv_ack;
+
+	struct work_struct task;
+	u16 pageno;
+	u16 ovl;
+
+	const struct firmware *dsp_firm;
+	struct urb *urb_int;
+
+	u8 cmv_function;
+	u16 cmv_idx;
+	u32 cmv_address;
+	u16 cmv_offset;
+
+	/* keep in sync with eaglectl */
+	struct uea_stats {
+		struct {
+			u32 state;
+			u32 flags;
+			u32 mflags;
+			u32 vidcpe;
+			u32 vidco;
+			u32 dsrate;
+			u32 usrate;
+			u32 dsunc;
+			u32 usunc;
+			u32 dscorr;
+			u32 uscorr;
+			u32 txflow;
+			u32 rxflow;
+			u32 usattenuation;
+			u32 dsattenuation;
+			u32 dsmargin;
+			u32 usmargin;
+			u32 firmid;
+		} phy;
+	} stats;
+};
+
+/*
+ * Elsa IDs
+ */
+#define ELSA_VID		0x05CC
+#define ELSA_PID_PSTFIRM	0x3350
+#define ELSA_PID_PREFIRM	0x3351
+
+/*
+ * Sagem USB IDs
+ */
+#define EAGLE_VID		0x1110
+#define EAGLE_I_PID_PREFIRM	0x9010	/* Eagle I */
+#define EAGLE_I_PID_PSTFIRM	0x900F	/* Eagle I */
+
+#define EAGLE_IIC_PID_PREFIRM	0x9024	/* Eagle IIC */
+#define EAGLE_IIC_PID_PSTFIRM	0x9023	/* Eagle IIC */
+
+#define EAGLE_II_PID_PREFIRM	0x9022	/* Eagle II */
+#define EAGLE_II_PID_PSTFIRM	0x9021	/* Eagle II */
+
+/*
+ *  Eagle III Pid
+ */
+#define EAGLE_III_PID_PREFIRM	0x9032	/* Eagle III */
+#define EAGLE_III_PID_PSTFIRM	0x9031	/* Eagle III */
+
+/*
+ * USR USB IDs
+ */
+#define USR_VID			0x0BAF
+#define MILLER_A_PID_PREFIRM	0x00F2
+#define MILLER_A_PID_PSTFIRM	0x00F1
+#define MILLER_B_PID_PREFIRM	0x00FA
+#define MILLER_B_PID_PSTFIRM	0x00F9
+#define HEINEKEN_A_PID_PREFIRM	0x00F6
+#define HEINEKEN_A_PID_PSTFIRM	0x00F5
+#define HEINEKEN_B_PID_PREFIRM	0x00F8
+#define HEINEKEN_B_PID_PSTFIRM	0x00F7
+
+#define PREFIRM 0
+#define PSTFIRM (1<<7)
+enum {
+	ADI930 = 0,
+	EAGLE_I,
+	EAGLE_II,
+	EAGLE_III
+};
+
+/* macros for both struct usb_device_id and struct uea_softc */
+#define UEA_IS_PREFIRM(x) \
+	(!((x)->driver_info & PSTFIRM))
+#define UEA_CHIP_VERSION(x) \
+	((x)->driver_info & 0xf)
+
+#define IS_ISDN(sc) \
+	(le16_to_cpu(sc->usb_dev->descriptor.bcdDevice) & 0x80)
+
+#define INS_TO_USBDEV(ins) ins->usb_dev
+
+#define GET_STATUS(data) \
+	((data >> 8) & 0xf)
+#define IS_OPERATIONAL(sc) \
+	(GET_STATUS(sc->stats.phy.state) == 2)
+
+/*
+ * Set of macros to handle unaligned data in the firmware blob.
+ * The FW_GET_BYTE() macro is provided only for consistency.
+ */
+
+#define FW_GET_BYTE(p)	*((__u8 *) (p))
+#define FW_GET_WORD(p)	le16_to_cpu(get_unaligned((__le16 *) (p)))
+#define FW_GET_LONG(p)	le32_to_cpu(get_unaligned((__le32 *) (p)))
+
+#define FW_DIR "ueagle-atm/"
+#define NB_MODEM 4
+
+#define BULK_TIMEOUT 300
+#define CTRL_TIMEOUT 1000
+
+#define ACK_TIMEOUT msecs_to_jiffies(1500)
+
+#define UEA_INTR_IFACE_NO 	0
+#define UEA_US_IFACE_NO		1
+#define UEA_DS_IFACE_NO		2
+
+#define FASTEST_ISO_INTF	8
+
+#define UEA_BULK_DATA_PIPE	0x02
+#define UEA_IDMA_PIPE		0x04
+#define UEA_INTR_PIPE		0x04
+#define UEA_ISO_DATA_PIPE	0x08
+
+#define UEA_SET_BLOCK    	0x0001
+#define UEA_SET_MODE     	0x0003
+#define UEA_SET_2183_DATA	0x0004
+#define UEA_SET_TIMEOUT		0x0011
+
+#define UEA_LOOPBACK_OFF	0x0002
+#define UEA_LOOPBACK_ON		0x0003
+#define UEA_BOOT_IDMA		0x0006
+#define UEA_START_RESET		0x0007
+#define UEA_END_RESET		0x0008
+
+#define UEA_SWAP_MAILBOX	(0x3fcd | 0x4000)
+#define UEA_MPTX_START		(0x3fce | 0x4000)
+#define UEA_MPTX_MAILBOX	(0x3fd6 | 0x4000)
+#define UEA_MPRX_MAILBOX	(0x3fdf | 0x4000)
+
+/* structure describing a block within a DSP page */
+struct block_info {
+	__le16 wHdr;
+#define UEA_BIHDR 0xabcd
+	__le16 wAddress;
+	__le16 wSize;
+	__le16 wOvlOffset;
+	__le16 wOvl;		/* overlay */
+	__le16 wLast;
+} __attribute__ ((packed));
+#define BLOCK_INFO_SIZE 12
+
+/* structure representing a CMV (Configuration and Management Variable) */
+struct cmv {
+	__le16 wPreamble;
+#define PREAMBLE 0x535c
+	__u8 bDirection;
+#define MODEMTOHOST 0x01
+#define HOSTTOMODEM 0x10
+	__u8 bFunction;
+#define FUNCTION_TYPE(f)    ((f) >> 4)
+#define MEMACCESS	0x1
+#define ADSLDIRECTIVE	0x7
+
+#define FUNCTION_SUBTYPE(f) ((f) & 0x0f)
+/* for MEMACCESS */
+#define REQUESTREAD	0x0
+#define REQUESTWRITE	0x1
+#define REPLYREAD	0x2
+#define REPLYWRITE	0x3
+/* for ADSLDIRECTIVE */
+#define KERNELREADY	0x0
+#define MODEMREADY	0x1
+
+#define MAKEFUNCTION(t, s) (((t) & 0xf) << 4 | ((s) & 0xf))
+	__le16 wIndex;
+	__le32 dwSymbolicAddress;
+#define MAKESA(a, b, c, d)						\
+	(((c) & 0xff) << 24 |						\
+	 ((d) & 0xff) << 16 |						\
+	 ((a) & 0xff) << 8  |						\
+	 ((b) & 0xff))
+
+#define SA_CNTL MAKESA('C', 'N', 'T', 'L')
+#define SA_DIAG MAKESA('D', 'I', 'A', 'G')
+#define SA_INFO MAKESA('I', 'N', 'F', 'O')
+#define SA_OPTN MAKESA('O', 'P', 'T', 'N')
+#define SA_RATE MAKESA('R', 'A', 'T', 'E')
+#define SA_STAT MAKESA('S', 'T', 'A', 'T')
+	__le16 wOffsetAddress;
+	__le32 dwData;
+} __attribute__ ((packed));
+#define CMV_SIZE 16
+
+/* structure representing swap information */
+struct swap_info {
+	__u8 bSwapPageNo;
+	__u8 bOvl;		/* overlay */
+} __attribute__ ((packed));
+
+/* structure representing interrupt data */
+struct intr_pkt {
+	__u8 bType;
+	__u8 bNotification;
+	__le16 wValue;
+	__le16 wIndex;
+	__le16 wLength;
+	__le16 wInterrupt;
+#define INT_LOADSWAPPAGE 0x0001
+#define INT_INCOMINGCMV  0x0002
+	union {
+		struct {
+			struct swap_info swapinfo;
+			__le16 wDataSize;
+		} __attribute__ ((packed)) s1;
+
+		struct {
+			struct cmv cmv;
+			__le16 wDataSize;
+		} __attribute__ ((packed)) s2;
+	} __attribute__ ((packed)) u;
+#define bSwapPageNo	u.s1.swapinfo.bSwapPageNo
+#define bOvl		u.s1.swapinfo.bOvl
+} __attribute__ ((packed));
+#define INTR_PKT_SIZE 28
+
+static struct usb_driver uea_driver;
+static DECLARE_MUTEX(uea_semaphore);
+static const char *chip_name[] = {"ADI930", "Eagle I", "Eagle II", "Eagle III"};
+
+static int modem_index;
+static unsigned int debug;
+static int sync_wait[NB_MODEM];
+static char *cmv_file[NB_MODEM];
+
+module_param(debug, uint, 0644);
+MODULE_PARM_DESC(debug, "module debug level (0=off,1=on,2=verbose)");
+module_param_array(sync_wait, bool, NULL, 0644);
+MODULE_PARM_DESC(sync_wait, "wait the synchronisation before starting ATM");
+module_param_array(cmv_file, charp, NULL, 0644);
+MODULE_PARM_DESC(cmv_file,
+		"file name with configuration and management variables");
+
+#define UPDATE_ATM_STAT(type, val) \
+	do { \
+		if (sc->usbatm->atm_dev) \
+			sc->usbatm->atm_dev->type = val; \
+	} while (0)
+
+/* Firmware loading */
+#define LOAD_INTERNAL     0xA0
+#define F8051_USBCS       0x7f92
+
+/**
+ * uea_send_modem_cmd - Send a command for pre-firmware devices.
+ */
+static int uea_send_modem_cmd(struct usb_device *usb,
+		u16 addr, u16 size, u8 * buff)
+{
+	int ret = -ENOMEM;
+	u8 *xfer_buff;
+
+	xfer_buff = kmalloc(size, GFP_KERNEL);
+	if (xfer_buff) {
+		memcpy(xfer_buff, buff, size);
+		ret = usb_control_msg(usb,
+				      usb_sndctrlpipe(usb, 0),
+				      LOAD_INTERNAL,
+				      USB_DIR_OUT | USB_TYPE_VENDOR |
+				      USB_RECIP_DEVICE, addr, 0, xfer_buff,
+				      size, CTRL_TIMEOUT);
+		kfree(xfer_buff);
+	}
+
+	if (ret < 0)
+		return ret;
+
+	return (ret == size) ? 0 : -EIO;
+}
+
+static void uea_upload_pre_firmware(const struct firmware *fw_entry, void *context)
+{
+	struct usb_device *usb = context;
+	u8 *pfw, value;
+	u32 crc = 0;
+	int ret, size;
+
+	uea_enters(usb);
+	if (!fw_entry) {
+		uea_err(usb, "firmware is not available\n");
+		goto err;
+	}
+
+	pfw = fw_entry->data;
+	size = fw_entry->size;
+	if (size < 4)
+		goto err_fw_corrupted;
+
+	crc = FW_GET_LONG(pfw);
+	pfw += 4;
+	size -= 4;
+	if (crc32_be(0, pfw, size) != crc)
+		goto err_fw_corrupted;
+
+	/*
+	 * Start to upload formware : send reset
+	 */
+	value = 1;
+	ret = uea_send_modem_cmd(usb, F8051_USBCS, sizeof(value), &value);
+
+	if (ret < 0) {
+		uea_err(usb, "modem reset failed with error %d\n", ret);
+		goto err;
+	}
+
+	while (size > 3) {
+		u8 len = FW_GET_BYTE(pfw);
+		u16 add = FW_GET_WORD(pfw + 1);
+
+		size -= len + 3;
+		if (size < 0)
+			goto err_fw_corrupted;
+
+		ret = uea_send_modem_cmd(usb, add, len, pfw + 3);
+		if (ret < 0) {
+			uea_err(usb, "uploading firmware data failed "
+					"with error %d\n", ret);
+			goto err;
+		}
+		pfw += len + 3;
+	}
+
+	if (size != 0)
+		goto err_fw_corrupted;
+
+	/*
+	 * Tell the modem we finish : de-assert reset
+	 */
+	value = 0;
+	ret = uea_send_modem_cmd(usb, F8051_USBCS, 1, &value);
+	if (ret < 0)
+		uea_err(usb, "modem de-assert failed with error %d\n", ret);
+	else
+		uea_info(usb, "firmware uploaded\n");
+
+	uea_leaves(usb);
+	return;
+
+err_fw_corrupted:
+	uea_err(usb, "firmware is corrupted\n");
+err:
+	uea_leaves(usb);
+}
+
+/**
+ * uea_load_firmware - Load usb firmware for pre-firmware devices.
+ */
+static int uea_load_firmware(struct usb_device *usb, unsigned int ver)
+{
+	int ret;
+	char *fw_name = FW_DIR "eagle.fw";
+
+	uea_enters(usb);
+	uea_info(usb, "pre-firmware device, uploading firmware\n");
+
+	switch (ver) {
+	case ADI930:
+		fw_name = FW_DIR "adi930.fw";
+		break;
+	case EAGLE_I:
+		fw_name = FW_DIR "eagleI.fw";
+		break;
+	case EAGLE_II:
+		fw_name = FW_DIR "eagleII.fw";
+		break;
+	case EAGLE_III:
+		fw_name = FW_DIR "eagleIII.fw";
+		break;
+	}
+
+	ret = request_firmware_nowait(THIS_MODULE, 1, fw_name, &usb->dev, usb, uea_upload_pre_firmware);
+	if (ret)
+		uea_err(usb, "firmware %s is not available\n", fw_name);
+	else
+		uea_info(usb, "loading firmware %s\n", fw_name);
+
+	uea_leaves(usb);
+	return ret;
+}
+
+/* modem management : dsp firmware, send/read CMV, monitoring statistic
+ */
+
+/*
+ * Make sure that the DSP code provided is safe to use.
+ */
+static int check_dsp(u8 *dsp, unsigned int len)
+{
+	u8 pagecount, blockcount;
+	u16 blocksize;
+	u32 pageoffset;
+	unsigned int i, j, p, pp;
+
+	pagecount = FW_GET_BYTE(dsp);
+	p = 1;
+
+	/* enough space for page offsets? */
+	if (p + 4 * pagecount > len)
+		return 1;
+
+	for (i = 0; i < pagecount; i++) {
+
+		pageoffset = FW_GET_LONG(dsp + p);
+		p += 4;
+
+		if (pageoffset == 0)
+			continue;
+
+		/* enough space for blockcount? */
+		if (pageoffset >= len)
+			return 1;
+
+		pp = pageoffset;
+		blockcount = FW_GET_BYTE(dsp + pp);
+		pp += 1;
+
+		for (j = 0; j < blockcount; j++) {
+
+			/* enough space for block header? */
+			if (pp + 4 > len)
+				return 1;
+
+			pp += 2;	/* skip blockaddr */
+			blocksize = FW_GET_WORD(dsp + pp);
+			pp += 2;
+
+			/* enough space for block data? */
+			if (pp + blocksize > len)
+				return 1;
+
+			pp += blocksize;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * send data to the idma pipe
+ * */
+static int uea_idma_write(struct uea_softc *sc, void *data, u32 size)
+{
+	int ret = -ENOMEM;
+	u8 *xfer_buff;
+	int bytes_read;
+
+	xfer_buff = kmalloc(size, GFP_KERNEL);
+	if (!xfer_buff) {
+		uea_err(INS_TO_USBDEV(sc), "can't allocate xfer_buff\n");
+		return ret;
+	}
+
+	memcpy(xfer_buff, data, size);
+
+	ret = usb_bulk_msg(sc->usb_dev,
+			 usb_sndbulkpipe(sc->usb_dev, UEA_IDMA_PIPE),
+			 xfer_buff, size, &bytes_read, BULK_TIMEOUT);
+
+	kfree(xfer_buff);
+	if (ret < 0)
+		return ret;
+	if (size != bytes_read) {
+		uea_err(INS_TO_USBDEV(sc), "size != bytes_read %d %d\n", size,
+		       bytes_read);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int request_dsp(struct uea_softc *sc)
+{
+	int ret;
+	char *dsp_name;
+
+	if (UEA_CHIP_VERSION(sc) == ADI930) {
+		if (IS_ISDN(sc))
+			dsp_name = FW_DIR "DSP9i.bin";
+		else
+			dsp_name = FW_DIR "DSP9p.bin";
+	} else {
+		if (IS_ISDN(sc))
+			dsp_name = FW_DIR "DSPei.bin";
+		else
+			dsp_name = FW_DIR "DSPep.bin";
+	}
+
+	ret = request_firmware(&sc->dsp_firm,
+				dsp_name, &sc->usb_dev->dev);
+	if (ret < 0) {
+		uea_err(INS_TO_USBDEV(sc),
+		       "requesting firmware %s failed with error %d\n",
+		       dsp_name, ret);
+		return ret;
+	}
+
+	if (check_dsp(sc->dsp_firm->data, sc->dsp_firm->size)) {
+		uea_err(INS_TO_USBDEV(sc), "firmware %s is corrupted\n",
+		       dsp_name);
+		release_firmware(sc->dsp_firm);
+		sc->dsp_firm = NULL;
+		return -EILSEQ;
+	}
+
+	return 0;
+}
+
+/*
+ * The uea_load_page() function must be called within a process context
+ */
+static void uea_load_page(void *xsc)
+{
+	struct uea_softc *sc = xsc;
+	u16 pageno = sc->pageno;
+	u16 ovl = sc->ovl;
+	struct block_info bi;
+
+	u8 *p;
+	u8 pagecount, blockcount;
+	u16 blockaddr, blocksize;
+	u32 pageoffset;
+	int i;
+
+	/* reload firmware when reboot start and it's loaded already */
+	if (ovl == 0 && pageno == 0 && sc->dsp_firm) {
+		release_firmware(sc->dsp_firm);
+		sc->dsp_firm = NULL;
+	}
+
+	if (sc->dsp_firm == NULL && request_dsp(sc) < 0)
+		return;
+
+	p = sc->dsp_firm->data;
+	pagecount = FW_GET_BYTE(p);
+	p += 1;
+
+	if (pageno >= pagecount)
+		goto bad1;
+
+	p += 4 * pageno;
+	pageoffset = FW_GET_LONG(p);
+
+	if (pageoffset == 0)
+		goto bad1;
+
+	p = sc->dsp_firm->data + pageoffset;
+	blockcount = FW_GET_BYTE(p);
+	p += 1;
+
+	uea_dbg(INS_TO_USBDEV(sc),
+	       "sending %u blocks for DSP page %u\n", blockcount, pageno);
+
+	bi.wHdr = cpu_to_le16(UEA_BIHDR);
+	bi.wOvl = cpu_to_le16(ovl);
+	bi.wOvlOffset = cpu_to_le16(ovl | 0x8000);
+
+	for (i = 0; i < blockcount; i++) {
+		blockaddr = FW_GET_WORD(p);
+		p += 2;
+
+		blocksize = FW_GET_WORD(p);
+		p += 2;
+
+		bi.wSize = cpu_to_le16(blocksize);
+		bi.wAddress = cpu_to_le16(blockaddr);
+		bi.wLast = cpu_to_le16((i == blockcount - 1) ? 1 : 0);
+
+		/* send block info through the IDMA pipe */
+		if (uea_idma_write(sc, &bi, BLOCK_INFO_SIZE))
+			goto bad2;
+
+		/* send block data through the IDMA pipe */
+		if (uea_idma_write(sc, p, blocksize))
+			goto bad2;
+
+		p += blocksize;
+	}
+
+	return;
+
+bad2:
+	uea_err(INS_TO_USBDEV(sc), "sending DSP block %u failed\n", i);
+	return;
+bad1:
+	uea_err(INS_TO_USBDEV(sc), "invalid DSP page %u requested\n",pageno);
+}
+
+static inline void wake_up_cmv_ack(struct uea_softc *sc)
+{
+	sc->cmv_ack = 1;
+	wake_up(&sc->cmv_ack_wait);
+}
+
+static inline int wait_cmv_ack(struct uea_softc *sc)
+{
+	int ret = wait_event_timeout(sc->cmv_ack_wait,
+						   sc->cmv_ack, ACK_TIMEOUT);
+	sc->cmv_ack = 0;
+
+	if (ret < 0)
+		return ret;
+
+	return (ret == 0) ? -ETIMEDOUT : 0;
+
+}
+
+#define UCDC_SEND_ENCAPSULATED_COMMAND 0x00
+
+static int uea_request(struct uea_softc *sc,
+		u16 value, u16 index, u16 size, void *data)
+{
+	u8 *xfer_buff;
+	int ret = -ENOMEM;
+
+	xfer_buff = kmalloc(size, GFP_KERNEL);
+	if (!xfer_buff) {
+		uea_err(INS_TO_USBDEV(sc), "can't allocate xfer_buff\n");
+		return ret;
+	}
+	memcpy(xfer_buff, data, size);
+
+	ret = usb_control_msg(sc->usb_dev, usb_sndctrlpipe(sc->usb_dev, 0),
+			      UCDC_SEND_ENCAPSULATED_COMMAND,
+			      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			      value, index, xfer_buff, size, CTRL_TIMEOUT);
+
+	kfree(xfer_buff);
+	if (ret < 0) {
+		uea_err(INS_TO_USBDEV(sc), "usb_control_msg error %d\n", ret);
+		return ret;
+	}
+
+	if (ret != size) {
+		uea_err(INS_TO_USBDEV(sc),
+		       "usb_control_msg send only %d bytes (instead of %d)\n",
+		       ret, size);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int uea_cmv(struct uea_softc *sc,
+		u8 function, u32 address, u16 offset, u32 data)
+{
+	struct cmv cmv;
+	int ret;
+
+	/* we send a request, but we expect a reply */
+	sc->cmv_function = function | 0x2;
+	sc->cmv_idx++;
+	sc->cmv_address = address;
+	sc->cmv_offset = offset;
+
+	cmv.wPreamble = cpu_to_le16(PREAMBLE);
+	cmv.bDirection = HOSTTOMODEM;
+	cmv.bFunction = function;
+	cmv.wIndex = cpu_to_le16(sc->cmv_idx);
+	put_unaligned(cpu_to_le32(address), &cmv.dwSymbolicAddress);
+	cmv.wOffsetAddress = cpu_to_le16(offset);
+	put_unaligned(cpu_to_le32(data >> 16 | data << 16), &cmv.dwData);
+
+	ret = uea_request(sc, UEA_SET_BLOCK, UEA_MPTX_START, CMV_SIZE, &cmv);
+	if (ret < 0)
+		return ret;
+	return wait_cmv_ack(sc);
+}
+
+static inline int uea_read_cmv(struct uea_softc *sc,
+		u32 address, u16 offset, u32 *data)
+{
+	int ret = uea_cmv(sc, MAKEFUNCTION(MEMACCESS, REQUESTREAD),
+			  address, offset, 0);
+	if (ret < 0)
+		uea_err(INS_TO_USBDEV(sc),
+			"reading cmv failed with error %d\n", ret);
+	else
+	 	*data = sc->data;
+
+	return ret;
+}
+
+static inline int uea_write_cmv(struct uea_softc *sc,
+		u32 address, u16 offset, u32 data)
+{
+	int ret = uea_cmv(sc, MAKEFUNCTION(MEMACCESS, REQUESTWRITE),
+			  address, offset, data);
+	if (ret < 0)
+		uea_err(INS_TO_USBDEV(sc),
+			"writing cmv failed with error %d\n", ret);
+
+	return ret;
+}
+
+/*
+ * Monitor the modem and update the stat
+ * return 0 if everything is ok
+ * return < 0 if an error occurs (-EAGAIN reboot needed)
+ */
+static int uea_stat(struct uea_softc *sc)
+{
+	u32 data;
+	int ret;
+
+	uea_enters(INS_TO_USBDEV(sc));
+	data = sc->stats.phy.state;
+
+	ret = uea_read_cmv(sc, SA_STAT, 0, &sc->stats.phy.state);
+	if (ret < 0)
+		return ret;
+
+	switch (GET_STATUS(sc->stats.phy.state)) {
+	case 0:		/* not yet synchronized */
+		uea_dbg(INS_TO_USBDEV(sc),
+		       "modem not yet synchronized\n");
+		return 0;
+
+	case 1:		/* initialization */
+		uea_dbg(INS_TO_USBDEV(sc), "modem initializing\n");
+		return 0;
+
+	case 2:		/* operational */
+		uea_vdbg(INS_TO_USBDEV(sc), "modem operational\n");
+		break;
+
+	case 3:		/* fail ... */
+		uea_info(INS_TO_USBDEV(sc), "modem synchronization failed\n");
+		return -EAGAIN;
+
+	case 4 ... 6:	/* test state */
+		uea_warn(INS_TO_USBDEV(sc),
+				"modem in test mode - not supported\n");
+		return -EAGAIN;
+
+	case 7:		/* fast-retain ... */
+		uea_info(INS_TO_USBDEV(sc), "modem in fast-retain mode\n");
+		return 0;
+	default:
+		uea_err(INS_TO_USBDEV(sc), "modem invalid SW mode %d\n",
+			GET_STATUS(sc->stats.phy.state));
+		return -EAGAIN;
+	}
+
+	if (GET_STATUS(data) != 2) {
+		uea_request(sc, UEA_SET_MODE, UEA_LOOPBACK_OFF, 0, NULL);
+		uea_info(INS_TO_USBDEV(sc), "modem operational\n");
+
+		/* release the dsp firmware as it is not needed until
+		 * the next failure
+		 */
+		if (sc->dsp_firm) {
+			release_firmware(sc->dsp_firm);
+			sc->dsp_firm = NULL;
+		}
+
+		ret = uea_read_cmv(sc, SA_INFO, 10, &sc->stats.phy.firmid);
+		if (ret < 0)
+			return ret;
+		uea_info(INS_TO_USBDEV(sc), "ATU-R firmware version : %x\n",
+				sc->stats.phy.firmid);
+	}
+
+	/* always update it as atm layer could not be init when we switch to
+	 * operational state
+	 */
+	UPDATE_ATM_STAT(signal, ATM_PHY_SIG_FOUND);
+
+	/* wake up processes waiting for synchronization */
+	wake_up(&sc->sync_q);
+
+	ret = uea_read_cmv(sc, SA_DIAG, 2, &sc->stats.phy.flags);
+	if (ret < 0)
+		return ret;
+	sc->stats.phy.mflags |= sc->stats.phy.flags;
+
+	/* in case of a flags ( for example delineation LOSS (& 0x10)),
+	 * we check the status again in order to detect the failure earlier
+	 */
+	if (sc->stats.phy.flags) {
+		uea_dbg(INS_TO_USBDEV(sc), "Stat flag = %d\n",
+		       sc->stats.phy.flags);
+		return 0;
+	}
+
+	ret = uea_read_cmv(sc, SA_RATE, 0, &data);
+	if (ret < 0)
+		return ret;
+
+	/* in bulk mode the modem have problem with high rate
+	 * changing internal timing could improve things, but the
+	 * value is misterious.
+	 * ADI930 don't support it (-EPIPE error).
+	 */
+	if (UEA_CHIP_VERSION(sc) != ADI930
+		    && sc->stats.phy.dsrate != (data >> 16) * 32) {
+		/* Original timming from ADI(used in windows driver)
+		 * 0x20ffff>>16 * 32 = 32 * 32 = 1Mbits
+		 */
+		u16 timeout = (data <= 0x20ffff) ? 0 : 1;
+		ret = uea_request(sc, UEA_SET_TIMEOUT, timeout, 0, NULL);
+		uea_info(INS_TO_USBDEV(sc),
+				"setting new timeout %d%s\n", timeout,
+				ret < 0?" failed":"");
+	}
+	sc->stats.phy.dsrate = (data >> 16) * 32;
+	sc->stats.phy.usrate = (data & 0xffff) * 32;
+	UPDATE_ATM_STAT(link_rate, sc->stats.phy.dsrate * 1000 / 424);
+
+	ret = uea_read_cmv(sc, SA_DIAG, 23, &data);
+	if (ret < 0)
+		return ret;
+	sc->stats.phy.dsattenuation = (data & 0xff) / 2;
+
+	ret = uea_read_cmv(sc, SA_DIAG, 47, &data);
+	if (ret < 0)
+		return ret;
+	sc->stats.phy.usattenuation = (data & 0xff) / 2;
+
+	ret = uea_read_cmv(sc, SA_DIAG, 25, &sc->stats.phy.dsmargin);
+	if (ret < 0)
+		return ret;
+
+	ret = uea_read_cmv(sc, SA_DIAG, 49, &sc->stats.phy.usmargin);
+	if (ret < 0)
+		return ret;
+
+	ret = uea_read_cmv(sc, SA_DIAG, 51, &sc->stats.phy.rxflow);
+	if (ret < 0)
+		return ret;
+
+	ret = uea_read_cmv(sc, SA_DIAG, 52, &sc->stats.phy.txflow);
+	if (ret < 0)
+		return ret;
+
+	ret = uea_read_cmv(sc, SA_DIAG, 54, &sc->stats.phy.dsunc);
+	if (ret < 0)
+		return ret;
+
+	/* only for atu-c */
+	ret = uea_read_cmv(sc, SA_DIAG, 58, &sc->stats.phy.usunc);
+	if (ret < 0)
+		return ret;
+
+	ret = uea_read_cmv(sc, SA_DIAG, 53, &sc->stats.phy.dscorr);
+	if (ret < 0)
+		return ret;
+
+	/* only for atu-c */
+	ret = uea_read_cmv(sc, SA_DIAG, 57, &sc->stats.phy.uscorr);
+	if (ret < 0)
+		return ret;
+
+	ret = uea_read_cmv(sc, SA_INFO, 8, &sc->stats.phy.vidco);
+	if (ret < 0)
+		return ret;
+
+	ret = uea_read_cmv(sc, SA_INFO, 13, &sc->stats.phy.vidcpe);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int request_cmvs(struct uea_softc *sc,
+		 struct uea_cmvs **cmvs, const struct firmware **fw)
+{
+	int ret, size;
+	u8 *data;
+	char *file;
+	static char cmv_name[256] = FW_DIR;
+
+	if (cmv_file[sc->modem_index] == NULL) {
+		if (UEA_CHIP_VERSION(sc) == ADI930)
+			file = (IS_ISDN(sc)) ? "CMV9i.bin" : "CMV9p.bin";
+		else
+			file = (IS_ISDN(sc)) ? "CMVei.bin" : "CMVep.bin";
+	} else
+		file = cmv_file[sc->modem_index];
+
+	strcpy(cmv_name, FW_DIR);
+	strlcat(cmv_name, file, sizeof(cmv_name));
+
+	ret = request_firmware(fw, cmv_name, &sc->usb_dev->dev);
+	if (ret < 0) {
+		uea_err(INS_TO_USBDEV(sc),
+		       "requesting firmware %s failed with error %d\n",
+		       cmv_name, ret);
+		return ret;
+	}
+
+	data = (u8 *) (*fw)->data;
+	size = *data * sizeof(struct uea_cmvs) + 1;
+	if (size != (*fw)->size) {
+		uea_err(INS_TO_USBDEV(sc), "firmware %s is corrupted\n",
+		       cmv_name);
+		release_firmware(*fw);
+		return -EILSEQ;
+	}
+
+	*cmvs = (struct uea_cmvs *)(data + 1);
+	return *data;
+}
+
+/* Start boot post firmware modem:
+ * - send reset commands through usb control pipe
+ * - start workqueue for DSP loading
+ * - send CMV options to modem
+ */
+
+static int uea_start_reset(struct uea_softc *sc)
+{
+	u16 zero = 0;	/* ;-) */
+	int i, len, ret;
+	struct uea_cmvs *cmvs;
+	const struct firmware *cmvs_fw;
+
+	uea_enters(INS_TO_USBDEV(sc));
+	uea_info(INS_TO_USBDEV(sc), "(re)booting started\n");
+
+	sc->booting = 1;
+	UPDATE_ATM_STAT(signal, ATM_PHY_SIG_LOST);
+
+	/* reset statistics */
+	memset(&sc->stats, 0, sizeof(struct uea_stats));
+
+	/* tell the modem that we want to boot in IDMA mode */
+	uea_request(sc, UEA_SET_MODE, UEA_LOOPBACK_ON, 0, NULL);
+	uea_request(sc, UEA_SET_MODE, UEA_BOOT_IDMA, 0, NULL);
+
+ 	/* enter reset mode */
+	uea_request(sc, UEA_SET_MODE, UEA_START_RESET, 0, NULL);
+
+	/* original driver use 200ms, but windows driver use 100ms */
+	msleep(100);
+
+	/* leave reset mode */
+	uea_request(sc, UEA_SET_MODE, UEA_END_RESET, 0, NULL);
+
+ 	/* clear tx and rx mailboxes */
+	uea_request(sc, UEA_SET_2183_DATA, UEA_MPTX_MAILBOX, 2, &zero);
+	uea_request(sc, UEA_SET_2183_DATA, UEA_MPRX_MAILBOX, 2, &zero);
+	uea_request(sc, UEA_SET_2183_DATA, UEA_SWAP_MAILBOX, 2, &zero);
+
+	msleep(1000);
+	sc->cmv_function = MAKEFUNCTION(ADSLDIRECTIVE, MODEMREADY);
+	sc->booting = 0;
+
+	/* start loading DSP */
+	sc->pageno = 0;
+	sc->ovl = 0;
+	schedule_work(&sc->task);
+
+	/* wait for modem ready CMV */
+	ret = wait_cmv_ack(sc);
+	if (ret < 0)
+		return ret;
+
+	/* Enter in R-IDLE (cmv) until instructed otherwise */
+	ret = uea_write_cmv(sc, SA_CNTL, 0, 1);
+	if (ret < 0)
+		return ret;
+
+	/* get options */
+ 	ret = len = request_cmvs(sc, &cmvs, &cmvs_fw);
+	if (ret < 0)
+		return ret;
+
+	/* send options */
+	for (i = 0; i < len; i++) {
+		ret = uea_write_cmv(sc, FW_GET_LONG(&cmvs[i].address),
+					FW_GET_WORD(&cmvs[i].offset),
+					FW_GET_LONG(&cmvs[i].data));
+		if (ret < 0)
+			goto out;
+	}
+	/* Enter in R-ACT-REQ */
+	ret = uea_write_cmv(sc, SA_CNTL, 0, 2);
+out:
+	release_firmware(cmvs_fw);
+	sc->reset = 0;
+	uea_leaves(INS_TO_USBDEV(sc));
+	return ret;
+}
+
+/*
+ * In case of an error wait 1s before rebooting the modem
+ * if the modem don't request reboot (-EAGAIN).
+ * Monitor the modem every 1s.
+ */
+
+static int uea_kthread(void *data)
+{
+	struct uea_softc *sc = data;
+	int ret = -EAGAIN;
+
+	uea_enters(INS_TO_USBDEV(sc));
+	while (!kthread_should_stop()) {
+		if (ret < 0 || sc->reset)
+			ret = uea_start_reset(sc);
+		if (!ret)
+			ret = uea_stat(sc);
+		if (ret != -EAGAIN)
+			msleep(1000);
+	}
+	uea_leaves(INS_TO_USBDEV(sc));
+	return ret;
+}
+
+/* Load second usb firmware for ADI930 chip */
+static int load_XILINX_firmware(struct uea_softc *sc)
+{
+	const struct firmware *fw_entry;
+	int ret, size, u, ln;
+	u8 *pfw, value;
+	char *fw_name = FW_DIR "930-fpga.bin";
+
+	uea_enters(INS_TO_USBDEV(sc));
+
+	ret = request_firmware(&fw_entry, fw_name, &sc->usb_dev->dev);
+	if (ret) {
+		uea_err(INS_TO_USBDEV(sc), "firmware %s is not available\n",
+		       fw_name);
+		goto err0;
+	}
+
+	pfw = fw_entry->data;
+	size = fw_entry->size;
+	if (size != 0x577B) {
+		uea_err(INS_TO_USBDEV(sc), "firmware %s is corrupted\n",
+		       fw_name);
+		ret = -EILSEQ;
+		goto err1;
+	}
+	for (u = 0; u < size; u += ln) {
+		ln = min(size - u, 64);
+		ret = uea_request(sc, 0xe, 0, ln, pfw + u);
+		if (ret < 0) {
+			uea_err(INS_TO_USBDEV(sc),
+			       "elsa download data failed (%d)\n", ret);
+			goto err1;
+		}
+	}
+
+	/* finish to send the fpga
+	 */
+	ret = uea_request(sc, 0xe, 1, 0, NULL);
+	if (ret < 0) {
+		uea_err(INS_TO_USBDEV(sc),
+				"elsa download data failed (%d)\n", ret);
+		goto err1;
+	}
+
+	/*
+	 * Tell the modem we finish : de-assert reset
+	 */
+	value = 0;
+	ret = uea_send_modem_cmd(sc->usb_dev, 0xe, 1, &value);
+	if (ret < 0)
+		uea_err(sc->usb_dev, "elsa de-assert failed with error %d\n", ret);
+
+
+err1:
+	release_firmware(fw_entry);
+err0:
+	uea_leaves(INS_TO_USBDEV(sc));
+	return ret;
+}
+
+static void uea_dispatch_cmv(struct uea_softc *sc, struct cmv* cmv)
+{
+	uea_enters(INS_TO_USBDEV(sc));
+	if (le16_to_cpu(cmv->wPreamble) != PREAMBLE)
+		goto bad1;
+
+	if (cmv->bDirection != MODEMTOHOST)
+		goto bad1;
+
+	/* FIXME : ADI930 reply wrong preambule (func = 2, sub = 2) to
+	 * the first MEMACESS cmv. Ignore it...
+	 */
+	if (cmv->bFunction != sc->cmv_function) {
+		if (UEA_CHIP_VERSION(sc) == ADI930
+				&& cmv->bFunction ==  MAKEFUNCTION(2, 2)) {
+			cmv->wIndex = cpu_to_le16(sc->cmv_idx);
+			put_unaligned(cpu_to_le32(sc->cmv_address), &cmv->dwSymbolicAddress);
+			cmv->wOffsetAddress = cpu_to_le16(sc->cmv_offset);
+		}
+		else
+			goto bad2;
+	}
+
+	if (cmv->bFunction == MAKEFUNCTION(ADSLDIRECTIVE, MODEMREADY)) {
+		wake_up_cmv_ack(sc);
+		return;
+	}
+
+	/* in case of MEMACCESS */
+	if (le16_to_cpu(cmv->wIndex) != sc->cmv_idx ||
+	    le32_to_cpu(get_unaligned(&cmv->dwSymbolicAddress)) !=
+	    sc->cmv_address
+	    || le16_to_cpu(cmv->wOffsetAddress) != sc->cmv_offset)
+		goto bad2;
+
+	sc->data = le32_to_cpu(get_unaligned(&cmv->dwData));
+	sc->data = sc->data << 16 | sc->data >> 16;
+
+	wake_up_cmv_ack(sc);
+	return;
+
+bad2:
+	uea_err(INS_TO_USBDEV(sc), "unexpected cmv received,"
+			"Function : %d, Subfunction : %d\n",
+			FUNCTION_TYPE(cmv->bFunction),
+			FUNCTION_SUBTYPE(cmv->bFunction));
+	return;
+
+bad1:
+	uea_err(INS_TO_USBDEV(sc), "invalid cmv received, "
+			"wPreamble %d, bDirection %d\n",
+			le16_to_cpu(cmv->wPreamble), cmv->bDirection);
+}
+
+/*
+ * interrupt handler
+ */
+static void uea_intr(struct urb *urb, struct pt_regs *regs)
+{
+	struct uea_softc *sc = (struct uea_softc *)urb->context;
+	struct intr_pkt *intr;
+	uea_enters(INS_TO_USBDEV(sc));
+
+	if (urb->status < 0) {
+		uea_err(INS_TO_USBDEV(sc), "uea_intr() failed with %d\n",
+		       urb->status);
+		return;
+	}
+
+	intr = (struct intr_pkt *) urb->transfer_buffer;
+
+	/* device-to-host interrupt */
+	if (intr->bType != 0x08 || sc->booting) {
+		uea_err(INS_TO_USBDEV(sc), "wrong intr\n");
+		// rebooting ?
+		// sc->reset = 1;
+		goto resubmit;
+	}
+
+	switch (le16_to_cpu(intr->wInterrupt)) {
+	case INT_LOADSWAPPAGE:
+		sc->pageno = intr->bSwapPageNo;
+		sc->ovl = intr->bOvl >> 4 | intr->bOvl << 4;
+		schedule_work(&sc->task);
+		break;
+
+	case INT_INCOMINGCMV:
+		uea_dispatch_cmv(sc, &intr->u.s2.cmv);
+		break;
+
+	default:
+		uea_err(INS_TO_USBDEV(sc), "unknown intr %u\n",
+		       le16_to_cpu(intr->wInterrupt));
+	}
+
+resubmit:
+	usb_submit_urb(sc->urb_int, GFP_ATOMIC);
+}
+
+/*
+ * Start the modem : init the data and start kernel thread
+ */
+static int uea_boot(struct uea_softc *sc)
+{
+	int ret;
+	struct intr_pkt *intr;
+
+	uea_enters(INS_TO_USBDEV(sc));
+
+	INIT_WORK(&sc->task, uea_load_page, sc);
+	init_waitqueue_head(&sc->sync_q);
+	init_waitqueue_head(&sc->cmv_ack_wait);
+
+	if (UEA_CHIP_VERSION(sc) == ADI930)
+		load_XILINX_firmware(sc);
+
+	intr = kmalloc(INTR_PKT_SIZE, GFP_KERNEL);
+	if (!intr) {
+		uea_err(INS_TO_USBDEV(sc),
+		       "cannot allocate interrupt package\n");
+		uea_leaves(INS_TO_USBDEV(sc));
+		return -ENOMEM;
+	}
+
+	sc->urb_int = usb_alloc_urb(0, GFP_KERNEL);
+	if (!sc->urb_int) {
+		uea_err(INS_TO_USBDEV(sc), "cannot allocate interrupt URB\n");
+		goto err;
+	}
+
+	usb_fill_int_urb(sc->urb_int, sc->usb_dev,
+			 usb_rcvintpipe(sc->usb_dev, UEA_INTR_PIPE),
+			 intr, INTR_PKT_SIZE, uea_intr, sc,
+			 sc->usb_dev->actconfig->interface[0]->altsetting[0].
+			 endpoint[0].desc.bInterval);
+
+	ret = usb_submit_urb(sc->urb_int, GFP_KERNEL);
+	if (ret < 0) {
+		uea_err(INS_TO_USBDEV(sc),
+		       "urb submition failed with error %d\n", ret);
+		goto err1;
+	}
+
+	sc->kthread = kthread_run(uea_kthread, sc, "ueagle-atm");
+	if (sc->kthread == ERR_PTR(-ENOMEM)) {
+		uea_err(INS_TO_USBDEV(sc), "failed to create thread\n");
+		goto err2;
+	}
+
+	uea_leaves(INS_TO_USBDEV(sc));
+	return 0;
+
+err2:
+	usb_kill_urb(sc->urb_int);
+err1:
+	kfree(intr);
+err:
+	usb_free_urb(sc->urb_int);
+	uea_leaves(INS_TO_USBDEV(sc));
+	return -ENOMEM;
+}
+
+/*
+ * Stop the modem : kill kernel thread and free data
+ */
+static void uea_stop(struct uea_softc *sc)
+{
+	int ret;
+	uea_enters(INS_TO_USBDEV(sc));
+	ret = kthread_stop(sc->kthread);
+	uea_info(INS_TO_USBDEV(sc), "kthread finish with status %d\n", ret);
+
+	/* stop any pending boot process */
+	flush_scheduled_work();
+
+	uea_request(sc, UEA_SET_MODE, UEA_LOOPBACK_ON, 0, NULL);
+
+	usb_kill_urb(sc->urb_int);
+	kfree(sc->urb_int->transfer_buffer);
+	usb_free_urb(sc->urb_int);
+
+	if (sc->dsp_firm)
+		release_firmware(sc->dsp_firm);
+	uea_leaves(INS_TO_USBDEV(sc));
+}
+
+/* syfs interface */
+static struct uea_softc *dev_to_uea(struct device *dev)
+{
+	struct usb_interface *intf;
+	struct usbatm_data *usbatm;
+
+	intf = to_usb_interface(dev);
+	if (!intf)
+		return NULL;
+
+	usbatm = usb_get_intfdata(intf);
+	if (!usbatm)
+		return NULL;
+
+	return usbatm->driver_data;
+}
+
+static ssize_t read_status(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	int ret = -ENODEV;
+	struct uea_softc *sc;
+
+	down(&uea_semaphore);
+	sc = dev_to_uea(dev);
+	if (!sc)
+		goto out;
+	ret = snprintf(buf, 10, "%08x\n", sc->stats.phy.state);
+out:
+	up(&uea_semaphore);
+	return ret;
+}
+
+static ssize_t reboot(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	int ret = -ENODEV;
+	struct uea_softc *sc;
+
+	down(&uea_semaphore);
+	sc = dev_to_uea(dev);
+	if (!sc)
+		goto out;
+	sc->reset = 1;
+	ret = count;
+out:
+	up(&uea_semaphore);
+	return ret;
+}
+
+static DEVICE_ATTR(stat_status, S_IWUGO | S_IRUGO, read_status, reboot);
+
+static ssize_t read_human_status(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	int ret = -ENODEV;
+	struct uea_softc *sc;
+
+	down(&uea_semaphore);
+	sc = dev_to_uea(dev);
+	if (!sc)
+		goto out;
+
+	switch (GET_STATUS(sc->stats.phy.state)) {
+	case 0:
+		ret = sprintf(buf, "Modem is booting\n");
+		break;
+	case 1:
+		ret = sprintf(buf, "Modem is initializing\n");
+		break;
+	case 2:
+		ret = sprintf(buf, "Modem is operational\n");
+		break;
+	default:
+		ret = sprintf(buf, "Modem synchronization failed\n");
+		break;
+	}
+out:
+	up(&uea_semaphore);
+	return ret;
+}
+
+static DEVICE_ATTR(stat_human_status, S_IWUGO | S_IRUGO, read_human_status, NULL);
+
+static ssize_t read_delin(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	int ret = -ENODEV;
+	struct uea_softc *sc;
+
+	down(&uea_semaphore);
+	sc = dev_to_uea(dev);
+	if (!sc)
+		goto out;
+
+	if (sc->stats.phy.flags & 0x0C00)
+		ret = sprintf(buf, "ERROR\n");
+	else if (sc->stats.phy.flags & 0x0030)
+		ret = sprintf(buf, "LOSS\n");
+	else
+		ret = sprintf(buf, "GOOD\n");
+out:
+	up(&uea_semaphore);
+	return ret;
+}
+
+static DEVICE_ATTR(stat_delin, S_IWUGO | S_IRUGO, read_delin, NULL);
+
+#define UEA_ATTR(name, reset) 					\
+								\
+static ssize_t read_##name(struct device *dev, 			\
+		struct device_attribute *attr, char *buf)	\
+{ 								\
+	int ret = -ENODEV; 					\
+	struct uea_softc *sc; 					\
+ 								\
+	down(&uea_semaphore); 					\
+	sc = dev_to_uea(dev);					\
+	if (!sc) 						\
+		goto out; 					\
+	ret = snprintf(buf, 10, "%08x\n", sc->stats.phy.name);	\
+	if (reset)						\
+		sc->stats.phy.name = 0;				\
+out: 								\
+	up(&uea_semaphore); 					\
+	return ret; 						\
+} 								\
+								\
+static DEVICE_ATTR(stat_##name, S_IRUGO, read_##name, NULL)
+
+UEA_ATTR(mflags, 1);
+UEA_ATTR(vidcpe, 0);
+UEA_ATTR(usrate, 0);
+UEA_ATTR(dsrate, 0);
+UEA_ATTR(usattenuation, 0);
+UEA_ATTR(dsattenuation, 0);
+UEA_ATTR(usmargin, 0);
+UEA_ATTR(dsmargin, 0);
+UEA_ATTR(txflow, 0);
+UEA_ATTR(rxflow, 0);
+UEA_ATTR(uscorr, 0);
+UEA_ATTR(dscorr, 0);
+UEA_ATTR(usunc, 0);
+UEA_ATTR(dsunc, 0);
+
+/* Retrieve the device End System Identifier (MAC) */
+
+#define htoi(x) (isdigit(x) ? x-'0' : toupper(x)-'A'+10)
+static int uea_getesi(struct uea_softc *sc, u_char * esi)
+{
+	unsigned char mac_str[2 * ETH_ALEN + 1];
+	int i;
+	if (usb_string
+	    (sc->usb_dev, sc->usb_dev->descriptor.iSerialNumber, mac_str,
+	     sizeof(mac_str)) != 2 * ETH_ALEN)
+		return 1;
+
+	for (i = 0; i < ETH_ALEN; i++)
+		esi[i] = htoi(mac_str[2 * i]) * 16 + htoi(mac_str[2 * i + 1]);
+
+	return 0;
+}
+
+/* ATM stuff */
+static int uea_atm_open(struct usbatm_data *usbatm, struct atm_dev *atm_dev)
+{
+	struct uea_softc *sc = usbatm->driver_data;
+
+	return uea_getesi(sc, atm_dev->esi);
+}
+
+static int uea_heavy(struct usbatm_data *usbatm, struct usb_interface *intf)
+{
+	struct uea_softc *sc = usbatm->driver_data;
+
+	wait_event(sc->sync_q, IS_OPERATIONAL(sc));
+
+	return 0;
+
+}
+
+static int claim_interface(struct usb_device *usb_dev,
+			   struct usbatm_data *usbatm, int ifnum)
+{
+	int ret;
+	struct usb_interface *intf = usb_ifnum_to_if(usb_dev, ifnum);
+
+	if (!intf) {
+		uea_err(usb_dev, "interface %d not found\n", ifnum);
+		return -ENODEV;
+	}
+
+	ret = usb_driver_claim_interface(&uea_driver, intf, usbatm);
+	if (ret != 0)
+		uea_err(usb_dev, "can't claim interface %d, error %d\n", ifnum,
+		       ret);
+	return ret;
+}
+
+static void create_fs_entries(struct uea_softc *sc, struct usb_interface *intf)
+{
+	/* sysfs interface */
+	device_create_file(&intf->dev, &dev_attr_stat_status);
+	device_create_file(&intf->dev, &dev_attr_stat_mflags);
+	device_create_file(&intf->dev, &dev_attr_stat_human_status);
+	device_create_file(&intf->dev, &dev_attr_stat_delin);
+	device_create_file(&intf->dev, &dev_attr_stat_vidcpe);
+	device_create_file(&intf->dev, &dev_attr_stat_usrate);
+	device_create_file(&intf->dev, &dev_attr_stat_dsrate);
+	device_create_file(&intf->dev, &dev_attr_stat_usattenuation);
+	device_create_file(&intf->dev, &dev_attr_stat_dsattenuation);
+	device_create_file(&intf->dev, &dev_attr_stat_usmargin);
+	device_create_file(&intf->dev, &dev_attr_stat_dsmargin);
+	device_create_file(&intf->dev, &dev_attr_stat_txflow);
+	device_create_file(&intf->dev, &dev_attr_stat_rxflow);
+	device_create_file(&intf->dev, &dev_attr_stat_uscorr);
+	device_create_file(&intf->dev, &dev_attr_stat_dscorr);
+	device_create_file(&intf->dev, &dev_attr_stat_usunc);
+	device_create_file(&intf->dev, &dev_attr_stat_dsunc);
+}
+
+static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf,
+		   const struct usb_device_id *id, int *heavy)
+{
+	struct usb_device *usb = interface_to_usbdev(intf);
+	struct uea_softc *sc;
+	int ret, ifnum = intf->altsetting->desc.bInterfaceNumber;
+
+	uea_enters(usb);
+
+	/* interface 0 is for firmware/monitoring */
+	if (ifnum != UEA_INTR_IFACE_NO)
+		return -ENODEV;
+
+	*heavy = sync_wait[modem_index];
+
+	/* interface 1 is for outbound traffic */
+	ret = claim_interface(usb, usbatm, UEA_US_IFACE_NO);
+	if (ret < 0)
+		return ret;
+
+	/* ADI930 has only 2 interfaces and inbound traffic
+	 * is on interface 1
+	 */
+	if (UEA_CHIP_VERSION(id) != ADI930) {
+		/* interface 2 is for inbound traffic */
+		ret = claim_interface(usb, usbatm, UEA_DS_IFACE_NO);
+		if (ret < 0)
+			return ret;
+	}
+
+	sc = kzalloc(sizeof(struct uea_softc), GFP_KERNEL);
+	if (!sc) {
+		uea_err(INS_TO_USBDEV(sc), "uea_init: not enough memory !\n");
+		return -ENOMEM;
+	}
+
+	sc->usb_dev = usb;
+	usbatm->driver_data = sc;
+	sc->usbatm = usbatm;
+	sc->modem_index = (modem_index < NB_MODEM) ? modem_index++ : 0;
+	sc->driver_info = id->driver_info;
+
+	ret = uea_boot(sc);
+	if (ret < 0) {
+		kfree(sc);
+		return ret;
+	}
+
+	create_fs_entries(sc, intf);
+	return 0;
+}
+
+static void destroy_fs_entries(struct uea_softc *sc, struct usb_interface *intf)
+{
+	/* sysfs interface */
+	device_remove_file(&intf->dev, &dev_attr_stat_status);
+	device_remove_file(&intf->dev, &dev_attr_stat_mflags);
+	device_remove_file(&intf->dev, &dev_attr_stat_human_status);
+	device_remove_file(&intf->dev, &dev_attr_stat_delin);
+	device_remove_file(&intf->dev, &dev_attr_stat_vidcpe);
+	device_remove_file(&intf->dev, &dev_attr_stat_usrate);
+	device_remove_file(&intf->dev, &dev_attr_stat_dsrate);
+	device_remove_file(&intf->dev, &dev_attr_stat_usattenuation);
+	device_remove_file(&intf->dev, &dev_attr_stat_dsattenuation);
+	device_remove_file(&intf->dev, &dev_attr_stat_usmargin);
+	device_remove_file(&intf->dev, &dev_attr_stat_dsmargin);
+	device_remove_file(&intf->dev, &dev_attr_stat_txflow);
+	device_remove_file(&intf->dev, &dev_attr_stat_rxflow);
+	device_remove_file(&intf->dev, &dev_attr_stat_uscorr);
+	device_remove_file(&intf->dev, &dev_attr_stat_dscorr);
+	device_remove_file(&intf->dev, &dev_attr_stat_usunc);
+	device_remove_file(&intf->dev, &dev_attr_stat_dsunc);
+}
+
+static void uea_unbind(struct usbatm_data *usbatm, struct usb_interface *intf)
+{
+	struct uea_softc *sc = usbatm->driver_data;
+
+	destroy_fs_entries(sc, intf);
+	uea_stop(sc);
+	kfree(sc);
+}
+
+static struct usbatm_driver uea_usbatm_driver = {
+	.driver_name = "ueagle-atm",
+	.owner = THIS_MODULE,
+	.bind = uea_bind,
+	.atm_start = uea_atm_open,
+	.unbind = uea_unbind,
+	.heavy_init = uea_heavy,
+	.in = UEA_BULK_DATA_PIPE,
+	.out = UEA_BULK_DATA_PIPE,
+};
+
+static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+	struct usb_device *usb = interface_to_usbdev(intf);
+
+	uea_enters(usb);
+	uea_info(usb, "ADSL device founded vid (%#X) pid (%#X) : %s\n",
+	       le16_to_cpu(usb->descriptor.idVendor),
+	       le16_to_cpu(usb->descriptor.idProduct),
+	       chip_name[UEA_CHIP_VERSION(id)]);
+
+	usb_reset_device(usb);
+
+	if (UEA_IS_PREFIRM(id))
+		return uea_load_firmware(usb, UEA_CHIP_VERSION(id));
+
+	return usbatm_usb_probe(intf, id, &uea_usbatm_driver);
+}
+
+static void uea_disconnect(struct usb_interface *intf)
+{
+	struct usb_device *usb = interface_to_usbdev(intf);
+	int ifnum = intf->altsetting->desc.bInterfaceNumber;
+	uea_enters(usb);
+
+	/* ADI930 has 2 interfaces and eagle 3 interfaces.
+	 * Pre-firmware device has one interface
+	 */
+	if (usb->config->desc.bNumInterfaces != 1 && ifnum == 0) {
+		down(&uea_semaphore);
+		usbatm_usb_disconnect(intf);
+		up(&uea_semaphore);
+		uea_info(usb, "ADSL device removed\n");
+	}
+
+	uea_leaves(usb);
+}
+
+/*
+ * List of supported VID/PID
+ */
+static const struct usb_device_id uea_ids[] = {
+	{USB_DEVICE(ELSA_VID,	ELSA_PID_PREFIRM),	.driver_info = ADI930 | PREFIRM},
+	{USB_DEVICE(ELSA_VID,	ELSA_PID_PSTFIRM),	.driver_info = ADI930 | PSTFIRM},
+	{USB_DEVICE(EAGLE_VID,	EAGLE_I_PID_PREFIRM),	.driver_info = EAGLE_I | PREFIRM},
+	{USB_DEVICE(EAGLE_VID,	EAGLE_I_PID_PSTFIRM),	.driver_info = EAGLE_I | PSTFIRM},
+	{USB_DEVICE(EAGLE_VID,	EAGLE_II_PID_PREFIRM),	.driver_info = EAGLE_II | PREFIRM},
+	{USB_DEVICE(EAGLE_VID,	EAGLE_II_PID_PSTFIRM),	.driver_info = EAGLE_II | PSTFIRM},
+	{USB_DEVICE(EAGLE_VID,	EAGLE_IIC_PID_PREFIRM),	.driver_info = EAGLE_II | PREFIRM},
+	{USB_DEVICE(EAGLE_VID,	EAGLE_IIC_PID_PSTFIRM),	.driver_info = EAGLE_II | PSTFIRM},
+	{USB_DEVICE(EAGLE_VID,	EAGLE_III_PID_PREFIRM),	.driver_info = EAGLE_III | PREFIRM},
+	{USB_DEVICE(EAGLE_VID,	EAGLE_III_PID_PSTFIRM),	.driver_info = EAGLE_III | PSTFIRM},
+	{USB_DEVICE(USR_VID,	MILLER_A_PID_PREFIRM),	.driver_info = EAGLE_I | PREFIRM},
+	{USB_DEVICE(USR_VID,	MILLER_A_PID_PSTFIRM),	.driver_info = EAGLE_I | PSTFIRM},
+	{USB_DEVICE(USR_VID,	MILLER_B_PID_PREFIRM),	.driver_info = EAGLE_I | PREFIRM},
+	{USB_DEVICE(USR_VID,	MILLER_B_PID_PSTFIRM),	.driver_info = EAGLE_I | PSTFIRM},
+	{USB_DEVICE(USR_VID,	HEINEKEN_A_PID_PREFIRM),.driver_info = EAGLE_I | PREFIRM},
+	{USB_DEVICE(USR_VID,	HEINEKEN_A_PID_PSTFIRM),.driver_info = EAGLE_I | PSTFIRM},
+	{USB_DEVICE(USR_VID,	HEINEKEN_B_PID_PREFIRM),.driver_info = EAGLE_I | PREFIRM},
+	{USB_DEVICE(USR_VID,	HEINEKEN_B_PID_PSTFIRM),.driver_info = EAGLE_I | PSTFIRM},
+	{}
+};
+
+/*
+ * USB driver descriptor
+ */
+static struct usb_driver uea_driver = {
+	.name = "ueagle-atm",
+	.id_table = uea_ids,
+	.probe = uea_probe,
+	.disconnect = uea_disconnect,
+};
+
+MODULE_DEVICE_TABLE(usb, uea_ids);
+
+/**
+ * uea_init - Initialize the module.
+ *      Register to USB subsystem
+ */
+static int __init uea_init(void)
+{
+	printk(KERN_INFO "[ueagle-atm] driver " EAGLEUSBVERSION " loaded\n");
+
+	usb_register(&uea_driver);
+
+	return 0;
+}
+
+module_init(uea_init);
+
+/**
+ * uea_exit  -  Destroy module
+ *    Deregister with USB subsystem
+ */
+static void __exit uea_exit(void)
+{
+	/*
+	 * This calls automatically the uea_disconnect method if necessary:
+	 */
+	usb_deregister(&uea_driver);
+
+	printk(KERN_INFO "[ueagle-atm] driver unloaded\n");
+}
+
+module_exit(uea_exit);
+
+MODULE_AUTHOR("Damien Bergamini/Matthieu Castet/Stanislaw W. Gruszka");
+MODULE_DESCRIPTION("ADI 930/Eagle USB ADSL Modem driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c
index 2e6593e6c1bd..9baa6296fc95 100644
--- a/drivers/usb/atm/usbatm.c
+++ b/drivers/usb/atm/usbatm.c
@@ -646,14 +646,14 @@ static void usbatm_destroy_instance(struct kref *kref)
 	kfree(instance);
 }
 
-void usbatm_get_instance(struct usbatm_data *instance)
+static void usbatm_get_instance(struct usbatm_data *instance)
 {
 	dbg("%s", __func__);
 
 	kref_get(&instance->refcount);
 }
 
-void usbatm_put_instance(struct usbatm_data *instance)
+static void usbatm_put_instance(struct usbatm_data *instance)
 {
 	dbg("%s", __func__);
 
diff --git a/drivers/usb/atm/xusbatm.c b/drivers/usb/atm/xusbatm.c
index 7fe7fb484d10..5c76e3aaaa5e 100644
--- a/drivers/usb/atm/xusbatm.c
+++ b/drivers/usb/atm/xusbatm.c
@@ -140,7 +140,6 @@ static int xusbatm_usb_probe(struct usb_interface *intf,
 }
 
 static struct usb_driver xusbatm_usb_driver = {
-	.owner		= THIS_MODULE,
 	.name		= xusbatm_driver_name,
 	.probe		= xusbatm_usb_probe,
 	.disconnect	= usbatm_usb_disconnect,
diff --git a/drivers/usb/class/audio.c b/drivers/usb/class/audio.c
index 50858273f8d3..3ad9ee8b84a9 100644
--- a/drivers/usb/class/audio.c
+++ b/drivers/usb/class/audio.c
@@ -2732,7 +2732,6 @@ static struct usb_device_id usb_audio_ids [] = {
 MODULE_DEVICE_TABLE (usb, usb_audio_ids);
 
 static struct usb_driver usb_audio_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"audio",
 	.probe =	usb_audio_probe,
 	.disconnect =	usb_audio_disconnect,
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 1b4751412970..248279e44c99 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -6,6 +6,7 @@
  * Copyright (c) 1999 Johannes Erdfelt	<johannes@erdfelt.com>
  * Copyright (c) 2000 Vojtech Pavlik	<vojtech@suse.cz>
  * Copyright (c) 2004 Oliver Neukum	<oliver@neukum.name>
+ * Copyright (c) 2005 David Kubicek	<dave@awk.cz>
  *
  * USB Abstract Control Model driver for USB modems and ISDN adapters
  *
@@ -29,6 +30,7 @@
  *		config we want, sysadmin changes bConfigurationValue in sysfs.
  *	v0.23 - use softirq for rx processing, as needed by tty layer
  *	v0.24 - change probe method to evaluate CDC union descriptor
+ *	v0.25 - downstream tasks paralelized to maximize throughput
  */
 
 /*
@@ -63,14 +65,15 @@
 #include <linux/usb_cdc.h>
 #include <asm/byteorder.h>
 #include <asm/unaligned.h>
+#include <linux/list.h>
 
 #include "cdc-acm.h"
 
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v0.23"
-#define DRIVER_AUTHOR "Armin Fuerst, Pavel Machek, Johannes Erdfelt, Vojtech Pavlik"
+#define DRIVER_VERSION "v0.25"
+#define DRIVER_AUTHOR "Armin Fuerst, Pavel Machek, Johannes Erdfelt, Vojtech Pavlik, David Kubicek"
 #define DRIVER_DESC "USB Abstract Control Model driver for USB modems and ISDN adapters"
 
 static struct usb_driver acm_driver;
@@ -284,7 +287,9 @@ exit:
 /* data interface returns incoming bytes, or we got unthrottled */
 static void acm_read_bulk(struct urb *urb, struct pt_regs *regs)
 {
-	struct acm *acm = urb->context;
+	struct acm_rb *buf;
+	struct acm_ru *rcv = urb->context;
+	struct acm *acm = rcv->instance;
 	dbg("Entering acm_read_bulk with status %d\n", urb->status);
 
 	if (!ACM_READY(acm))
@@ -293,49 +298,109 @@ static void acm_read_bulk(struct urb *urb, struct pt_regs *regs)
 	if (urb->status)
 		dev_dbg(&acm->data->dev, "bulk rx status %d\n", urb->status);
 
-	/* calling tty_flip_buffer_push() in_irq() isn't allowed */
-	tasklet_schedule(&acm->bh);
+	buf = rcv->buffer;
+	buf->size = urb->actual_length;
+
+	spin_lock(&acm->read_lock);
+	list_add_tail(&rcv->list, &acm->spare_read_urbs);
+	list_add_tail(&buf->list, &acm->filled_read_bufs);
+	spin_unlock(&acm->read_lock);
+
+	tasklet_schedule(&acm->urb_task);
 }
 
 static void acm_rx_tasklet(unsigned long _acm)
 {
 	struct acm *acm = (void *)_acm;
-	struct urb *urb = acm->readurb;
+	struct acm_rb *buf;
 	struct tty_struct *tty = acm->tty;
-	unsigned char *data = urb->transfer_buffer;
+	struct acm_ru *rcv;
+	//unsigned long flags;
 	int i = 0;
 	dbg("Entering acm_rx_tasklet");
 
-	if (urb->actual_length > 0 && !acm->throttle)  {
-		for (i = 0; i < urb->actual_length && !acm->throttle; i++) {
-			/* if we insert more than TTY_FLIPBUF_SIZE characters,
-			 * we drop them. */
-			if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-				tty_flip_buffer_push(tty);
-			}
-			tty_insert_flip_char(tty, data[i], 0);
-		}
-		dbg("Handed %d bytes to tty layer", i+1);
-		tty_flip_buffer_push(tty);
+	if (!ACM_READY(acm) || acm->throttle)
+		return;
+
+next_buffer:
+	spin_lock(&acm->read_lock);
+	if (list_empty(&acm->filled_read_bufs)) {
+		spin_unlock(&acm->read_lock);
+		goto urbs;
 	}
+	buf = list_entry(acm->filled_read_bufs.next,
+			 struct acm_rb, list);
+	list_del(&buf->list);
+	spin_unlock(&acm->read_lock);
+
+	dbg("acm_rx_tasklet: procesing buf 0x%p, size = %d\n", buf, buf->size);
+
+	for (i = 0; i < buf->size && !acm->throttle; i++) {
+		/* if we insert more than TTY_FLIPBUF_SIZE characters,
+		   we drop them. */
+		if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
+			tty_flip_buffer_push(tty);
+ 		}
+		tty_insert_flip_char(tty, buf->base[i], 0);
+ 	}
+	tty_flip_buffer_push(tty);
 
 	spin_lock(&acm->throttle_lock);
 	if (acm->throttle) {
 		dbg("Throtteling noticed");
-		memmove(data, data + i, urb->actual_length - i);
-		urb->actual_length -= i;
-		acm->resubmit_to_unthrottle = 1;
+		memmove(buf->base, buf->base + i, buf->size - i);
+		buf->size -= i;
 		spin_unlock(&acm->throttle_lock);
+		spin_lock(&acm->read_lock);
+		list_add(&buf->list, &acm->filled_read_bufs);
+		spin_unlock(&acm->read_lock);
 		return;
 	}
 	spin_unlock(&acm->throttle_lock);
 
-	urb->actual_length = 0;
-	urb->dev = acm->dev;
-
-	i = usb_submit_urb(urb, GFP_ATOMIC);
-	if (i)
-		dev_dbg(&acm->data->dev, "bulk rx resubmit %d\n", i);
+	spin_lock(&acm->read_lock);
+	list_add(&buf->list, &acm->spare_read_bufs);
+	spin_unlock(&acm->read_lock);
+	goto next_buffer;
+
+urbs:
+	while (!list_empty(&acm->spare_read_bufs)) {
+		spin_lock(&acm->read_lock);
+		if (list_empty(&acm->spare_read_urbs)) {
+			spin_unlock(&acm->read_lock);
+			return;
+		}
+		rcv = list_entry(acm->spare_read_urbs.next,
+				 struct acm_ru, list);
+		list_del(&rcv->list);
+		spin_unlock(&acm->read_lock);
+
+		buf = list_entry(acm->spare_read_bufs.next,
+				 struct acm_rb, list);
+		list_del(&buf->list);
+
+		rcv->buffer = buf;
+
+		usb_fill_bulk_urb(rcv->urb, acm->dev,
+				  acm->rx_endpoint,
+				  buf->base,
+				  acm->readsize,
+				  acm_read_bulk, rcv);
+		rcv->urb->transfer_dma = buf->dma;
+		rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+		dbg("acm_rx_tasklet: sending urb 0x%p, rcv 0x%p, buf 0x%p\n", rcv->urb, rcv, buf);
+
+		/* This shouldn't kill the driver as unsuccessful URBs are returned to the
+		   free-urbs-pool and resubmited ASAP */
+		if (usb_submit_urb(rcv->urb, GFP_ATOMIC) < 0) {
+			list_add(&buf->list, &acm->spare_read_bufs);
+			spin_lock(&acm->read_lock);
+			list_add(&rcv->list, &acm->spare_read_urbs);
+			spin_unlock(&acm->read_lock);
+			return;
+		}
+	}
 }
 
 /* data interface wrote those outgoing bytes */
@@ -369,6 +434,7 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
 {
 	struct acm *acm;
 	int rv = -EINVAL;
+	int i;
 	dbg("Entering acm_tty_open.\n");
 	
 	down(&open_sem);
@@ -382,7 +448,9 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
 	tty->driver_data = acm;
 	acm->tty = tty;
 
-
+	/* force low_latency on so that our tty_push actually forces the data through,
+	   otherwise it is scheduled, and with high data rates data can get lost. */
+	tty->low_latency = 1;
 
 	if (acm->used++) {
 		goto done;
@@ -394,18 +462,20 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
 		goto bail_out;
 	}
 
-	acm->readurb->dev = acm->dev;
-	if (usb_submit_urb(acm->readurb, GFP_KERNEL)) {
-		dbg("usb_submit_urb(read bulk) failed");
-		goto bail_out_and_unlink;
-	}
-
 	if (0 > acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS))
 		goto full_bailout;
 
-	/* force low_latency on so that our tty_push actually forces the data through, 
-	   otherwise it is scheduled, and with high data rates data can get lost. */
-	tty->low_latency = 1;
+	INIT_LIST_HEAD(&acm->spare_read_urbs);
+	INIT_LIST_HEAD(&acm->spare_read_bufs);
+	INIT_LIST_HEAD(&acm->filled_read_bufs);
+	for (i = 0; i < ACM_NRU; i++) {
+		list_add(&(acm->ru[i].list), &acm->spare_read_urbs);
+	}
+	for (i = 0; i < ACM_NRB; i++) {
+		list_add(&(acm->rb[i].list), &acm->spare_read_bufs);
+	}
+
+	tasklet_schedule(&acm->urb_task);
 
 done:
 err_out:
@@ -413,8 +483,6 @@ err_out:
 	return rv;
 
 full_bailout:
-	usb_kill_urb(acm->readurb);
-bail_out_and_unlink:
 	usb_kill_urb(acm->ctrlurb);
 bail_out:
 	acm->used--;
@@ -424,18 +492,22 @@ bail_out:
 
 static void acm_tty_unregister(struct acm *acm)
 {
+	int i;
+
 	tty_unregister_device(acm_tty_driver, acm->minor);
 	usb_put_intf(acm->control);
 	acm_table[acm->minor] = NULL;
 	usb_free_urb(acm->ctrlurb);
-	usb_free_urb(acm->readurb);
 	usb_free_urb(acm->writeurb);
+	for (i = 0; i < ACM_NRU; i++)
+		usb_free_urb(acm->ru[i].urb);
 	kfree(acm);
 }
 
 static void acm_tty_close(struct tty_struct *tty, struct file *filp)
 {
 	struct acm *acm = tty->driver_data;
+	int i;
 
 	if (!acm || !acm->used)
 		return;
@@ -446,7 +518,8 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp)
 			acm_set_control(acm, acm->ctrlout = 0);
 			usb_kill_urb(acm->ctrlurb);
 			usb_kill_urb(acm->writeurb);
-			usb_kill_urb(acm->readurb);
+			for (i = 0; i < ACM_NRU; i++)
+				usb_kill_urb(acm->ru[i].urb);
 		} else
 			acm_tty_unregister(acm);
 	}
@@ -528,10 +601,7 @@ static void acm_tty_unthrottle(struct tty_struct *tty)
 	spin_lock_bh(&acm->throttle_lock);
 	acm->throttle = 0;
 	spin_unlock_bh(&acm->throttle_lock);
-	if (acm->resubmit_to_unthrottle) {
-		acm->resubmit_to_unthrottle = 0;
-		acm_read_bulk(acm->readurb, NULL);
-	}
+	tasklet_schedule(&acm->urb_task);
 }
 
 static void acm_tty_break_ctl(struct tty_struct *tty, int state)
@@ -588,7 +658,7 @@ static int acm_tty_ioctl(struct tty_struct *tty, struct file *file, unsigned int
 	return -ENOIOCTLCMD;
 }
 
-static __u32 acm_tty_speed[] = {
+static const __u32 acm_tty_speed[] = {
 	0, 50, 75, 110, 134, 150, 200, 300, 600,
 	1200, 1800, 2400, 4800, 9600, 19200, 38400,
 	57600, 115200, 230400, 460800, 500000, 576000,
@@ -596,7 +666,7 @@ static __u32 acm_tty_speed[] = {
 	2500000, 3000000, 3500000, 4000000
 };
 
-static __u8 acm_tty_size[] = {
+static const __u8 acm_tty_size[] = {
 	5, 6, 7, 8
 };
 
@@ -694,6 +764,7 @@ static int acm_probe (struct usb_interface *intf,
 	int call_interface_num = -1;
 	int data_interface_num;
 	unsigned long quirks;
+	int i;
 
 	/* handle quirks deadly to normal probing*/
 	quirks = (unsigned long)id->driver_info;
@@ -833,7 +904,7 @@ skip_normal_probe:
 	}
 
 	ctrlsize = le16_to_cpu(epctrl->wMaxPacketSize);
-	readsize = le16_to_cpu(epread->wMaxPacketSize);
+	readsize = le16_to_cpu(epread->wMaxPacketSize)*2;
 	acm->writesize = le16_to_cpu(epwrite->wMaxPacketSize);
 	acm->control = control_interface;
 	acm->data = data_interface;
@@ -842,12 +913,14 @@ skip_normal_probe:
 	acm->ctrl_caps = ac_management_function;
 	acm->ctrlsize = ctrlsize;
 	acm->readsize = readsize;
-	acm->bh.func = acm_rx_tasklet;
-	acm->bh.data = (unsigned long) acm;
+	acm->urb_task.func = acm_rx_tasklet;
+	acm->urb_task.data = (unsigned long) acm;
 	INIT_WORK(&acm->work, acm_softint, acm);
 	spin_lock_init(&acm->throttle_lock);
 	spin_lock_init(&acm->write_lock);
+	spin_lock_init(&acm->read_lock);
 	acm->write_ready = 1;
+	acm->rx_endpoint = usb_rcvbulkpipe(usb_dev, epread->bEndpointAddress);
 
 	buf = usb_buffer_alloc(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma);
 	if (!buf) {
@@ -856,13 +929,6 @@ skip_normal_probe:
 	}
 	acm->ctrl_buffer = buf;
 
-	buf = usb_buffer_alloc(usb_dev, readsize, GFP_KERNEL, &acm->read_dma);
-	if (!buf) {
-		dev_dbg(&intf->dev, "out of memory (read buffer alloc)\n");
-		goto alloc_fail3;
-	}
-	acm->read_buffer = buf;
-
 	if (acm_write_buffers_alloc(acm) < 0) {
 		dev_dbg(&intf->dev, "out of memory (write buffer alloc)\n");
 		goto alloc_fail4;
@@ -873,10 +939,25 @@ skip_normal_probe:
 		dev_dbg(&intf->dev, "out of memory (ctrlurb kmalloc)\n");
 		goto alloc_fail5;
 	}
-	acm->readurb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!acm->readurb) {
-		dev_dbg(&intf->dev, "out of memory (readurb kmalloc)\n");
-		goto alloc_fail6;
+	for (i = 0; i < ACM_NRU; i++) {
+		struct acm_ru *rcv = &(acm->ru[i]);
+
+		if (!(rcv->urb = usb_alloc_urb(0, GFP_KERNEL))) {
+			dev_dbg(&intf->dev, "out of memory (read urbs usb_alloc_urb)\n");
+			goto alloc_fail7;
+		}
+
+		rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+		rcv->instance = acm;
+	}
+	for (i = 0; i < ACM_NRB; i++) {
+		struct acm_rb *buf = &(acm->rb[i]);
+
+		// Using usb_buffer_alloc instead of kmalloc as Oliver suggested
+		if (!(buf->base = usb_buffer_alloc(acm->dev, readsize, GFP_KERNEL, &buf->dma))) {
+			dev_dbg(&intf->dev, "out of memory (read bufs usb_buffer_alloc)\n");
+			goto alloc_fail7;
+		}
 	}
 	acm->writeurb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!acm->writeurb) {
@@ -889,15 +970,9 @@ skip_normal_probe:
 	acm->ctrlurb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 	acm->ctrlurb->transfer_dma = acm->ctrl_dma;
 
-	usb_fill_bulk_urb(acm->readurb, usb_dev, usb_rcvbulkpipe(usb_dev, epread->bEndpointAddress),
-			  acm->read_buffer, readsize, acm_read_bulk, acm);
-	acm->readurb->transfer_flags |= URB_NO_FSBR | URB_NO_TRANSFER_DMA_MAP;
-	acm->readurb->transfer_dma = acm->read_dma;
-
 	usb_fill_bulk_urb(acm->writeurb, usb_dev, usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress),
 			  NULL, acm->writesize, acm_write_bulk, acm);
 	acm->writeurb->transfer_flags |= URB_NO_FSBR | URB_NO_TRANSFER_DMA_MAP;
-	/* acm->writeurb->transfer_dma = 0; */
 
 	dev_info(&intf->dev, "ttyACM%d: USB ACM device\n", minor);
 
@@ -917,14 +992,14 @@ skip_normal_probe:
 	return 0;
 
 alloc_fail7:
-	usb_free_urb(acm->readurb);
-alloc_fail6:
+	for (i = 0; i < ACM_NRB; i++)
+		usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma);
+	for (i = 0; i < ACM_NRU; i++)
+		usb_free_urb(acm->ru[i].urb);
 	usb_free_urb(acm->ctrlurb);
 alloc_fail5:
 	acm_write_buffers_free(acm);
 alloc_fail4:
-	usb_buffer_free(usb_dev, readsize, acm->read_buffer, acm->read_dma);
-alloc_fail3:
 	usb_buffer_free(usb_dev, ctrlsize, acm->ctrl_buffer, acm->ctrl_dma);
 alloc_fail2:
 	kfree(acm);
@@ -936,6 +1011,7 @@ static void acm_disconnect(struct usb_interface *intf)
 {
 	struct acm *acm = usb_get_intfdata (intf);
 	struct usb_device *usb_dev = interface_to_usbdev(intf);
+	int i;
 
 	if (!acm || !acm->dev) {
 		dbg("disconnect on nonexisting interface");
@@ -946,15 +1022,24 @@ static void acm_disconnect(struct usb_interface *intf)
 	acm->dev = NULL;
 	usb_set_intfdata (intf, NULL);
 
+	tasklet_disable(&acm->urb_task);
+
 	usb_kill_urb(acm->ctrlurb);
-	usb_kill_urb(acm->readurb);
 	usb_kill_urb(acm->writeurb);
+	for (i = 0; i < ACM_NRU; i++)
+		usb_kill_urb(acm->ru[i].urb);
+
+	INIT_LIST_HEAD(&acm->filled_read_bufs);
+	INIT_LIST_HEAD(&acm->spare_read_bufs);
+
+	tasklet_enable(&acm->urb_task);
 
 	flush_scheduled_work(); /* wait for acm_softint */
 
 	acm_write_buffers_free(acm);
-	usb_buffer_free(usb_dev, acm->readsize, acm->read_buffer, acm->read_dma);
 	usb_buffer_free(usb_dev, acm->ctrlsize, acm->ctrl_buffer, acm->ctrl_dma);
+	for (i = 0; i < ACM_NRB; i++)
+		usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma);
 
 	usb_driver_release_interface(&acm_driver, acm->data);
 
@@ -1003,7 +1088,6 @@ static struct usb_device_id acm_ids[] = {
 MODULE_DEVICE_TABLE (usb, acm_ids);
 
 static struct usb_driver acm_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"cdc_acm",
 	.probe =	acm_probe,
 	.disconnect =	acm_disconnect,
diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h
index 963a5dfd2096..fd2aaccdcbac 100644
--- a/drivers/usb/class/cdc-acm.h
+++ b/drivers/usb/class/cdc-acm.h
@@ -59,6 +59,9 @@
  * when processing onlcr, so we only need 2 buffers.
  */
 #define ACM_NWB  2
+#define ACM_NRU  16
+#define ACM_NRB  16
+
 struct acm_wb {
 	unsigned char *buf;
 	dma_addr_t dmah;
@@ -66,22 +69,43 @@ struct acm_wb {
 	int use;
 };
 
+struct acm_rb {
+	struct list_head	list;
+	int			size;
+	unsigned char		*base;
+	dma_addr_t		dma;
+};
+
+struct acm_ru {
+	struct list_head	list;
+	struct acm_rb		*buffer;
+	struct urb		*urb;
+	struct acm		*instance;
+};
+
 struct acm {
 	struct usb_device *dev;				/* the corresponding usb device */
 	struct usb_interface *control;			/* control interface */
 	struct usb_interface *data;			/* data interface */
 	struct tty_struct *tty;				/* the corresponding tty */
-	struct urb *ctrlurb, *readurb, *writeurb;	/* urbs */
-	u8 *ctrl_buffer, *read_buffer;			/* buffers of urbs */
-	dma_addr_t ctrl_dma, read_dma;			/* dma handles of buffers */
+	struct urb *ctrlurb, *writeurb;			/* urbs */
+	u8 *ctrl_buffer;				/* buffers of urbs */
+	dma_addr_t ctrl_dma;				/* dma handles of buffers */
 	struct acm_wb wb[ACM_NWB];
+	struct acm_ru ru[ACM_NRU];
+	struct acm_rb rb[ACM_NRB];
+	int rx_endpoint;
+	spinlock_t read_lock;
+	struct list_head spare_read_urbs;
+	struct list_head spare_read_bufs;
+	struct list_head filled_read_bufs;
 	int write_current;				/* current write buffer */
 	int write_used;					/* number of non-empty write buffers */
 	int write_ready;				/* write urb is not running */
 	spinlock_t write_lock;
 	struct usb_cdc_line_coding line;		/* bits, stop, parity */
 	struct work_struct work;			/* work queue entry for line discipline waking up */
-	struct tasklet_struct bh;			/* rx processing */
+	struct tasklet_struct urb_task;                 /* rx processing */
 	spinlock_t throttle_lock;			/* synchronize throtteling and read callback */
 	unsigned int ctrlin;				/* input control lines (DCD, DSR, RI, break, overruns) */
 	unsigned int ctrlout;				/* output control lines (DTR, RTS) */
@@ -91,7 +115,6 @@ struct acm {
 	unsigned int minor;				/* acm minor number */
 	unsigned char throttle;				/* throttled by tty layer */
 	unsigned char clocal;				/* termios CLOCAL */
-	unsigned char resubmit_to_unthrottle;		/* throtteling has disabled the read urb */
 	unsigned int ctrl_caps;				/* control capabilities from the class specific header */
 };
 
diff --git a/drivers/usb/class/usb-midi.c b/drivers/usb/class/usb-midi.c
index 5f8af35e7633..f13f004d311f 100644
--- a/drivers/usb/class/usb-midi.c
+++ b/drivers/usb/class/usb-midi.c
@@ -2027,7 +2027,6 @@ static struct usb_device_id id_table[] = {
 };
 
 static struct usb_driver usb_midi_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"midi",
 	.probe =	usb_midi_probe,
 	.disconnect =	usb_midi_disconnect,
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
index 357e75335f17..dba4cc026077 100644
--- a/drivers/usb/class/usblp.c
+++ b/drivers/usb/class/usblp.c
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 1999 Michael Gee	<michael@linuxspecific.com>
  * Copyright (c) 1999 Pavel Machek	<pavel@suse.cz>
- * Copyright (c) 2000 Randy Dunlap	<rddunlap@osdl.org>
+ * Copyright (c) 2000 Randy Dunlap	<rdunlap@xenotime.net>
  * Copyright (c) 2000 Vojtech Pavlik	<vojtech@suse.cz>
  # Copyright (c) 2001 Pete Zaitcev	<zaitcev@redhat.com>
  # Copyright (c) 2001 David Paschal	<paschal@rcsis.com>
@@ -199,7 +199,7 @@ struct quirk_printer_struct {
 #define USBLP_QUIRK_BIDIR	0x1	/* reports bidir but requires unidirectional mode (no INs/reads) */
 #define USBLP_QUIRK_USB_INIT	0x2	/* needs vendor USB init string */
 
-static struct quirk_printer_struct quirk_printers[] = {
+static const struct quirk_printer_struct quirk_printers[] = {
 	{ 0x03f0, 0x0004, USBLP_QUIRK_BIDIR }, /* HP DeskJet 895C */
 	{ 0x03f0, 0x0104, USBLP_QUIRK_BIDIR }, /* HP DeskJet 880C */
 	{ 0x03f0, 0x0204, USBLP_QUIRK_BIDIR }, /* HP DeskJet 815C */
@@ -301,7 +301,7 @@ static void usblp_bulk_write(struct urb *urb, struct pt_regs *regs)
  * Get and print printer errors.
  */
 
-static char *usblp_messages[] = { "ok", "out of paper", "off-line", "on fire" };
+static const char *usblp_messages[] = { "ok", "out of paper", "off-line", "on fire" };
 
 static int usblp_check_status(struct usblp *usblp, int err)
 {
@@ -438,7 +438,7 @@ static unsigned int usblp_poll(struct file *file, struct poll_table_struct *wait
  			       | (!usblp->wcomplete ? 0 : POLLOUT | POLLWRNORM);
 }
 
-static int usblp_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 	struct usblp *usblp = file->private_data;
 	int length, err, i;
@@ -838,7 +838,8 @@ static struct file_operations usblp_fops = {
 	.read =		usblp_read,
 	.write =	usblp_write,
 	.poll =		usblp_poll,
-	.ioctl =	usblp_ioctl,
+	.unlocked_ioctl =	usblp_ioctl,
+	.compat_ioctl =		usblp_ioctl,
 	.open =		usblp_open,
 	.release =	usblp_release,
 };
@@ -849,6 +850,20 @@ static struct usb_class_driver usblp_class = {
 	.minor_base =	USBLP_MINOR_BASE,
 };
 
+static ssize_t usblp_show_ieee1284_id(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct usb_interface *intf = to_usb_interface(dev);
+	struct usblp *usblp = usb_get_intfdata (intf);
+
+	if (usblp->device_id_string[0] == 0 &&
+	    usblp->device_id_string[1] == 0)
+		return 0;
+
+	return sprintf(buf, "%s", usblp->device_id_string+2);
+}
+
+static DEVICE_ATTR(ieee1284_id, S_IRUGO, usblp_show_ieee1284_id, NULL);
+
 static int usblp_probe(struct usb_interface *intf,
 		       const struct usb_device_id *id)
 {
@@ -933,20 +948,12 @@ static int usblp_probe(struct usb_interface *intf,
 
 	/* Retrieve and store the device ID string. */
 	usblp_cache_device_id_string(usblp);
+	device_create_file(&intf->dev, &dev_attr_ieee1284_id);
 
 #ifdef DEBUG
 	usblp_check_status(usblp, 0);
 #endif
 
-	info("usblp%d: USB %sdirectional printer dev %d "
-		"if %d alt %d proto %d vid 0x%4.4X pid 0x%4.4X",
-		usblp->minor, usblp->bidir ? "Bi" : "Uni", dev->devnum,
-		usblp->ifnum,
-		usblp->protocol[usblp->current_protocol].alt_setting,
-		usblp->current_protocol,
-		le16_to_cpu(usblp->dev->descriptor.idVendor),
-		le16_to_cpu(usblp->dev->descriptor.idProduct));
-
 	usb_set_intfdata (intf, usblp);
 
 	usblp->present = 1;
@@ -957,11 +964,20 @@ static int usblp_probe(struct usb_interface *intf,
 		goto abort_intfdata;
 	}
 	usblp->minor = intf->minor;
+	info("usblp%d: USB %sdirectional printer dev %d "
+		"if %d alt %d proto %d vid 0x%4.4X pid 0x%4.4X",
+		usblp->minor, usblp->bidir ? "Bi" : "Uni", dev->devnum,
+		usblp->ifnum,
+		usblp->protocol[usblp->current_protocol].alt_setting,
+		usblp->current_protocol,
+		le16_to_cpu(usblp->dev->descriptor.idVendor),
+		le16_to_cpu(usblp->dev->descriptor.idProduct));
 
 	return 0;
 
 abort_intfdata:
 	usb_set_intfdata (intf, NULL);
+	device_remove_file(&intf->dev, &dev_attr_ieee1284_id);
 abort:
 	if (usblp) {
 		if (usblp->writebuf)
@@ -1156,6 +1172,8 @@ static void usblp_disconnect(struct usb_interface *intf)
 		BUG ();
 	}
 
+	device_remove_file(&intf->dev, &dev_attr_ieee1284_id);
+
 	down (&usblp_sem);
 	down (&usblp->sem);
 	usblp->present = 0;
@@ -1186,7 +1204,6 @@ static struct usb_device_id usblp_ids [] = {
 MODULE_DEVICE_TABLE (usb, usblp_ids);
 
 static struct usb_driver usblp_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"usblp",
 	.probe =	usblp_probe,
 	.disconnect =	usblp_disconnect,
diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile
index 86d5c380892d..28329ddf187c 100644
--- a/drivers/usb/core/Makefile
+++ b/drivers/usb/core/Makefile
@@ -2,7 +2,7 @@
 # Makefile for USB Core files and filesystem
 #
 
-usbcore-objs	:= usb.o hub.o hcd.o urb.o message.o \
+usbcore-objs	:= usb.o hub.o hcd.o urb.o message.o driver.o \
 			config.o file.o buffer.o sysfs.o devio.o notify.o
 
 ifeq ($(CONFIG_PCI),y)
diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c
index 419c9943a7cb..ad742cec94fa 100644
--- a/drivers/usb/core/buffer.c
+++ b/drivers/usb/core/buffer.c
@@ -55,6 +55,9 @@ int hcd_buffer_create (struct usb_hcd *hcd)
 	char		name [16];
 	int 		i, size;
 
+	if (!hcd->self.controller->dma_mask)
+		return 0;
+
 	for (i = 0; i < HCD_BUFFER_POOLS; i++) { 
 		if (!(size = pool_max [i]))
 			continue;
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
index 83e815d3cd52..2684e15b813b 100644
--- a/drivers/usb/core/devices.c
+++ b/drivers/usb/core/devices.c
@@ -67,45 +67,45 @@
 /* Define ALLOW_SERIAL_NUMBER if you want to see the serial number of devices */
 #define ALLOW_SERIAL_NUMBER
 
-static char *format_topo =
+static const char *format_topo =
 /* T:  Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=ddd MxCh=dd */
 "\nT:  Bus=%2.2d Lev=%2.2d Prnt=%2.2d Port=%2.2d Cnt=%2.2d Dev#=%3d Spd=%3s MxCh=%2d\n";
 
-static char *format_string_manufacturer =
+static const char *format_string_manufacturer =
 /* S:  Manufacturer=xxxx */
   "S:  Manufacturer=%.100s\n";
 
-static char *format_string_product =
+static const char *format_string_product =
 /* S:  Product=xxxx */
   "S:  Product=%.100s\n";
 
 #ifdef ALLOW_SERIAL_NUMBER
-static char *format_string_serialnumber =
+static const char *format_string_serialnumber =
 /* S:  SerialNumber=xxxx */
   "S:  SerialNumber=%.100s\n";
 #endif
 
-static char *format_bandwidth =
+static const char *format_bandwidth =
 /* B:  Alloc=ddd/ddd us (xx%), #Int=ddd, #Iso=ddd */
   "B:  Alloc=%3d/%3d us (%2d%%), #Int=%3d, #Iso=%3d\n";
   
-static char *format_device1 =
+static const char *format_device1 =
 /* D:  Ver=xx.xx Cls=xx(sssss) Sub=xx Prot=xx MxPS=dd #Cfgs=dd */
   "D:  Ver=%2x.%02x Cls=%02x(%-5s) Sub=%02x Prot=%02x MxPS=%2d #Cfgs=%3d\n";
 
-static char *format_device2 =
+static const char *format_device2 =
 /* P:  Vendor=xxxx ProdID=xxxx Rev=xx.xx */
   "P:  Vendor=%04x ProdID=%04x Rev=%2x.%02x\n";
 
-static char *format_config =
+static const char *format_config =
 /* C:  #Ifs=dd Cfg#=dd Atr=xx MPwr=dddmA */
   "C:%c #Ifs=%2d Cfg#=%2d Atr=%02x MxPwr=%3dmA\n";
   
-static char *format_iface =
+static const char *format_iface =
 /* I:  If#=dd Alt=dd #EPs=dd Cls=xx(sssss) Sub=xx Prot=xx Driver=xxxx*/
   "I:  If#=%2d Alt=%2d #EPs=%2d Cls=%02x(%-5s) Sub=%02x Prot=%02x Driver=%s\n";
 
-static char *format_endpt =
+static const char *format_endpt =
 /* E:  Ad=xx(s) Atr=xx(ssss) MxPS=dddd Ivl=D?s */
   "E:  Ad=%02x(%c) Atr=%02x(%-4s) MxPS=%4d Ivl=%d%cs\n";
 
@@ -545,10 +545,10 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, loff_t *ski
 		struct usb_device *childdev = usbdev->children[chix];
 
 		if (childdev) {
-			down(&childdev->serialize);
+			usb_lock_device(childdev);
 			ret = usb_device_dump(buffer, nbytes, skip_bytes, file_offset, childdev,
 					bus, level + 1, chix, ++cnt);
-			up(&childdev->serialize);
+			usb_unlock_device(childdev);
 			if (ret == -EFAULT)
 				return total_written;
 			total_written += ret;
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index b1d6e9af732d..2b68998fe4b3 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -402,7 +402,6 @@ static void driver_disconnect(struct usb_interface *intf)
 }
 
 struct usb_driver usbfs_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"usbfs",
 	.probe =	driver_probe,
 	.disconnect =	driver_disconnect,
@@ -1350,9 +1349,7 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl)
 	/* let kernel drivers try to (re)bind to the interface */
 	case USBDEVFS_CONNECT:
 		usb_unlock_device(ps->dev);
-		usb_lock_all_devices();
 		bus_rescan_devices(intf->dev.bus);
-		usb_unlock_all_devices();
 		usb_lock_device(ps->dev);
 		break;
 
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
new file mode 100644
index 000000000000..076462c8ba2a
--- /dev/null
+++ b/drivers/usb/core/driver.c
@@ -0,0 +1,472 @@
+/*
+ * drivers/usb/driver.c - most of the driver model stuff for usb
+ *
+ * (C) Copyright 2005 Greg Kroah-Hartman <gregkh@suse.de>
+ *
+ * based on drivers/usb/usb.c which had the following copyrights:
+ *	(C) Copyright Linus Torvalds 1999
+ *	(C) Copyright Johannes Erdfelt 1999-2001
+ *	(C) Copyright Andreas Gal 1999
+ *	(C) Copyright Gregory P. Smith 1999
+ *	(C) Copyright Deti Fliegl 1999 (new USB architecture)
+ *	(C) Copyright Randy Dunlap 2000
+ *	(C) Copyright David Brownell 2000-2004
+ *	(C) Copyright Yggdrasil Computing, Inc. 2000
+ *		(usb_device_id matching changes by Adam J. Richter)
+ *	(C) Copyright Greg Kroah-Hartman 2002-2003
+ *
+ * NOTE! This is not actually a driver at all, rather this is
+ * just a collection of helper routines that implement the
+ * generic USB things that the real drivers can use..
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/device.h>
+#include <linux/usb.h>
+#include "hcd.h"
+#include "usb.h"
+
+static int usb_match_one_id(struct usb_interface *interface,
+			    const struct usb_device_id *id);
+
+struct usb_dynid {
+	struct list_head node;
+	struct usb_device_id id;
+};
+
+
+static int generic_probe(struct device *dev)
+{
+	return 0;
+}
+static int generic_remove(struct device *dev)
+{
+	struct usb_device *udev = to_usb_device(dev);
+
+	/* if this is only an unbind, not a physical disconnect, then
+	 * unconfigure the device */
+	if (udev->state == USB_STATE_CONFIGURED)
+		usb_set_configuration(udev, 0);
+
+	/* in case the call failed or the device was suspended */
+	if (udev->state >= USB_STATE_CONFIGURED)
+		usb_disable_device(udev, 0);
+	return 0;
+}
+
+struct device_driver usb_generic_driver = {
+	.owner = THIS_MODULE,
+	.name =	"usb",
+	.bus = &usb_bus_type,
+	.probe = generic_probe,
+	.remove = generic_remove,
+};
+
+/* Fun hack to determine if the struct device is a
+ * usb device or a usb interface. */
+int usb_generic_driver_data;
+
+#ifdef CONFIG_HOTPLUG
+
+/*
+ * Adds a new dynamic USBdevice ID to this driver,
+ * and cause the driver to probe for all devices again.
+ */
+static ssize_t store_new_id(struct device_driver *driver,
+			    const char *buf, size_t count)
+{
+	struct usb_driver *usb_drv = to_usb_driver(driver);
+	struct usb_dynid *dynid;
+	u32 idVendor = 0;
+	u32 idProduct = 0;
+	int fields = 0;
+
+	fields = sscanf(buf, "%x %x", &idVendor, &idProduct);
+	if (fields < 2)
+		return -EINVAL;
+
+	dynid = kzalloc(sizeof(*dynid), GFP_KERNEL);
+	if (!dynid)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&dynid->node);
+	dynid->id.idVendor = idVendor;
+	dynid->id.idProduct = idProduct;
+	dynid->id.match_flags = USB_DEVICE_ID_MATCH_DEVICE;
+
+	spin_lock(&usb_drv->dynids.lock);
+	list_add_tail(&usb_drv->dynids.list, &dynid->node);
+	spin_unlock(&usb_drv->dynids.lock);
+
+	if (get_driver(driver)) {
+		driver_attach(driver);
+		put_driver(driver);
+	}
+
+	return count;
+}
+static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id);
+
+static int usb_create_newid_file(struct usb_driver *usb_drv)
+{
+	int error = 0;
+
+	if (usb_drv->no_dynamic_id)
+		goto exit;
+
+	if (usb_drv->probe != NULL)
+		error = sysfs_create_file(&usb_drv->driver.kobj,
+					  &driver_attr_new_id.attr);
+exit:
+	return error;
+}
+
+static void usb_remove_newid_file(struct usb_driver *usb_drv)
+{
+	if (usb_drv->no_dynamic_id)
+		return;
+
+	if (usb_drv->probe != NULL)
+		sysfs_remove_file(&usb_drv->driver.kobj,
+				  &driver_attr_new_id.attr);
+}
+
+static void usb_free_dynids(struct usb_driver *usb_drv)
+{
+	struct usb_dynid *dynid, *n;
+
+	spin_lock(&usb_drv->dynids.lock);
+	list_for_each_entry_safe(dynid, n, &usb_drv->dynids.list, node) {
+		list_del(&dynid->node);
+		kfree(dynid);
+	}
+	spin_unlock(&usb_drv->dynids.lock);
+}
+#else
+static inline int usb_create_newid_file(struct usb_driver *usb_drv)
+{
+	return 0;
+}
+
+static void usb_remove_newid_file(struct usb_driver *usb_drv)
+{
+}
+
+static inline void usb_free_dynids(struct usb_driver *usb_drv)
+{
+}
+#endif
+
+static const struct usb_device_id *usb_match_dynamic_id(struct usb_interface *intf,
+							struct usb_driver *drv)
+{
+	struct usb_dynid *dynid;
+
+	spin_lock(&drv->dynids.lock);
+	list_for_each_entry(dynid, &drv->dynids.list, node) {
+		if (usb_match_one_id(intf, &dynid->id)) {
+			spin_unlock(&drv->dynids.lock);
+			return &dynid->id;
+		}
+	}
+	spin_unlock(&drv->dynids.lock);
+	return NULL;
+}
+
+
+/* called from driver core with usb_bus_type.subsys writelock */
+static int usb_probe_interface(struct device *dev)
+{
+	struct usb_interface * intf = to_usb_interface(dev);
+	struct usb_driver * driver = to_usb_driver(dev->driver);
+	const struct usb_device_id *id;
+	int error = -ENODEV;
+
+	dev_dbg(dev, "%s\n", __FUNCTION__);
+
+	if (!driver->probe)
+		return error;
+	/* FIXME we'd much prefer to just resume it ... */
+	if (interface_to_usbdev(intf)->state == USB_STATE_SUSPENDED)
+		return -EHOSTUNREACH;
+
+	id = usb_match_id(intf, driver->id_table);
+	if (!id)
+		id = usb_match_dynamic_id(intf, driver);
+	if (id) {
+		dev_dbg(dev, "%s - got id\n", __FUNCTION__);
+
+		/* Interface "power state" doesn't correspond to any hardware
+		 * state whatsoever.  We use it to record when it's bound to
+		 * a driver that may start I/0:  it's not frozen/quiesced.
+		 */
+		mark_active(intf);
+		intf->condition = USB_INTERFACE_BINDING;
+		error = driver->probe(intf, id);
+		if (error) {
+			mark_quiesced(intf);
+			intf->condition = USB_INTERFACE_UNBOUND;
+		} else
+			intf->condition = USB_INTERFACE_BOUND;
+	}
+
+	return error;
+}
+
+/* called from driver core with usb_bus_type.subsys writelock */
+static int usb_unbind_interface(struct device *dev)
+{
+	struct usb_interface *intf = to_usb_interface(dev);
+	struct usb_driver *driver = to_usb_driver(intf->dev.driver);
+
+	intf->condition = USB_INTERFACE_UNBINDING;
+
+	/* release all urbs for this interface */
+	usb_disable_interface(interface_to_usbdev(intf), intf);
+
+	if (driver && driver->disconnect)
+		driver->disconnect(intf);
+
+	/* reset other interface state */
+	usb_set_interface(interface_to_usbdev(intf),
+			intf->altsetting[0].desc.bInterfaceNumber,
+			0);
+	usb_set_intfdata(intf, NULL);
+	intf->condition = USB_INTERFACE_UNBOUND;
+	mark_quiesced(intf);
+
+	return 0;
+}
+
+/* returns 0 if no match, 1 if match */
+static int usb_match_one_id(struct usb_interface *interface,
+			    const struct usb_device_id *id)
+{
+	struct usb_host_interface *intf;
+	struct usb_device *dev;
+
+	/* proc_connectinfo in devio.c may call us with id == NULL. */
+	if (id == NULL)
+		return 0;
+
+	intf = interface->cur_altsetting;
+	dev = interface_to_usbdev(interface);
+
+	if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
+	    id->idVendor != le16_to_cpu(dev->descriptor.idVendor))
+		return 0;
+
+	if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&
+	    id->idProduct != le16_to_cpu(dev->descriptor.idProduct))
+		return 0;
+
+	/* No need to test id->bcdDevice_lo != 0, since 0 is never
+	   greater than any unsigned number. */
+	if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) &&
+	    (id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice)))
+		return 0;
+
+	if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) &&
+	    (id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice)))
+		return 0;
+
+	if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&
+	    (id->bDeviceClass != dev->descriptor.bDeviceClass))
+		return 0;
+
+	if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
+	    (id->bDeviceSubClass!= dev->descriptor.bDeviceSubClass))
+		return 0;
+
+	if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&
+	    (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
+		return 0;
+
+	if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) &&
+	    (id->bInterfaceClass != intf->desc.bInterfaceClass))
+		return 0;
+
+	if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS) &&
+	    (id->bInterfaceSubClass != intf->desc.bInterfaceSubClass))
+		return 0;
+
+	if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL) &&
+	    (id->bInterfaceProtocol != intf->desc.bInterfaceProtocol))
+		return 0;
+
+	return 1;
+}
+/**
+ * usb_match_id - find first usb_device_id matching device or interface
+ * @interface: the interface of interest
+ * @id: array of usb_device_id structures, terminated by zero entry
+ *
+ * usb_match_id searches an array of usb_device_id's and returns
+ * the first one matching the device or interface, or null.
+ * This is used when binding (or rebinding) a driver to an interface.
+ * Most USB device drivers will use this indirectly, through the usb core,
+ * but some layered driver frameworks use it directly.
+ * These device tables are exported with MODULE_DEVICE_TABLE, through
+ * modutils, to support the driver loading functionality of USB hotplugging.
+ *
+ * What Matches:
+ *
+ * The "match_flags" element in a usb_device_id controls which
+ * members are used.  If the corresponding bit is set, the
+ * value in the device_id must match its corresponding member
+ * in the device or interface descriptor, or else the device_id
+ * does not match.
+ *
+ * "driver_info" is normally used only by device drivers,
+ * but you can create a wildcard "matches anything" usb_device_id
+ * as a driver's "modules.usbmap" entry if you provide an id with
+ * only a nonzero "driver_info" field.  If you do this, the USB device
+ * driver's probe() routine should use additional intelligence to
+ * decide whether to bind to the specified interface.
+ *
+ * What Makes Good usb_device_id Tables:
+ *
+ * The match algorithm is very simple, so that intelligence in
+ * driver selection must come from smart driver id records.
+ * Unless you have good reasons to use another selection policy,
+ * provide match elements only in related groups, and order match
+ * specifiers from specific to general.  Use the macros provided
+ * for that purpose if you can.
+ *
+ * The most specific match specifiers use device descriptor
+ * data.  These are commonly used with product-specific matches;
+ * the USB_DEVICE macro lets you provide vendor and product IDs,
+ * and you can also match against ranges of product revisions.
+ * These are widely used for devices with application or vendor
+ * specific bDeviceClass values.
+ *
+ * Matches based on device class/subclass/protocol specifications
+ * are slightly more general; use the USB_DEVICE_INFO macro, or
+ * its siblings.  These are used with single-function devices
+ * where bDeviceClass doesn't specify that each interface has
+ * its own class.
+ *
+ * Matches based on interface class/subclass/protocol are the
+ * most general; they let drivers bind to any interface on a
+ * multiple-function device.  Use the USB_INTERFACE_INFO
+ * macro, or its siblings, to match class-per-interface style
+ * devices (as recorded in bDeviceClass).
+ *
+ * Within those groups, remember that not all combinations are
+ * meaningful.  For example, don't give a product version range
+ * without vendor and product IDs; or specify a protocol without
+ * its associated class and subclass.
+ */
+const struct usb_device_id *usb_match_id(struct usb_interface *interface,
+					 const struct usb_device_id *id)
+{
+	/* proc_connectinfo in devio.c may call us with id == NULL. */
+	if (id == NULL)
+		return NULL;
+
+	/* It is important to check that id->driver_info is nonzero,
+	   since an entry that is all zeroes except for a nonzero
+	   id->driver_info is the way to create an entry that
+	   indicates that the driver want to examine every
+	   device and interface. */
+	for (; id->idVendor || id->bDeviceClass || id->bInterfaceClass ||
+	       id->driver_info; id++) {
+		if (usb_match_one_id(interface, id))
+			return id;
+	}
+
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(usb_match_id);
+
+int usb_device_match(struct device *dev, struct device_driver *drv)
+{
+	struct usb_interface *intf;
+	struct usb_driver *usb_drv;
+	const struct usb_device_id *id;
+
+	/* check for generic driver, which we don't match any device with */
+	if (drv == &usb_generic_driver)
+		return 0;
+
+	intf = to_usb_interface(dev);
+	usb_drv = to_usb_driver(drv);
+
+	id = usb_match_id(intf, usb_drv->id_table);
+	if (id)
+		return 1;
+
+	id = usb_match_dynamic_id(intf, usb_drv);
+	if (id)
+		return 1;
+	return 0;
+}
+
+/**
+ * usb_register_driver - register a USB driver
+ * @new_driver: USB operations for the driver
+ * @owner: module owner of this driver.
+ *
+ * Registers a USB driver with the USB core.  The list of unattached
+ * interfaces will be rescanned whenever a new driver is added, allowing
+ * the new driver to attach to any recognized devices.
+ * Returns a negative error code on failure and 0 on success.
+ *
+ * NOTE: if you want your driver to use the USB major number, you must call
+ * usb_register_dev() to enable that functionality.  This function no longer
+ * takes care of that.
+ */
+int usb_register_driver(struct usb_driver *new_driver, struct module *owner)
+{
+	int retval = 0;
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	new_driver->driver.name = (char *)new_driver->name;
+	new_driver->driver.bus = &usb_bus_type;
+	new_driver->driver.probe = usb_probe_interface;
+	new_driver->driver.remove = usb_unbind_interface;
+	new_driver->driver.owner = owner;
+	spin_lock_init(&new_driver->dynids.lock);
+	INIT_LIST_HEAD(&new_driver->dynids.list);
+
+	retval = driver_register(&new_driver->driver);
+
+	if (!retval) {
+		pr_info("%s: registered new driver %s\n",
+			usbcore_name, new_driver->name);
+		usbfs_update_special();
+		usb_create_newid_file(new_driver);
+	} else {
+		printk(KERN_ERR "%s: error %d registering driver %s\n",
+			usbcore_name, retval, new_driver->name);
+	}
+
+	return retval;
+}
+EXPORT_SYMBOL_GPL(usb_register_driver);
+
+/**
+ * usb_deregister - unregister a USB driver
+ * @driver: USB operations of the driver to unregister
+ * Context: must be able to sleep
+ *
+ * Unlinks the specified driver from the internal USB driver list.
+ *
+ * NOTE: If you called usb_register_dev(), you still need to call
+ * usb_deregister_dev() to clean up your driver's allocated minor numbers,
+ * this * call will no longer do it for you.
+ */
+void usb_deregister(struct usb_driver *driver)
+{
+	pr_info("%s: deregistering driver %s\n", usbcore_name, driver->name);
+
+	usb_remove_newid_file(driver);
+	usb_free_dynids(driver);
+	driver_unregister(&driver->driver);
+
+	usbfs_update_special();
+}
+EXPORT_SYMBOL_GPL(usb_deregister);
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index da24c31ee00d..0018bbc4de34 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -857,9 +857,7 @@ static int register_root_hub (struct usb_device *usb_dev,
 		return (retval < 0) ? retval : -EMSGSIZE;
 	}
 
-	usb_lock_device (usb_dev);
 	retval = usb_new_device (usb_dev);
-	usb_unlock_device (usb_dev);
 	if (retval) {
 		usb_dev->bus->root_hub = NULL;
 		dev_err (parent_dev, "can't register root hub for %s, %d\n",
@@ -1827,8 +1825,6 @@ int usb_add_hcd(struct usb_hcd *hcd,
 		retval = -ENOMEM;
 		goto err_allocate_root_hub;
 	}
-	rhdev->speed = (hcd->driver->flags & HCD_USB2) ? USB_SPEED_HIGH :
-			USB_SPEED_FULL;
 
 	/* Although in principle hcd->driver->start() might need to use rhdev,
 	 * none of the current drivers do.
@@ -1846,6 +1842,9 @@ int usb_add_hcd(struct usb_hcd *hcd,
 		dev_dbg(hcd->self.controller, "supports USB remote wakeup\n");
 	hcd->remote_wakeup = hcd->can_wakeup;
 
+	rhdev->speed = (hcd->driver->flags & HCD_USB2) ? USB_SPEED_HIGH :
+			USB_SPEED_FULL;
+	rhdev->bus_mA = min(500u, hcd->power_budget);
 	if ((retval = register_root_hub(rhdev, hcd)) != 0)
 		goto err_register_root_hub;
 
@@ -1891,7 +1890,10 @@ void usb_remove_hcd(struct usb_hcd *hcd)
 	spin_lock_irq (&hcd_root_hub_lock);
 	hcd->rh_registered = 0;
 	spin_unlock_irq (&hcd_root_hub_lock);
+
+	down(&usb_bus_list_lock);
 	usb_disconnect(&hcd->self.root_hub);
+	up(&usb_bus_list_lock);
 
 	hcd->poll_rh = 0;
 	del_timer_sync(&hcd->rh_timer);
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
index c8a1b350e2cf..591b5aad1a18 100644
--- a/drivers/usb/core/hcd.h
+++ b/drivers/usb/core/hcd.h
@@ -380,6 +380,7 @@ extern int usb_find_interface_driver (struct usb_device *dev,
 #ifdef CONFIG_PM
 extern void usb_hcd_suspend_root_hub (struct usb_hcd *hcd);
 extern void usb_hcd_resume_root_hub (struct usb_hcd *hcd);
+extern void usb_root_hub_lost_power (struct usb_device *rhdev);
 extern int hcd_bus_suspend (struct usb_bus *bus);
 extern int hcd_bus_resume (struct usb_bus *bus);
 #else
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index f78bd124d290..650d5ee5871b 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -32,7 +32,7 @@
 #include "hub.h"
 
 /* Protect struct usb_device->state and ->children members
- * Note: Both are also protected by ->serialize, except that ->state can
+ * Note: Both are also protected by ->dev.sem, except that ->state can
  * change to USB_STATE_NOTATTACHED even when the semaphore isn't held. */
 static DEFINE_SPINLOCK(device_state_lock);
 
@@ -515,6 +515,31 @@ static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)
 	return ret;
 }
 
+
+/* caller has locked the hub device */
+static void hub_pre_reset(struct usb_hub *hub, int disable_ports)
+{
+	struct usb_device *hdev = hub->hdev;
+	int port1;
+
+	for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
+		if (hdev->children[port1 - 1]) {
+			usb_disconnect(&hdev->children[port1 - 1]);
+			if (disable_ports)
+				hub_port_disable(hub, port1, 0);
+		}
+	}
+	hub_quiesce(hub);
+}
+
+/* caller has locked the hub device */
+static void hub_post_reset(struct usb_hub *hub)
+{
+	hub_activate(hub);
+	hub_power_on(hub);
+}
+
+
 static int hub_configure(struct usb_hub *hub,
 	struct usb_endpoint_descriptor *endpoint)
 {
@@ -677,26 +702,40 @@ static int hub_configure(struct usb_hub *hub,
 	 * and battery-powered root hubs (may provide just 8 mA).
 	 */
 	ret = usb_get_status(hdev, USB_RECIP_DEVICE, 0, &hubstatus);
-	if (ret < 0) {
+	if (ret < 2) {
 		message = "can't get hub status";
 		goto fail;
 	}
 	le16_to_cpus(&hubstatus);
 	if (hdev == hdev->bus->root_hub) {
-		struct usb_hcd *hcd =
-				container_of(hdev->bus, struct usb_hcd, self);
-
-		hub->power_budget = min(500u, hcd->power_budget) / 2;
+		if (hdev->bus_mA == 0 || hdev->bus_mA >= 500)
+			hub->mA_per_port = 500;
+		else {
+			hub->mA_per_port = hdev->bus_mA;
+			hub->limited_power = 1;
+		}
 	} else if ((hubstatus & (1 << USB_DEVICE_SELF_POWERED)) == 0) {
 		dev_dbg(hub_dev, "hub controller current requirement: %dmA\n",
 			hub->descriptor->bHubContrCurrent);
-		hub->power_budget = (501 - hub->descriptor->bHubContrCurrent)
-					/ 2;
+		hub->limited_power = 1;
+		if (hdev->maxchild > 0) {
+			int remaining = hdev->bus_mA -
+					hub->descriptor->bHubContrCurrent;
+
+			if (remaining < hdev->maxchild * 100)
+				dev_warn(hub_dev,
+					"insufficient power available "
+					"to use all downstream ports\n");
+			hub->mA_per_port = 100;		/* 7.2.1.1 */
+		}
+	} else {	/* Self-powered external hub */
+		/* FIXME: What about battery-powered external hubs that
+		 * provide less current per port? */
+		hub->mA_per_port = 500;
 	}
-	if (hub->power_budget)
-		dev_dbg(hub_dev, "%dmA bus power budget for children\n",
-			hub->power_budget * 2);
-
+	if (hub->mA_per_port < 500)
+		dev_dbg(hub_dev, "%umA bus power budget for each child\n",
+				hub->mA_per_port);
 
 	ret = hub_hub_status(hub, &hubstatus, &hubchange);
 	if (ret < 0) {
@@ -750,29 +789,10 @@ fail:
 
 static unsigned highspeed_hubs;
 
-/* Called after the hub driver is unbound from a hub with children */
-static void hub_remove_children_work(void *__hub)
-{
-	struct usb_hub		*hub = __hub;
-	struct usb_device	*hdev = hub->hdev;
-	int			i;
-
-	kfree(hub);
-
-	usb_lock_device(hdev);
-	for (i = 0; i < hdev->maxchild; ++i) {
-		if (hdev->children[i])
-			usb_disconnect(&hdev->children[i]);
-	}
-	usb_unlock_device(hdev);
-	usb_put_dev(hdev);
-}
-
 static void hub_disconnect(struct usb_interface *intf)
 {
 	struct usb_hub *hub = usb_get_intfdata (intf);
 	struct usb_device *hdev;
-	int n, port1;
 
 	usb_set_intfdata (intf, NULL);
 	hdev = hub->hdev;
@@ -780,7 +800,9 @@ static void hub_disconnect(struct usb_interface *intf)
 	if (hdev->speed == USB_SPEED_HIGH)
 		highspeed_hubs--;
 
-	hub_quiesce(hub);
+	/* Disconnect all children and quiesce the hub */
+	hub_pre_reset(hub, 1);
+
 	usb_free_urb(hub->urb);
 	hub->urb = NULL;
 
@@ -800,27 +822,7 @@ static void hub_disconnect(struct usb_interface *intf)
 		hub->buffer = NULL;
 	}
 
-	/* If there are any children then this is an unbind only, not a
-	 * physical disconnection.  The active ports must be disabled
-	 * and later on we must call usb_disconnect().  We can't call
-	 * it now because we may not hold the hub's device lock.
-	 */
-	n = 0;
-	for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
-		if (hdev->children[port1 - 1]) {
-			++n;
-			hub_port_disable(hub, port1, 1);
-		}
-	}
-
-	if (n == 0)
-		kfree(hub);
-	else {
-		/* Reuse the hub->leds work_struct for our own purposes */
-		INIT_WORK(&hub->leds, hub_remove_children_work, hub);
-		schedule_work(&hub->leds);
-		usb_get_dev(hdev);
-	}
+	kfree(hub);
 }
 
 static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
@@ -917,26 +919,6 @@ hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data)
 	}
 }
 
-/* caller has locked the hub device */
-static void hub_pre_reset(struct usb_hub *hub)
-{
-	struct usb_device *hdev = hub->hdev;
-	int i;
-
-	for (i = 0; i < hdev->maxchild; ++i) {
-		if (hdev->children[i])
-			usb_disconnect(&hdev->children[i]);
-	}
-	hub_quiesce(hub);
-}
-
-/* caller has locked the hub device */
-static void hub_post_reset(struct usb_hub *hub)
-{
-	hub_activate(hub);
-	hub_power_on(hub);
-}
-
 
 /* grab device/port lock, returning index of that port (zero based).
  * protects the upstream link used by this device from concurrent
@@ -964,24 +946,21 @@ static int locktree(struct usb_device *udev)
 	t = locktree(hdev);
 	if (t < 0)
 		return t;
-	for (t = 0; t < hdev->maxchild; t++) {
-		if (hdev->children[t] == udev) {
-			/* everything is fail-fast once disconnect
-			 * processing starts
-			 */
-			if (udev->state == USB_STATE_NOTATTACHED)
-				break;
 
-			/* when everyone grabs locks top->bottom,
-			 * non-overlapping work may be concurrent
-			 */
-			down(&udev->serialize);
-			up(&hdev->serialize);
-			return t + 1;
-		}
+	/* everything is fail-fast once disconnect
+	 * processing starts
+	 */
+	if (udev->state == USB_STATE_NOTATTACHED) {
+		usb_unlock_device(hdev);
+		return -ENODEV;
 	}
+
+	/* when everyone grabs locks top->bottom,
+	 * non-overlapping work may be concurrent
+	 */
+	usb_lock_device(udev);
 	usb_unlock_device(hdev);
-	return -ENODEV;
+	return udev->portnum;
 }
 
 static void recursively_mark_NOTATTACHED(struct usb_device *udev)
@@ -1039,6 +1018,39 @@ void usb_set_device_state(struct usb_device *udev,
 EXPORT_SYMBOL(usb_set_device_state);
 
 
+#ifdef CONFIG_PM
+
+/**
+ * usb_root_hub_lost_power - called by HCD if the root hub lost Vbus power
+ * @rhdev: struct usb_device for the root hub
+ *
+ * The USB host controller driver calls this function when its root hub
+ * is resumed and Vbus power has been interrupted or the controller
+ * has been reset.  The routine marks all the children of the root hub
+ * as NOTATTACHED and marks logical connect-change events on their ports.
+ */
+void usb_root_hub_lost_power(struct usb_device *rhdev)
+{
+	struct usb_hub *hub;
+	int port1;
+	unsigned long flags;
+
+	dev_warn(&rhdev->dev, "root hub lost power or was reset\n");
+	spin_lock_irqsave(&device_state_lock, flags);
+	hub = hdev_to_hub(rhdev);
+	for (port1 = 1; port1 <= rhdev->maxchild; ++port1) {
+		if (rhdev->children[port1 - 1]) {
+			recursively_mark_NOTATTACHED(
+					rhdev->children[port1 - 1]);
+			set_bit(port1, hub->change_bits);
+		}
+	}
+	spin_unlock_irqrestore(&device_state_lock, flags);
+}
+EXPORT_SYMBOL_GPL(usb_root_hub_lost_power);
+
+#endif
+
 static void choose_address(struct usb_device *udev)
 {
 	int		devnum;
@@ -1099,16 +1111,10 @@ void usb_disconnect(struct usb_device **pdev)
 	 * this quiesces everyting except pending urbs.
 	 */
 	usb_set_device_state(udev, USB_STATE_NOTATTACHED);
-
-	/* lock the bus list on behalf of HCDs unregistering their root hubs */
-	if (!udev->parent) {
-		down(&usb_bus_list_lock);
-		usb_lock_device(udev);
-	} else
-		down(&udev->serialize);
-
 	dev_info (&udev->dev, "USB disconnect, address %d\n", udev->devnum);
 
+	usb_lock_device(udev);
+
 	/* Free up all the children before we remove this device */
 	for (i = 0; i < USB_MAXCHILDREN; i++) {
 		if (udev->children[i])
@@ -1136,54 +1142,112 @@ void usb_disconnect(struct usb_device **pdev)
 	*pdev = NULL;
 	spin_unlock_irq(&device_state_lock);
 
-	if (!udev->parent) {
-		usb_unlock_device(udev);
-		up(&usb_bus_list_lock);
-	} else
-		up(&udev->serialize);
+	usb_unlock_device(udev);
 
 	device_unregister(&udev->dev);
 }
 
+static inline const char *plural(int n)
+{
+	return (n == 1 ? "" : "s");
+}
+
 static int choose_configuration(struct usb_device *udev)
 {
-	int c, i;
+	int i;
+	u16 devstatus;
+	int bus_powered;
+	int num_configs;
+	struct usb_host_config *c, *best;
+
+	/* If this fails, assume the device is bus-powered */
+	devstatus = 0;
+	usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus);
+	le16_to_cpus(&devstatus);
+	bus_powered = ((devstatus & (1 << USB_DEVICE_SELF_POWERED)) == 0);
+	dev_dbg(&udev->dev, "device is %s-powered\n",
+			bus_powered ? "bus" : "self");
+
+	best = NULL;
+	c = udev->config;
+	num_configs = udev->descriptor.bNumConfigurations;
+	for (i = 0; i < num_configs; (i++, c++)) {
+		struct usb_interface_descriptor	*desc =
+				&c->intf_cache[0]->altsetting->desc;
+
+		/*
+		 * HP's USB bus-powered keyboard has only one configuration
+		 * and it claims to be self-powered; other devices may have
+		 * similar errors in their descriptors.  If the next test
+		 * were allowed to execute, such configurations would always
+		 * be rejected and the devices would not work as expected.
+		 */
+#if 0
+		/* Rule out self-powered configs for a bus-powered device */
+		if (bus_powered && (c->desc.bmAttributes &
+					USB_CONFIG_ATT_SELFPOWER))
+			continue;
+#endif
 
-	/* NOTE: this should interact with hub power budgeting */
+		/*
+		 * The next test may not be as effective as it should be.
+		 * Some hubs have errors in their descriptor, claiming
+		 * to be self-powered when they are really bus-powered.
+		 * We will overestimate the amount of current such hubs
+		 * make available for each port.
+		 *
+		 * This is a fairly benign sort of failure.  It won't
+		 * cause us to reject configurations that we should have
+		 * accepted.
+		 */
 
-	c = udev->config[0].desc.bConfigurationValue;
-	if (udev->descriptor.bNumConfigurations != 1) {
-		for (i = 0; i < udev->descriptor.bNumConfigurations; i++) {
-			struct usb_interface_descriptor	*desc;
+		/* Rule out configs that draw too much bus current */
+		if (c->desc.bMaxPower * 2 > udev->bus_mA)
+			continue;
 
-			/* heuristic:  Linux is more likely to have class
-			 * drivers, so avoid vendor-specific interfaces.
-			 */
-			desc = &udev->config[i].intf_cache[0]
-					->altsetting->desc;
-			if (desc->bInterfaceClass == USB_CLASS_VENDOR_SPEC)
-				continue;
-			/* COMM/2/all is CDC ACM, except 0xff is MSFT RNDIS.
-			 * MSFT needs this to be the first config; never use
-			 * it as the default unless Linux has host-side RNDIS.
-			 * A second config would ideally be CDC-Ethernet, but
-			 * may instead be the "vendor specific" CDC subset
-			 * long used by ARM Linux for sa1100 or pxa255.
-			 */
-			if (desc->bInterfaceClass == USB_CLASS_COMM
-					&& desc->bInterfaceSubClass == 2
-					&& desc->bInterfaceProtocol == 0xff) {
-				c = udev->config[1].desc.bConfigurationValue;
-				continue;
-			}
-			c = udev->config[i].desc.bConfigurationValue;
+		/* If the first config's first interface is COMM/2/0xff
+		 * (MSFT RNDIS), rule it out unless Linux has host-side
+		 * RNDIS support. */
+		if (i == 0 && desc->bInterfaceClass == USB_CLASS_COMM
+				&& desc->bInterfaceSubClass == 2
+				&& desc->bInterfaceProtocol == 0xff) {
+#ifndef CONFIG_USB_NET_RNDIS
+			continue;
+#else
+			best = c;
+#endif
+		}
+
+		/* From the remaining configs, choose the first one whose
+		 * first interface is for a non-vendor-specific class.
+		 * Reason: Linux is more likely to have a class driver
+		 * than a vendor-specific driver. */
+		else if (udev->descriptor.bDeviceClass !=
+						USB_CLASS_VENDOR_SPEC &&
+				desc->bInterfaceClass !=
+						USB_CLASS_VENDOR_SPEC) {
+			best = c;
 			break;
 		}
+
+		/* If all the remaining configs are vendor-specific,
+		 * choose the first one. */
+		else if (!best)
+			best = c;
+	}
+
+	if (best) {
+		i = best->desc.bConfigurationValue;
 		dev_info(&udev->dev,
-			"configuration #%d chosen from %d choices\n",
-			c, udev->descriptor.bNumConfigurations);
+			"configuration #%d chosen from %d choice%s\n",
+			i, num_configs, plural(num_configs));
+	} else {
+		i = -1;
+		dev_warn(&udev->dev,
+			"no configuration chosen from %d choice%s\n",
+			num_configs, plural(num_configs));
 	}
-	return c;
+	return i;
 }
 
 #ifdef DEBUG
@@ -1210,8 +1274,8 @@ static inline void show_string(struct usb_device *udev, char *id, char *string)
  *
  * This is called with devices which have been enumerated, but not yet
  * configured.  The device descriptor is available, but not descriptors
- * for any device configuration.  The caller must have locked udev and
- * either the parent hub (if udev is a normal device) or else the
+ * for any device configuration.  The caller must have locked either
+ * the parent hub (if udev is a normal device) or else the
  * usb_bus_list_lock (if udev is a root hub).  The parent's pointer to
  * udev has already been installed, but udev is not yet visible through
  * sysfs or other filesystem code.
@@ -1221,8 +1285,7 @@ static inline void show_string(struct usb_device *udev, char *id, char *string)
  *
  * This call is synchronous, and may not be used in an interrupt context.
  *
- * Only the hub driver should ever call this; root hub registration
- * uses it indirectly.
+ * Only the hub driver or root-hub registrar should ever call this.
  */
 int usb_new_device(struct usb_device *udev)
 {
@@ -1269,15 +1332,9 @@ int usb_new_device(struct usb_device *udev)
 					le16_to_cpu(udev->config[0].desc.wTotalLength),
 					USB_DT_OTG, (void **) &desc) == 0) {
 			if (desc->bmAttributes & USB_OTG_HNP) {
-				unsigned		port1;
+				unsigned		port1 = udev->portnum;
 				struct usb_device	*root = udev->parent;
 				
-				for (port1 = 1; port1 <= root->maxchild;
-						port1++) {
-					if (root->children[port1-1] == udev)
-						break;
-				}
-
 				dev_info(&udev->dev,
 					"Dual-Role OTG device on %sHNP port\n",
 					(port1 == bus->otg_port)
@@ -1331,27 +1388,27 @@ int usb_new_device(struct usb_device *udev)
 	}
 	usb_create_sysfs_dev_files (udev);
 
+	usb_lock_device(udev);
+
 	/* choose and set the configuration. that registers the interfaces
 	 * with the driver core, and lets usb device drivers bind to them.
 	 */
 	c = choose_configuration(udev);
-	if (c < 0)
-		dev_warn(&udev->dev,
-				"can't choose an initial configuration\n");
-	else {
+	if (c >= 0) {
 		err = usb_set_configuration(udev, c);
 		if (err) {
 			dev_err(&udev->dev, "can't set config #%d, error %d\n",
 					c, err);
-			usb_remove_sysfs_dev_files(udev);
-			device_del(&udev->dev);
-			goto fail;
+			/* This need not be fatal.  The user can try to
+			 * set other configurations. */
 		}
 	}
 
 	/* USB device state == configured ... usable */
 	usb_notify_add_device(udev);
 
+	usb_unlock_device(udev);
+
 	return 0;
 
 fail:
@@ -1654,15 +1711,9 @@ static int __usb_suspend_device (struct usb_device *udev, int port1)
 int usb_suspend_device(struct usb_device *udev)
 {
 #ifdef	CONFIG_USB_SUSPEND
-	int	port1, status;
-
-	port1 = locktree(udev);
-	if (port1 < 0)
-		return port1;
-
-	status = __usb_suspend_device(udev, port1);
-	usb_unlock_device(udev);
-	return status;
+	if (udev->state == USB_STATE_NOTATTACHED)
+		return -ENODEV;
+	return __usb_suspend_device(udev, udev->portnum);
 #else
 	/* NOTE:  udev->state unchanged, it's not lying ... */
 	udev->dev.power.power_state = PMSG_SUSPEND;
@@ -1694,13 +1745,14 @@ static int finish_device_resume(struct usb_device *udev)
 	usb_set_device_state(udev, udev->actconfig
 			? USB_STATE_CONFIGURED
 			: USB_STATE_ADDRESS);
+	udev->dev.power.power_state = PMSG_ON;
 
  	/* 10.5.4.5 says be sure devices in the tree are still there.
  	 * For now let's assume the device didn't go crazy on resume,
 	 * and device drivers will know about any resume quirks.
 	 */
 	status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus);
-	if (status < 0)
+	if (status < 2)
 		dev_dbg(&udev->dev,
 			"gone after usb resume? status %d\n",
 			status);
@@ -1709,7 +1761,7 @@ static int finish_device_resume(struct usb_device *udev)
 		int		(*resume)(struct device *);
 
 		le16_to_cpus(&devstatus);
-		if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)
+		if ((devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP))
 				&& udev->parent) {
 			status = usb_control_msg(udev,
 					usb_sndctrlpipe(udev, 0),
@@ -1729,8 +1781,14 @@ static int finish_device_resume(struct usb_device *udev)
 		 * may have a child resume event to deal with soon
 		 */
 		resume = udev->dev.bus->resume;
-		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++)
-			(void) resume(&udev->actconfig->interface[i]->dev);
+		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
+			struct device *dev =
+					&udev->actconfig->interface[i]->dev;
+
+			down(&dev->sem);
+			(void) resume(dev);
+			up(&dev->sem);
+		}
 		status = 0;
 
 	} else if (udev->devnum <= 0) {
@@ -1813,11 +1871,10 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
  */
 int usb_resume_device(struct usb_device *udev)
 {
-	int	port1, status;
+	int	status;
 
-	port1 = locktree(udev);
-	if (port1 < 0)
-		return port1;
+	if (udev->state == USB_STATE_NOTATTACHED)
+		return -ENODEV;
 
 #ifdef	CONFIG_USB_SUSPEND
 	/* selective resume of one downstream hub-to-device port */
@@ -1826,7 +1883,7 @@ int usb_resume_device(struct usb_device *udev)
 			// NOTE swsusp may bork us, device state being wrong...
 			// NOTE this fails if parent is also suspended...
 			status = hub_port_resume(hdev_to_hub(udev->parent),
-					port1, udev);
+					udev->portnum, udev);
 		} else
 			status = 0;
 	} else
@@ -1836,13 +1893,11 @@ int usb_resume_device(struct usb_device *udev)
 		dev_dbg(&udev->dev, "can't resume, status %d\n",
 			status);
 
-	usb_unlock_device(udev);
-
 	/* rebind drivers that had no suspend() */
 	if (status == 0) {
-		usb_lock_all_devices();
+		usb_unlock_device(udev);
 		bus_rescan_devices(&usb_bus_type);
-		usb_unlock_all_devices();
+		usb_lock_device(udev);
 	}
 	return status;
 }
@@ -1856,14 +1911,14 @@ static int remote_wakeup(struct usb_device *udev)
 	/* don't repeat RESUME sequence if this device
 	 * was already woken up by some other task
 	 */
-	down(&udev->serialize);
+	usb_lock_device(udev);
 	if (udev->state == USB_STATE_SUSPENDED) {
 		dev_dbg(&udev->dev, "RESUME (wakeup)\n");
 		/* TRSMRCY = 10 msec */
 		msleep(10);
 		status = finish_device_resume(udev);
 	}
-	up(&udev->serialize);
+	usb_unlock_device(udev);
 #endif
 	return status;
 }
@@ -1964,7 +2019,7 @@ static int hub_resume(struct usb_interface *intf)
 
 		if (!udev || status < 0)
 			continue;
-		down (&udev->serialize);
+		usb_lock_device(udev);
 		if (portstat & USB_PORT_STAT_SUSPEND)
 			status = hub_port_resume(hub, port1, udev);
 		else {
@@ -1975,7 +2030,7 @@ static int hub_resume(struct usb_interface *intf)
 				hub_port_logical_disconnect(hub, port1);
 			}
 		}
-		up(&udev->serialize);
+		usb_unlock_device(udev);
 	}
 	}
 #endif
@@ -2359,39 +2414,36 @@ hub_power_remaining (struct usb_hub *hub)
 {
 	struct usb_device *hdev = hub->hdev;
 	int remaining;
-	unsigned i;
+	int port1;
 
-	remaining = hub->power_budget;
-	if (!remaining)		/* self-powered */
+	if (!hub->limited_power)
 		return 0;
 
-	for (i = 0; i < hdev->maxchild; i++) {
-		struct usb_device	*udev = hdev->children[i];
-		int			delta, ceiling;
+	remaining = hdev->bus_mA - hub->descriptor->bHubContrCurrent;
+	for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
+		struct usb_device	*udev = hdev->children[port1 - 1];
+		int			delta;
 
 		if (!udev)
 			continue;
 
-		/* 100mA per-port ceiling, or 8mA for OTG ports */
-		if (i != (udev->bus->otg_port - 1) || hdev->parent)
-			ceiling = 50;
-		else
-			ceiling = 4;
-
+		/* Unconfigured devices may not use more than 100mA,
+		 * or 8mA for OTG ports */
 		if (udev->actconfig)
-			delta = udev->actconfig->desc.bMaxPower;
+			delta = udev->actconfig->desc.bMaxPower * 2;
+		else if (port1 != udev->bus->otg_port || hdev->parent)
+			delta = 100;
 		else
-			delta = ceiling;
-		// dev_dbg(&udev->dev, "budgeted %dmA\n", 2 * delta);
-		if (delta > ceiling)
-			dev_warn(&udev->dev, "%dmA over %dmA budget!\n",
-				2 * (delta - ceiling), 2 * ceiling);
+			delta = 8;
+		if (delta > hub->mA_per_port)
+			dev_warn(&udev->dev, "%dmA is over %umA budget "
+					"for port %d!\n",
+					delta, hub->mA_per_port, port1);
 		remaining -= delta;
 	}
 	if (remaining < 0) {
-		dev_warn(hub->intfdev,
-			"%dmA over power budget!\n",
-			-2 * remaining);
+		dev_warn(hub->intfdev, "%dmA over power budget!\n",
+			- remaining);
 		remaining = 0;
 	}
 	return remaining;
@@ -2486,7 +2538,8 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
 
 		usb_set_device_state(udev, USB_STATE_POWERED);
 		udev->speed = USB_SPEED_UNKNOWN;
- 
+ 		udev->bus_mA = hub->mA_per_port;
+
 		/* set the address */
 		choose_address(udev);
 		if (udev->devnum <= 0) {
@@ -2506,16 +2559,16 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
 		 * on the parent.
 		 */
 		if (udev->descriptor.bDeviceClass == USB_CLASS_HUB
-				&& hub->power_budget) {
+				&& udev->bus_mA <= 100) {
 			u16	devstat;
 
 			status = usb_get_status(udev, USB_RECIP_DEVICE, 0,
 					&devstat);
-			if (status < 0) {
+			if (status < 2) {
 				dev_dbg(&udev->dev, "get status %d ?\n", status);
 				goto loop_disable;
 			}
-			cpu_to_le16s(&devstat);
+			le16_to_cpus(&devstat);
 			if ((devstat & (1 << USB_DEVICE_SELF_POWERED)) == 0) {
 				dev_err(&udev->dev,
 					"can't connect bus-powered hub "
@@ -2540,7 +2593,6 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
 		 * udev becomes globally accessible, although presumably
 		 * no one will look at it until hdev is unlocked.
 		 */
-		down (&udev->serialize);
 		status = 0;
 
 		/* We mustn't add new devices if the parent hub has
@@ -2564,15 +2616,12 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
 			}
 		}
 
-		up (&udev->serialize);
 		if (status)
 			goto loop_disable;
 
 		status = hub_power_remaining(hub);
 		if (status)
-			dev_dbg(hub_dev,
-				"%dmA power budget left\n",
-				2 * status);
+			dev_dbg(hub_dev, "%dmA power budget left\n", status);
 
 		return;
 
@@ -2648,6 +2697,8 @@ static void hub_events(void)
 		if (i) {
 			dpm_runtime_resume(&hdev->dev);
 			dpm_runtime_resume(&intf->dev);
+			usb_put_intf(intf);
+			continue;
 		}
 
 		/* Lock the device, then check to see if we were
@@ -2661,7 +2712,7 @@ static void hub_events(void)
 
 		/* If the hub has died, clean up after it */
 		if (hdev->state == USB_STATE_NOTATTACHED) {
-			hub_pre_reset(hub);
+			hub_pre_reset(hub, 0);
 			goto loop;
 		}
 
@@ -2784,6 +2835,11 @@ static void hub_events(void)
 			if (hubchange & HUB_CHANGE_LOCAL_POWER) {
 				dev_dbg (hub_dev, "power change\n");
 				clear_hub_feature(hdev, C_HUB_LOCAL_POWER);
+				if (hubstatus & HUB_STATUS_LOCAL_POWER)
+					/* FIXME: Is this always true? */
+					hub->limited_power = 0;
+				else
+					hub->limited_power = 1;
 			}
 			if (hubchange & HUB_CHANGE_OVERCURRENT) {
 				dev_dbg (hub_dev, "overcurrent change\n");
@@ -2832,7 +2888,6 @@ static struct usb_device_id hub_id_table [] = {
 MODULE_DEVICE_TABLE (usb, hub_id_table);
 
 static struct usb_driver hub_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"hub",
 	.probe =	hub_probe,
 	.disconnect =	hub_disconnect,
@@ -2944,7 +2999,8 @@ int usb_reset_device(struct usb_device *udev)
 	struct usb_hub			*parent_hub;
 	struct usb_device_descriptor	descriptor = udev->descriptor;
 	struct usb_hub			*hub = NULL;
-	int 				i, ret = 0, port1 = -1;
+	int 				i, ret = 0;
+	int				port1 = udev->portnum;
 
 	if (udev->state == USB_STATE_NOTATTACHED ||
 			udev->state == USB_STATE_SUSPENDED) {
@@ -2958,18 +3014,6 @@ int usb_reset_device(struct usb_device *udev)
 		dev_dbg(&udev->dev, "%s for root hub!\n", __FUNCTION__);
 		return -EISDIR;
 	}
-
-	for (i = 0; i < parent_hdev->maxchild; i++)
-		if (parent_hdev->children[i] == udev) {
-			port1 = i + 1;
-			break;
-		}
-
-	if (port1 < 0) {
-		/* If this ever happens, it's very bad */
-		dev_err(&udev->dev, "Can't locate device's port!\n");
-		return -ENOENT;
-	}
 	parent_hub = hdev_to_hub(parent_hdev);
 
 	/* If we're resetting an active hub, take some special actions */
@@ -2977,7 +3021,7 @@ int usb_reset_device(struct usb_device *udev)
 			udev->actconfig->interface[0]->dev.driver ==
 				&hub_driver.driver &&
 			(hub = hdev_to_hub(udev)) != NULL) {
-		hub_pre_reset(hub);
+		hub_pre_reset(hub, 0);
 	}
 
 	set_bit(port1, parent_hub->busy_bits);
diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
index bf23f8978024..29d5f45a8456 100644
--- a/drivers/usb/core/hub.h
+++ b/drivers/usb/core/hub.h
@@ -220,8 +220,9 @@ struct usb_hub {
 	struct usb_hub_descriptor *descriptor;	/* class descriptor */
 	struct usb_tt		tt;		/* Transaction Translator */
 
-	u8			power_budget;	/* in 2mA units; or zero */
+	unsigned		mA_per_port;	/* current for each child */
 
+	unsigned		limited_power:1;
 	unsigned		quiescing:1;
 	unsigned		activating:1;
 	unsigned		resume_root_hub:1;
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index fe74f99ca5f4..319de03944e7 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1387,6 +1387,12 @@ free_interfaces:
 	if (dev->state != USB_STATE_ADDRESS)
 		usb_disable_device (dev, 1);	// Skip ep0
 
+	i = dev->bus_mA - cp->desc.bMaxPower * 2;
+	if (i < 0)
+		dev_warn(&dev->dev, "new config #%d exceeds power "
+				"limit by %dmA\n",
+				configuration, -i);
+
 	if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
 			USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
 			NULL, 0, USB_CTRL_SET_TIMEOUT)) < 0)
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index e80ef9467825..13d1d367f7f1 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -32,7 +32,6 @@
 #include <linux/spinlock.h>
 #include <linux/errno.h>
 #include <linux/smp_lock.h>
-#include <linux/rwsem.h>
 #include <linux/usb.h>
 
 #include <asm/io.h>
@@ -47,165 +46,7 @@
 const char *usbcore_name = "usbcore";
 
 static int nousb;	/* Disable USB when built into kernel image */
-			/* Not honored on modular build */
 
-static DECLARE_RWSEM(usb_all_devices_rwsem);
-
-
-static int generic_probe (struct device *dev)
-{
-	return 0;
-}
-static int generic_remove (struct device *dev)
-{
-	struct usb_device *udev = to_usb_device(dev);
-
-	/* if this is only an unbind, not a physical disconnect, then
-	 * unconfigure the device */
-	if (udev->state == USB_STATE_CONFIGURED)
-		usb_set_configuration(udev, 0);
-
-	/* in case the call failed or the device was suspended */
-	if (udev->state >= USB_STATE_CONFIGURED)
-		usb_disable_device(udev, 0);
-	return 0;
-}
-
-static struct device_driver usb_generic_driver = {
-	.owner = THIS_MODULE,
-	.name =	"usb",
-	.bus = &usb_bus_type,
-	.probe = generic_probe,
-	.remove = generic_remove,
-};
-
-static int usb_generic_driver_data;
-
-/* called from driver core with usb_bus_type.subsys writelock */
-static int usb_probe_interface(struct device *dev)
-{
-	struct usb_interface * intf = to_usb_interface(dev);
-	struct usb_driver * driver = to_usb_driver(dev->driver);
-	const struct usb_device_id *id;
-	int error = -ENODEV;
-
-	dev_dbg(dev, "%s\n", __FUNCTION__);
-
-	if (!driver->probe)
-		return error;
-	/* FIXME we'd much prefer to just resume it ... */
-	if (interface_to_usbdev(intf)->state == USB_STATE_SUSPENDED)
-		return -EHOSTUNREACH;
-
-	id = usb_match_id (intf, driver->id_table);
-	if (id) {
-		dev_dbg (dev, "%s - got id\n", __FUNCTION__);
-
-		/* Interface "power state" doesn't correspond to any hardware
-		 * state whatsoever.  We use it to record when it's bound to
-		 * a driver that may start I/0:  it's not frozen/quiesced.
-		 */
-		mark_active(intf);
-		intf->condition = USB_INTERFACE_BINDING;
-		error = driver->probe (intf, id);
-		if (error) {
-			mark_quiesced(intf);
-			intf->condition = USB_INTERFACE_UNBOUND;
-		} else
-			intf->condition = USB_INTERFACE_BOUND;
-	}
-
-	return error;
-}
-
-/* called from driver core with usb_bus_type.subsys writelock */
-static int usb_unbind_interface(struct device *dev)
-{
-	struct usb_interface *intf = to_usb_interface(dev);
-	struct usb_driver *driver = to_usb_driver(intf->dev.driver);
-
-	intf->condition = USB_INTERFACE_UNBINDING;
-
-	/* release all urbs for this interface */
-	usb_disable_interface(interface_to_usbdev(intf), intf);
-
-	if (driver && driver->disconnect)
-		driver->disconnect(intf);
-
-	/* reset other interface state */
-	usb_set_interface(interface_to_usbdev(intf),
-			intf->altsetting[0].desc.bInterfaceNumber,
-			0);
-	usb_set_intfdata(intf, NULL);
-	intf->condition = USB_INTERFACE_UNBOUND;
-	mark_quiesced(intf);
-
-	return 0;
-}
-
-/**
- * usb_register - register a USB driver
- * @new_driver: USB operations for the driver
- *
- * Registers a USB driver with the USB core.  The list of unattached
- * interfaces will be rescanned whenever a new driver is added, allowing
- * the new driver to attach to any recognized devices.
- * Returns a negative error code on failure and 0 on success.
- * 
- * NOTE: if you want your driver to use the USB major number, you must call
- * usb_register_dev() to enable that functionality.  This function no longer
- * takes care of that.
- */
-int usb_register(struct usb_driver *new_driver)
-{
-	int retval = 0;
-
-	if (nousb)
-		return -ENODEV;
-
-	new_driver->driver.name = (char *)new_driver->name;
-	new_driver->driver.bus = &usb_bus_type;
-	new_driver->driver.probe = usb_probe_interface;
-	new_driver->driver.remove = usb_unbind_interface;
-	new_driver->driver.owner = new_driver->owner;
-
-	usb_lock_all_devices();
-	retval = driver_register(&new_driver->driver);
-	usb_unlock_all_devices();
-
-	if (!retval) {
-		pr_info("%s: registered new driver %s\n",
-			usbcore_name, new_driver->name);
-		usbfs_update_special();
-	} else {
-		printk(KERN_ERR "%s: error %d registering driver %s\n",
-			usbcore_name, retval, new_driver->name);
-	}
-
-	return retval;
-}
-
-/**
- * usb_deregister - unregister a USB driver
- * @driver: USB operations of the driver to unregister
- * Context: must be able to sleep
- *
- * Unlinks the specified driver from the internal USB driver list.
- * 
- * NOTE: If you called usb_register_dev(), you still need to call
- * usb_deregister_dev() to clean up your driver's allocated minor numbers,
- * this * call will no longer do it for you.
- */
-void usb_deregister(struct usb_driver *driver)
-{
-	pr_info("%s: deregistering driver %s\n", usbcore_name, driver->name);
-
-	usb_lock_all_devices();
-	driver_unregister (&driver->driver);
-	usb_unlock_all_devices();
-
-	usbfs_update_special();
-}
 
 /**
  * usb_ifnum_to_if - get the interface object with a given interface number
@@ -352,151 +193,23 @@ void usb_driver_release_interface(struct usb_driver *driver,
 	mark_quiesced(iface);
 }
 
-/**
- * usb_match_id - find first usb_device_id matching device or interface
- * @interface: the interface of interest
- * @id: array of usb_device_id structures, terminated by zero entry
- *
- * usb_match_id searches an array of usb_device_id's and returns
- * the first one matching the device or interface, or null.
- * This is used when binding (or rebinding) a driver to an interface.
- * Most USB device drivers will use this indirectly, through the usb core,
- * but some layered driver frameworks use it directly.
- * These device tables are exported with MODULE_DEVICE_TABLE, through
- * modutils and "modules.usbmap", to support the driver loading
- * functionality of USB hotplugging.
- *
- * What Matches:
- *
- * The "match_flags" element in a usb_device_id controls which
- * members are used.  If the corresponding bit is set, the
- * value in the device_id must match its corresponding member
- * in the device or interface descriptor, or else the device_id
- * does not match.
- *
- * "driver_info" is normally used only by device drivers,
- * but you can create a wildcard "matches anything" usb_device_id
- * as a driver's "modules.usbmap" entry if you provide an id with
- * only a nonzero "driver_info" field.  If you do this, the USB device
- * driver's probe() routine should use additional intelligence to
- * decide whether to bind to the specified interface.
- * 
- * What Makes Good usb_device_id Tables:
- *
- * The match algorithm is very simple, so that intelligence in
- * driver selection must come from smart driver id records.
- * Unless you have good reasons to use another selection policy,
- * provide match elements only in related groups, and order match
- * specifiers from specific to general.  Use the macros provided
- * for that purpose if you can.
- *
- * The most specific match specifiers use device descriptor
- * data.  These are commonly used with product-specific matches;
- * the USB_DEVICE macro lets you provide vendor and product IDs,
- * and you can also match against ranges of product revisions.
- * These are widely used for devices with application or vendor
- * specific bDeviceClass values.
- *
- * Matches based on device class/subclass/protocol specifications
- * are slightly more general; use the USB_DEVICE_INFO macro, or
- * its siblings.  These are used with single-function devices
- * where bDeviceClass doesn't specify that each interface has
- * its own class. 
- *
- * Matches based on interface class/subclass/protocol are the
- * most general; they let drivers bind to any interface on a
- * multiple-function device.  Use the USB_INTERFACE_INFO
- * macro, or its siblings, to match class-per-interface style 
- * devices (as recorded in bDeviceClass).
- *  
- * Within those groups, remember that not all combinations are
- * meaningful.  For example, don't give a product version range
- * without vendor and product IDs; or specify a protocol without
- * its associated class and subclass.
- */   
-const struct usb_device_id *
-usb_match_id(struct usb_interface *interface, const struct usb_device_id *id)
-{
-	struct usb_host_interface *intf;
-	struct usb_device *dev;
-
-	/* proc_connectinfo in devio.c may call us with id == NULL. */
-	if (id == NULL)
-		return NULL;
-
-	intf = interface->cur_altsetting;
-	dev = interface_to_usbdev(interface);
-
-	/* It is important to check that id->driver_info is nonzero,
-	   since an entry that is all zeroes except for a nonzero
-	   id->driver_info is the way to create an entry that
-	   indicates that the driver want to examine every
-	   device and interface. */
-	for (; id->idVendor || id->bDeviceClass || id->bInterfaceClass ||
-	       id->driver_info; id++) {
-
-		if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
-		    id->idVendor != le16_to_cpu(dev->descriptor.idVendor))
-			continue;
-
-		if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&
-		    id->idProduct != le16_to_cpu(dev->descriptor.idProduct))
-			continue;
-
-		/* No need to test id->bcdDevice_lo != 0, since 0 is never
-		   greater than any unsigned number. */
-		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) &&
-		    (id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice)))
-			continue;
-
-		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) &&
-		    (id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice)))
-			continue;
-
-		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&
-		    (id->bDeviceClass != dev->descriptor.bDeviceClass))
-			continue;
-
-		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
-		    (id->bDeviceSubClass!= dev->descriptor.bDeviceSubClass))
-			continue;
-
-		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&
-		    (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
-			continue;
-
-		if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) &&
-		    (id->bInterfaceClass != intf->desc.bInterfaceClass))
-			continue;
-
-		if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS) &&
-		    (id->bInterfaceSubClass != intf->desc.bInterfaceSubClass))
-			continue;
-
-		if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL) &&
-		    (id->bInterfaceProtocol != intf->desc.bInterfaceProtocol))
-			continue;
-
-		return id;
-	}
-
-	return NULL;
-}
-
+struct find_interface_arg {
+	int minor;
+	struct usb_interface *interface;
+};
 
 static int __find_interface(struct device * dev, void * data)
 {
-	struct usb_interface ** ret = (struct usb_interface **)data;
-	struct usb_interface * intf = *ret;
-	int *minor = (int *)data;
+	struct find_interface_arg *arg = data;
+	struct usb_interface *intf;
 
 	/* can't look at usb devices, only interfaces */
 	if (dev->driver == &usb_generic_driver)
 		return 0;
 
 	intf = to_usb_interface(dev);
-	if (intf->minor != -1 && intf->minor == *minor) {
-		*ret = intf;
+	if (intf->minor != -1 && intf->minor == arg->minor) {
+		arg->interface = intf;
 		return 1;
 	}
 	return 0;
@@ -513,42 +226,18 @@ static int __find_interface(struct device * dev, void * data)
  */
 struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor)
 {
-	struct usb_interface *intf = (struct usb_interface *)(long)minor;
-	int ret;
-
-	ret = driver_for_each_device(&drv->driver, NULL, &intf, __find_interface);
-
-	return ret ? intf : NULL;
-}
-
-static int usb_device_match (struct device *dev, struct device_driver *drv)
-{
-	struct usb_interface *intf;
-	struct usb_driver *usb_drv;
-	const struct usb_device_id *id;
-
-	/* check for generic driver, which we don't match any device with */
-	if (drv == &usb_generic_driver)
-		return 0;
-
-	intf = to_usb_interface(dev);
-	usb_drv = to_usb_driver(drv);
-	
-	id = usb_match_id (intf, usb_drv->id_table);
-	if (id)
-		return 1;
+	struct find_interface_arg argb;
 
-	return 0;
+	argb.minor = minor;
+	argb.interface = NULL;
+	driver_for_each_device(&drv->driver, NULL, &argb, __find_interface);
+	return argb.interface;
 }
 
-
 #ifdef	CONFIG_HOTPLUG
 
 /*
- * USB hotplugging invokes what /proc/sys/kernel/hotplug says
- * (normally /sbin/hotplug) when USB devices get added or removed.
- *
- * This invokes a user mode policy agent, typically helping to load driver
+ * This sends an uevent to userspace, typically helping to load driver
  * or other modules, configure the device, and more.  Drivers can provide
  * a MODULE_DEVICE_TABLE to help with module loading subtasks.
  *
@@ -557,8 +246,8 @@ static int usb_device_match (struct device *dev, struct device_driver *drv)
  * delays in event delivery.  Use sysfs (and DEVPATH) to make sure the
  * device (and this configuration!) are still present.
  */
-static int usb_hotplug (struct device *dev, char **envp, int num_envp,
-			char *buffer, int buffer_size)
+static int usb_uevent(struct device *dev, char **envp, int num_envp,
+		      char *buffer, int buffer_size)
 {
 	struct usb_interface *intf;
 	struct usb_device *usb_dev;
@@ -570,7 +259,7 @@ static int usb_hotplug (struct device *dev, char **envp, int num_envp,
 		return -ENODEV;
 
 	/* driver is often null here; dev_dbg() would oops */
-	pr_debug ("usb %s: hotplug\n", dev->bus_id);
+	pr_debug ("usb %s: uevent\n", dev->bus_id);
 
 	/* Must check driver_data here, as on remove driver is always NULL */
 	if ((dev->driver == &usb_generic_driver) || 
@@ -597,51 +286,51 @@ static int usb_hotplug (struct device *dev, char **envp, int num_envp,
 	 *
 	 * FIXME reduce hardwired intelligence here
 	 */
-	if (add_hotplug_env_var(envp, num_envp, &i,
-				buffer, buffer_size, &length,
-				"DEVICE=/proc/bus/usb/%03d/%03d",
-				usb_dev->bus->busnum, usb_dev->devnum))
+	if (add_uevent_var(envp, num_envp, &i,
+			   buffer, buffer_size, &length,
+			   "DEVICE=/proc/bus/usb/%03d/%03d",
+			   usb_dev->bus->busnum, usb_dev->devnum))
 		return -ENOMEM;
 #endif
 
 	/* per-device configurations are common */
-	if (add_hotplug_env_var(envp, num_envp, &i,
-				buffer, buffer_size, &length,
-				"PRODUCT=%x/%x/%x",
-				le16_to_cpu(usb_dev->descriptor.idVendor),
-				le16_to_cpu(usb_dev->descriptor.idProduct),
-				le16_to_cpu(usb_dev->descriptor.bcdDevice)))
+	if (add_uevent_var(envp, num_envp, &i,
+			   buffer, buffer_size, &length,
+			   "PRODUCT=%x/%x/%x",
+			   le16_to_cpu(usb_dev->descriptor.idVendor),
+			   le16_to_cpu(usb_dev->descriptor.idProduct),
+			   le16_to_cpu(usb_dev->descriptor.bcdDevice)))
 		return -ENOMEM;
 
 	/* class-based driver binding models */
-	if (add_hotplug_env_var(envp, num_envp, &i,
-				buffer, buffer_size, &length,
-				"TYPE=%d/%d/%d",
-				usb_dev->descriptor.bDeviceClass,
-				usb_dev->descriptor.bDeviceSubClass,
-				usb_dev->descriptor.bDeviceProtocol))
+	if (add_uevent_var(envp, num_envp, &i,
+			   buffer, buffer_size, &length,
+			   "TYPE=%d/%d/%d",
+			   usb_dev->descriptor.bDeviceClass,
+			   usb_dev->descriptor.bDeviceSubClass,
+			   usb_dev->descriptor.bDeviceProtocol))
 		return -ENOMEM;
 
-	if (add_hotplug_env_var(envp, num_envp, &i,
-				buffer, buffer_size, &length,
-				"INTERFACE=%d/%d/%d",
-				alt->desc.bInterfaceClass,
-				alt->desc.bInterfaceSubClass,
-				alt->desc.bInterfaceProtocol))
+	if (add_uevent_var(envp, num_envp, &i,
+			   buffer, buffer_size, &length,
+			   "INTERFACE=%d/%d/%d",
+			   alt->desc.bInterfaceClass,
+			   alt->desc.bInterfaceSubClass,
+			   alt->desc.bInterfaceProtocol))
 		return -ENOMEM;
 
-	if (add_hotplug_env_var(envp, num_envp, &i,
-				buffer, buffer_size, &length,
-				"MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
-				le16_to_cpu(usb_dev->descriptor.idVendor),
-				le16_to_cpu(usb_dev->descriptor.idProduct),
-				le16_to_cpu(usb_dev->descriptor.bcdDevice),
-				usb_dev->descriptor.bDeviceClass,
-				usb_dev->descriptor.bDeviceSubClass,
-				usb_dev->descriptor.bDeviceProtocol,
-				alt->desc.bInterfaceClass,
-				alt->desc.bInterfaceSubClass,
-				alt->desc.bInterfaceProtocol))
+	if (add_uevent_var(envp, num_envp, &i,
+			   buffer, buffer_size, &length,
+			   "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
+			   le16_to_cpu(usb_dev->descriptor.idVendor),
+			   le16_to_cpu(usb_dev->descriptor.idProduct),
+			   le16_to_cpu(usb_dev->descriptor.bcdDevice),
+			   usb_dev->descriptor.bDeviceClass,
+			   usb_dev->descriptor.bDeviceSubClass,
+			   usb_dev->descriptor.bDeviceProtocol,
+			   alt->desc.bInterfaceClass,
+			   alt->desc.bInterfaceSubClass,
+			   alt->desc.bInterfaceProtocol))
 		return -ENOMEM;
 
 	envp[i] = NULL;
@@ -651,7 +340,7 @@ static int usb_hotplug (struct device *dev, char **envp, int num_envp,
 
 #else
 
-static int usb_hotplug (struct device *dev, char **envp,
+static int usb_uevent(struct device *dev, char **envp,
 			int num_envp, char *buffer, int buffer_size)
 {
 	return -ENODEV;
@@ -750,12 +439,11 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
 		/* hub driver sets up TT records */
 	}
 
+	dev->portnum = port1;
 	dev->bus = bus;
 	dev->parent = parent;
 	INIT_LIST_HEAD(&dev->filelist);
 
-	init_MUTEX(&dev->serialize);
-
 	return dev;
 }
 
@@ -828,76 +516,21 @@ void usb_put_intf(struct usb_interface *intf)
 
 /*			USB device locking
  *
- * Although locking USB devices should be straightforward, it is
- * complicated by the way the driver-model core works.  When a new USB
- * driver is registered or unregistered, the core will automatically
- * probe or disconnect all matching interfaces on all USB devices while
- * holding the USB subsystem writelock.  There's no good way for us to
- * tell which devices will be used or to lock them beforehand; our only
- * option is to effectively lock all the USB devices.
- *
- * We do that by using a private rw-semaphore, usb_all_devices_rwsem.
- * When locking an individual device you must first acquire the rwsem's
- * readlock.  When a driver is registered or unregistered the writelock
- * must be held.  These actions are encapsulated in the subroutines
- * below, so all a driver needs to do is call usb_lock_device() and
- * usb_unlock_device().
+ * USB devices and interfaces are locked using the semaphore in their
+ * embedded struct device.  The hub driver guarantees that whenever a
+ * device is connected or disconnected, drivers are called with the
+ * USB device locked as well as their particular interface.
  *
  * Complications arise when several devices are to be locked at the same
  * time.  Only hub-aware drivers that are part of usbcore ever have to
- * do this; nobody else needs to worry about it.  The problem is that
- * usb_lock_device() must not be called to lock a second device since it
- * would acquire the rwsem's readlock reentrantly, leading to deadlock if
- * another thread was waiting for the writelock.  The solution is simple:
- *
- *	When locking more than one device, call usb_lock_device()
- *	to lock the first one.  Lock the others by calling
- *	down(&udev->serialize) directly.
- *
- *	When unlocking multiple devices, use up(&udev->serialize)
- *	to unlock all but the last one.  Unlock the last one by
- *	calling usb_unlock_device().
+ * do this; nobody else needs to worry about it.  The rule for locking
+ * is simple:
  *
  *	When locking both a device and its parent, always lock the
  *	the parent first.
  */
 
 /**
- * usb_lock_device - acquire the lock for a usb device structure
- * @udev: device that's being locked
- *
- * Use this routine when you don't hold any other device locks;
- * to acquire nested inner locks call down(&udev->serialize) directly.
- * This is necessary for proper interaction with usb_lock_all_devices().
- */
-void usb_lock_device(struct usb_device *udev)
-{
-	down_read(&usb_all_devices_rwsem);
-	down(&udev->serialize);
-}
-
-/**
- * usb_trylock_device - attempt to acquire the lock for a usb device structure
- * @udev: device that's being locked
- *
- * Don't use this routine if you already hold a device lock;
- * use down_trylock(&udev->serialize) instead.
- * This is necessary for proper interaction with usb_lock_all_devices().
- *
- * Returns 1 if successful, 0 if contention.
- */
-int usb_trylock_device(struct usb_device *udev)
-{
-	if (!down_read_trylock(&usb_all_devices_rwsem))
-		return 0;
-	if (down_trylock(&udev->serialize)) {
-		up_read(&usb_all_devices_rwsem);
-		return 0;
-	}
-	return 1;
-}
-
-/**
  * usb_lock_device_for_reset - cautiously acquire the lock for a
  *	usb device structure
  * @udev: device that's being locked
@@ -935,7 +568,7 @@ int usb_lock_device_for_reset(struct usb_device *udev,
 		}
 	}
 
-	while (!usb_trylock_device(udev)) {
+	while (usb_trylock_device(udev) != 0) {
 
 		/* If we can't acquire the lock after waiting one second,
 		 * we're probably deadlocked */
@@ -953,39 +586,6 @@ int usb_lock_device_for_reset(struct usb_device *udev,
 	return 1;
 }
 
-/**
- * usb_unlock_device - release the lock for a usb device structure
- * @udev: device that's being unlocked
- *
- * Use this routine when releasing the only device lock you hold;
- * to release inner nested locks call up(&udev->serialize) directly.
- * This is necessary for proper interaction with usb_lock_all_devices().
- */
-void usb_unlock_device(struct usb_device *udev)
-{
-	up(&udev->serialize);
-	up_read(&usb_all_devices_rwsem);
-}
-
-/**
- * usb_lock_all_devices - acquire the lock for all usb device structures
- *
- * This is necessary when registering a new driver or probing a bus,
- * since the driver-model core may try to use any usb_device.
- */
-void usb_lock_all_devices(void)
-{
-	down_write(&usb_all_devices_rwsem);
-}
-
-/**
- * usb_unlock_all_devices - release the lock for all usb device structures
- */
-void usb_unlock_all_devices(void)
-{
-	up_write(&usb_all_devices_rwsem);
-}
-
 
 static struct usb_device *match_device(struct usb_device *dev,
 				       u16 vendor_id, u16 product_id)
@@ -1008,10 +608,10 @@ static struct usb_device *match_device(struct usb_device *dev,
 	/* look through all of the children of this device */
 	for (child = 0; child < dev->maxchild; ++child) {
 		if (dev->children[child]) {
-			down(&dev->children[child]->serialize);
+			usb_lock_device(dev->children[child]);
 			ret_dev = match_device(dev->children[child],
 					       vendor_id, product_id);
-			up(&dev->children[child]->serialize);
+			usb_unlock_device(dev->children[child]);
 			if (ret_dev)
 				goto exit;
 		}
@@ -1491,23 +1091,13 @@ static int usb_generic_resume(struct device *dev)
 struct bus_type usb_bus_type = {
 	.name =		"usb",
 	.match =	usb_device_match,
-	.hotplug =	usb_hotplug,
+	.uevent =	usb_uevent,
 	.suspend =	usb_generic_suspend,
 	.resume =	usb_generic_resume,
 };
 
-#ifndef MODULE
-
-static int __init usb_setup_disable(char *str)
-{
-	nousb = 1;
-	return 1;
-}
-
 /* format to disable USB on kernel command line is: nousb */
-__setup("nousb", usb_setup_disable);
-
-#endif
+__module_param_call("", nousb, param_set_bool, param_get_bool, &nousb, 0444);
 
 /*
  * for external read access to <nousb>
@@ -1598,8 +1188,6 @@ module_exit(usb_exit);
  * driver modules to use.
  */
 
-EXPORT_SYMBOL(usb_register);
-EXPORT_SYMBOL(usb_deregister);
 EXPORT_SYMBOL(usb_disabled);
 
 EXPORT_SYMBOL_GPL(usb_get_intf);
@@ -1610,14 +1198,10 @@ EXPORT_SYMBOL(usb_put_dev);
 EXPORT_SYMBOL(usb_get_dev);
 EXPORT_SYMBOL(usb_hub_tt_clear_buffer);
 
-EXPORT_SYMBOL(usb_lock_device);
-EXPORT_SYMBOL(usb_trylock_device);
 EXPORT_SYMBOL(usb_lock_device_for_reset);
-EXPORT_SYMBOL(usb_unlock_device);
 
 EXPORT_SYMBOL(usb_driver_claim_interface);
 EXPORT_SYMBOL(usb_driver_release_interface);
-EXPORT_SYMBOL(usb_match_id);
 EXPORT_SYMBOL(usb_find_interface);
 EXPORT_SYMBOL(usb_ifnum_to_if);
 EXPORT_SYMBOL(usb_altnum_to_altsetting);
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index 1c4a68499dce..4647e1ebc68d 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -16,9 +16,6 @@ extern int usb_get_device_descriptor(struct usb_device *dev,
 extern char *usb_cache_string(struct usb_device *udev, int index);
 extern int usb_set_configuration(struct usb_device *dev, int configuration);
 
-extern void usb_lock_all_devices(void);
-extern void usb_unlock_all_devices(void);
-
 extern void usb_kick_khubd(struct usb_device *dev);
 extern void usb_suspend_root_hub(struct usb_device *hdev);
 extern void usb_resume_root_hub(struct usb_device *dev);
@@ -33,6 +30,9 @@ extern void usb_host_cleanup(void);
 extern int usb_suspend_device(struct usb_device *dev);
 extern int usb_resume_device(struct usb_device *dev);
 
+extern struct device_driver usb_generic_driver;
+extern int usb_generic_driver_data;
+extern int usb_device_match(struct device *dev, struct device_driver *drv);
 
 /* Interfaces and their "power state" are owned by usbcore */
 
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index c655d46c8aed..9734cb76dd6c 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -138,7 +138,7 @@ static const char *const ep_name [] = {
 	/* or like sa1100: two fixed function endpoints */
 	"ep1out-bulk", "ep2in-bulk",
 };
-#define DUMMY_ENDPOINTS	(sizeof(ep_name)/sizeof(char *))
+#define DUMMY_ENDPOINTS	ARRAY_SIZE(ep_name)
 
 /*-------------------------------------------------------------------------*/
 
@@ -896,7 +896,7 @@ dummy_gadget_release (struct device *dev)
 #endif
 }
 
-static int dummy_udc_probe (struct platform_device *dev)
+static int dummy_udc_probe (struct platform_device *pdev)
 {
 	struct dummy	*dum = the_controller;
 	int		rc;
@@ -909,7 +909,7 @@ static int dummy_udc_probe (struct platform_device *dev)
 	dum->gadget.is_otg = (dummy_to_hcd(dum)->self.otg_port != 0);
 
 	strcpy (dum->gadget.dev.bus_id, "gadget");
-	dum->gadget.dev.parent = &dev->dev;
+	dum->gadget.dev.parent = &pdev->dev;
 	dum->gadget.dev.release = dummy_gadget_release;
 	rc = device_register (&dum->gadget.dev);
 	if (rc < 0)
@@ -919,47 +919,47 @@ static int dummy_udc_probe (struct platform_device *dev)
 	usb_bus_get (&dummy_to_hcd (dum)->self);
 #endif
 
-	platform_set_drvdata (dev, dum);
+	platform_set_drvdata (pdev, dum);
 	device_create_file (&dum->gadget.dev, &dev_attr_function);
 	return rc;
 }
 
-static int dummy_udc_remove (struct platform_device *dev)
+static int dummy_udc_remove (struct platform_device *pdev)
 {
-	struct dummy	*dum = platform_get_drvdata (dev);
+	struct dummy	*dum = platform_get_drvdata (pdev);
 
-	platform_set_drvdata (dev, NULL);
+	platform_set_drvdata (pdev, NULL);
 	device_remove_file (&dum->gadget.dev, &dev_attr_function);
 	device_unregister (&dum->gadget.dev);
 	return 0;
 }
 
-static int dummy_udc_suspend (struct platform_device *dev, pm_message_t state)
+static int dummy_udc_suspend (struct platform_device *pdev, pm_message_t state)
 {
-	struct dummy	*dum = platform_get_drvdata(dev);
+	struct dummy	*dum = platform_get_drvdata(pdev);
 
-	dev_dbg (&dev->dev, "%s\n", __FUNCTION__);
+	dev_dbg (&pdev->dev, "%s\n", __FUNCTION__);
 	spin_lock_irq (&dum->lock);
 	dum->udc_suspended = 1;
 	set_link_state (dum);
 	spin_unlock_irq (&dum->lock);
 
-	dev->dev.power.power_state = state;
+	pdev->dev.power.power_state = state;
 	usb_hcd_poll_rh_status (dummy_to_hcd (dum));
 	return 0;
 }
 
-static int dummy_udc_resume (struct platform_device *dev)
+static int dummy_udc_resume (struct platform_device *pdev)
 {
-	struct dummy	*dum = platform_get_drvdata(dev);
+	struct dummy	*dum = platform_get_drvdata(pdev);
 
-	dev_dbg (&dev->dev, "%s\n", __FUNCTION__);
+	dev_dbg (&pdev->dev, "%s\n", __FUNCTION__);
 	spin_lock_irq (&dum->lock);
 	dum->udc_suspended = 0;
 	set_link_state (dum);
 	spin_unlock_irq (&dum->lock);
 
-	dev->dev.power.power_state = PMSG_ON;
+	pdev->dev.power.power_state = PMSG_ON;
 	usb_hcd_poll_rh_status (dummy_to_hcd (dum));
 	return 0;
 }
@@ -1576,7 +1576,7 @@ static int dummy_hub_status (struct usb_hcd *hcd, char *buf)
 	dum = hcd_to_dummy (hcd);
 
 	spin_lock_irqsave (&dum->lock, flags);
-	if (hcd->state != HC_STATE_RUNNING)
+	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
 		goto done;
 
 	if (dum->resuming && time_after_eq (jiffies, dum->re_timeout)) {
@@ -1623,7 +1623,7 @@ static int dummy_hub_control (
 	int		retval = 0;
 	unsigned long	flags;
 
-	if (hcd->state != HC_STATE_RUNNING)
+	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
 		return -ETIMEDOUT;
 
 	dum = hcd_to_dummy (hcd);
@@ -1756,9 +1756,12 @@ static int dummy_bus_suspend (struct usb_hcd *hcd)
 {
 	struct dummy *dum = hcd_to_dummy (hcd);
 
+	dev_dbg (&hcd->self.root_hub->dev, "%s\n", __FUNCTION__);
+
 	spin_lock_irq (&dum->lock);
 	dum->rh_state = DUMMY_RH_SUSPENDED;
 	set_link_state (dum);
+	hcd->state = HC_STATE_SUSPENDED;
 	spin_unlock_irq (&dum->lock);
 	return 0;
 }
@@ -1766,14 +1769,23 @@ static int dummy_bus_suspend (struct usb_hcd *hcd)
 static int dummy_bus_resume (struct usb_hcd *hcd)
 {
 	struct dummy *dum = hcd_to_dummy (hcd);
+	int rc = 0;
+
+	dev_dbg (&hcd->self.root_hub->dev, "%s\n", __FUNCTION__);
 
 	spin_lock_irq (&dum->lock);
-	dum->rh_state = DUMMY_RH_RUNNING;
-	set_link_state (dum);
-	if (!list_empty(&dum->urbp_list))
-		mod_timer (&dum->timer, jiffies);
+	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
+		dev_warn (&hcd->self.root_hub->dev, "HC isn't running!\n");
+		rc = -ENODEV;
+	} else {
+		dum->rh_state = DUMMY_RH_RUNNING;
+		set_link_state (dum);
+		if (!list_empty(&dum->urbp_list))
+			mod_timer (&dum->timer, jiffies);
+		hcd->state = HC_STATE_RUNNING;
+	}
 	spin_unlock_irq (&dum->lock);
-	return 0;
+	return rc;
 }
 
 /*-------------------------------------------------------------------------*/
@@ -1899,14 +1911,14 @@ static const struct hc_driver dummy_hcd = {
 	.bus_resume =		dummy_bus_resume,
 };
 
-static int dummy_hcd_probe (struct platform_device *dev)
+static int dummy_hcd_probe(struct platform_device *pdev)
 {
 	struct usb_hcd		*hcd;
 	int			retval;
 
-	dev_info(&dev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc);
+	dev_info(&pdev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc);
 
-	hcd = usb_create_hcd (&dummy_hcd, &dev->dev, dev->dev.bus_id);
+	hcd = usb_create_hcd(&dummy_hcd, &pdev->dev, pdev->dev.bus_id);
 	if (!hcd)
 		return -ENOMEM;
 	the_controller = hcd_to_dummy (hcd);
@@ -1919,36 +1931,43 @@ static int dummy_hcd_probe (struct platform_device *dev)
 	return retval;
 }
 
-static int dummy_hcd_remove (struct platform_device *dev)
+static int dummy_hcd_remove (struct platform_device *pdev)
 {
 	struct usb_hcd		*hcd;
 
-	hcd = platform_get_drvdata (dev);
+	hcd = platform_get_drvdata (pdev);
 	usb_remove_hcd (hcd);
 	usb_put_hcd (hcd);
 	the_controller = NULL;
 	return 0;
 }
 
-static int dummy_hcd_suspend (struct platform_device *dev, pm_message_t state)
+static int dummy_hcd_suspend (struct platform_device *pdev, pm_message_t state)
 {
 	struct usb_hcd		*hcd;
+	struct dummy		*dum;
+	int			rc = 0;
 
-	dev_dbg (&dev->dev, "%s\n", __FUNCTION__);
-	hcd = platform_get_drvdata (dev);
+	dev_dbg (&pdev->dev, "%s\n", __FUNCTION__);
 
-	hcd->state = HC_STATE_SUSPENDED;
-	return 0;
+	hcd = platform_get_drvdata (pdev);
+	dum = hcd_to_dummy (hcd);
+	if (dum->rh_state == DUMMY_RH_RUNNING) {
+		dev_warn(&pdev->dev, "Root hub isn't suspended!\n");
+		rc = -EBUSY;
+	} else
+		clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+	return rc;
 }
 
-static int dummy_hcd_resume (struct platform_device *dev)
+static int dummy_hcd_resume (struct platform_device *pdev)
 {
 	struct usb_hcd		*hcd;
 
-	dev_dbg (&dev->dev, "%s\n", __FUNCTION__);
-	hcd = platform_get_drvdata (dev);
-	hcd->state = HC_STATE_RUNNING;
+	dev_dbg (&pdev->dev, "%s\n", __FUNCTION__);
 
+	hcd = platform_get_drvdata (pdev);
+	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
 	usb_hcd_poll_rh_status (hcd);
 	return 0;
 }
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index ea09aaa3cab6..0cea9782d7d4 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -224,6 +224,7 @@
 #include <linux/fs.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/kref.h>
 #include <linux/kthread.h>
 #include <linux/limits.h>
 #include <linux/list.h>
@@ -238,7 +239,6 @@
 #include <linux/string.h>
 #include <linux/suspend.h>
 #include <linux/utsname.h>
-#include <linux/wait.h>
 
 #include <linux/usb_ch9.h>
 #include <linux/usb_gadget.h>
@@ -250,7 +250,7 @@
 
 #define DRIVER_DESC		"File-backed Storage Gadget"
 #define DRIVER_NAME		"g_file_storage"
-#define DRIVER_VERSION		"20 October 2004"
+#define DRIVER_VERSION		"28 November 2005"
 
 static const char longname[] = DRIVER_DESC;
 static const char shortname[] = DRIVER_NAME;
@@ -335,8 +335,8 @@ MODULE_LICENSE("Dual BSD/GPL");
 #define MAX_LUNS	8
 
 	/* Arggh!  There should be a module_param_array_named macro! */
-static char		*file[MAX_LUNS] = {NULL, };
-static int		ro[MAX_LUNS] = {0, };
+static char		*file[MAX_LUNS];
+static int		ro[MAX_LUNS];
 
 static struct {
 	int		num_filenames;
@@ -587,7 +587,7 @@ enum fsg_buffer_state {
 struct fsg_buffhd {
 	void				*buf;
 	dma_addr_t			dma;
-	volatile enum fsg_buffer_state	state;
+	enum fsg_buffer_state		state;
 	struct fsg_buffhd		*next;
 
 	/* The NetChip 2280 is faster, and handles some protocol faults
@@ -596,9 +596,9 @@ struct fsg_buffhd {
 	unsigned int			bulk_out_intended_length;
 
 	struct usb_request		*inreq;
-	volatile int			inreq_busy;
+	int				inreq_busy;
 	struct usb_request		*outreq;
-	volatile int			outreq_busy;
+	int				outreq_busy;
 };
 
 enum fsg_state {
@@ -631,13 +631,16 @@ struct fsg_dev {
 	/* filesem protects: backing files in use */
 	struct rw_semaphore	filesem;
 
+	/* reference counting: wait until all LUNs are released */
+	struct kref		ref;
+
 	struct usb_ep		*ep0;		// Handy copy of gadget->ep0
 	struct usb_request	*ep0req;	// For control responses
-	volatile unsigned int	ep0_req_tag;
+	unsigned int		ep0_req_tag;
 	const char		*ep0req_name;
 
 	struct usb_request	*intreq;	// For interrupt responses
-	volatile int		intreq_busy;
+	int			intreq_busy;
 	struct fsg_buffhd	*intr_buffhd;
 
  	unsigned int		bulk_out_maxpacket;
@@ -667,7 +670,6 @@ struct fsg_dev {
 	struct fsg_buffhd	*next_buffhd_to_drain;
 	struct fsg_buffhd	buffhds[NUM_BUFFERS];
 
-	wait_queue_head_t	thread_wqh;
 	int			thread_wakeup_needed;
 	struct completion	thread_notifier;
 	struct task_struct	*thread_task;
@@ -694,7 +696,6 @@ struct fsg_dev {
 	unsigned int		nluns;
 	struct lun		*luns;
 	struct lun		*curlun;
-	struct completion	lun_released;
 };
 
 typedef void (*fsg_routine_t)(struct fsg_dev *);
@@ -1073,11 +1074,13 @@ static int populate_config_buf(struct usb_gadget *gadget,
 
 /* These routines may be called in process context or in_irq */
 
+/* Caller must hold fsg->lock */
 static void wakeup_thread(struct fsg_dev *fsg)
 {
 	/* Tell the main thread that something has happened */
 	fsg->thread_wakeup_needed = 1;
-	wake_up_all(&fsg->thread_wqh);
+	if (fsg->thread_task)
+		wake_up_process(fsg->thread_task);
 }
 
 
@@ -1164,11 +1167,12 @@ static void bulk_in_complete(struct usb_ep *ep, struct usb_request *req)
 		usb_ep_fifo_flush(ep);
 
 	/* Hold the lock while we update the request and buffer states */
+	smp_wmb();
 	spin_lock(&fsg->lock);
 	bh->inreq_busy = 0;
 	bh->state = BUF_STATE_EMPTY;
-	spin_unlock(&fsg->lock);
 	wakeup_thread(fsg);
+	spin_unlock(&fsg->lock);
 }
 
 static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req)
@@ -1185,11 +1189,12 @@ static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req)
 		usb_ep_fifo_flush(ep);
 
 	/* Hold the lock while we update the request and buffer states */
+	smp_wmb();
 	spin_lock(&fsg->lock);
 	bh->outreq_busy = 0;
 	bh->state = BUF_STATE_FULL;
-	spin_unlock(&fsg->lock);
 	wakeup_thread(fsg);
+	spin_unlock(&fsg->lock);
 }
 
 
@@ -1206,11 +1211,12 @@ static void intr_in_complete(struct usb_ep *ep, struct usb_request *req)
 		usb_ep_fifo_flush(ep);
 
 	/* Hold the lock while we update the request and buffer states */
+	smp_wmb();
 	spin_lock(&fsg->lock);
 	fsg->intreq_busy = 0;
 	bh->state = BUF_STATE_EMPTY;
-	spin_unlock(&fsg->lock);
 	wakeup_thread(fsg);
+	spin_unlock(&fsg->lock);
 }
 
 #else
@@ -1261,8 +1267,8 @@ static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
 	fsg->cbbuf_cmnd_size = req->actual;
 	memcpy(fsg->cbbuf_cmnd, req->buf, fsg->cbbuf_cmnd_size);
 
-	spin_unlock(&fsg->lock);
 	wakeup_thread(fsg);
+	spin_unlock(&fsg->lock);
 }
 
 #else
@@ -1514,8 +1520,8 @@ static int fsg_setup(struct usb_gadget *gadget,
 
 /* Use this for bulk or interrupt transfers, not ep0 */
 static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep,
-		struct usb_request *req, volatile int *pbusy,
-		volatile enum fsg_buffer_state *state)
+		struct usb_request *req, int *pbusy,
+		enum fsg_buffer_state *state)
 {
 	int	rc;
 
@@ -1523,8 +1529,11 @@ static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep,
 		dump_msg(fsg, "bulk-in", req->buf, req->length);
 	else if (ep == fsg->intr_in)
 		dump_msg(fsg, "intr-in", req->buf, req->length);
+
+	spin_lock_irq(&fsg->lock);
 	*pbusy = 1;
 	*state = BUF_STATE_BUSY;
+	spin_unlock_irq(&fsg->lock);
 	rc = usb_ep_queue(ep, req, GFP_KERNEL);
 	if (rc != 0) {
 		*pbusy = 0;
@@ -1544,14 +1553,23 @@ static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep,
 
 static int sleep_thread(struct fsg_dev *fsg)
 {
-	int	rc;
+	int	rc = 0;
 
 	/* Wait until a signal arrives or we are woken up */
-	rc = wait_event_interruptible(fsg->thread_wqh,
-			fsg->thread_wakeup_needed);
+	for (;;) {
+		try_to_freeze();
+		set_current_state(TASK_INTERRUPTIBLE);
+		if (signal_pending(current)) {
+			rc = -EINTR;
+			break;
+		}
+		if (fsg->thread_wakeup_needed)
+			break;
+		schedule();
+	}
+	__set_current_state(TASK_RUNNING);
 	fsg->thread_wakeup_needed = 0;
-	try_to_freeze();
-	return (rc ? -EINTR : 0);
+	return rc;
 }
 
 
@@ -1788,6 +1806,7 @@ static int do_write(struct fsg_dev *fsg)
 		if (bh->state == BUF_STATE_EMPTY && !get_some_more)
 			break;			// We stopped early
 		if (bh->state == BUF_STATE_FULL) {
+			smp_rmb();
 			fsg->next_buffhd_to_drain = bh->next;
 			bh->state = BUF_STATE_EMPTY;
 
@@ -2356,6 +2375,7 @@ static int throw_away_data(struct fsg_dev *fsg)
 
 		/* Throw away the data in a filled buffer */
 		if (bh->state == BUF_STATE_FULL) {
+			smp_rmb();
 			bh->state = BUF_STATE_EMPTY;
 			fsg->next_buffhd_to_drain = bh->next;
 
@@ -3021,6 +3041,7 @@ static int get_next_command(struct fsg_dev *fsg)
 			if ((rc = sleep_thread(fsg)) != 0)
 				return rc;
 			}
+		smp_rmb();
 		rc = received_cbw(fsg, bh);
 		bh->state = BUF_STATE_EMPTY;
 
@@ -3642,11 +3663,19 @@ static DEVICE_ATTR(file, 0444, show_file, NULL);
 
 /*-------------------------------------------------------------------------*/
 
+static void fsg_release(struct kref *ref)
+{
+	struct fsg_dev	*fsg = container_of(ref, struct fsg_dev, ref);
+
+	kfree(fsg->luns);
+	kfree(fsg);
+}
+
 static void lun_release(struct device *dev)
 {
 	struct fsg_dev	*fsg = (struct fsg_dev *) dev_get_drvdata(dev);
 
-	complete(&fsg->lun_released);
+	kref_put(&fsg->ref, fsg_release);
 }
 
 static void fsg_unbind(struct usb_gadget *gadget)
@@ -3660,14 +3689,12 @@ static void fsg_unbind(struct usb_gadget *gadget)
 	clear_bit(REGISTERED, &fsg->atomic_bitflags);
 
 	/* Unregister the sysfs attribute files and the LUNs */
-	init_completion(&fsg->lun_released);
 	for (i = 0; i < fsg->nluns; ++i) {
 		curlun = &fsg->luns[i];
 		if (curlun->registered) {
 			device_remove_file(&curlun->dev, &dev_attr_ro);
 			device_remove_file(&curlun->dev, &dev_attr_file);
 			device_unregister(&curlun->dev);
-			wait_for_completion(&fsg->lun_released);
 			curlun->registered = 0;
 		}
 	}
@@ -3846,6 +3873,7 @@ static int __init fsg_bind(struct usb_gadget *gadget)
 			curlun->dev.release = lun_release;
 			device_create_file(&curlun->dev, &dev_attr_ro);
 			device_create_file(&curlun->dev, &dev_attr_file);
+			kref_get(&fsg->ref);
 		}
 
 		if (file[i] && *file[i]) {
@@ -4061,7 +4089,7 @@ static int __init fsg_alloc(void)
 		return -ENOMEM;
 	spin_lock_init(&fsg->lock);
 	init_rwsem(&fsg->filesem);
-	init_waitqueue_head(&fsg->thread_wqh);
+	kref_init(&fsg->ref);
 	init_completion(&fsg->thread_notifier);
 
 	the_fsg = fsg;
@@ -4069,13 +4097,6 @@ static int __init fsg_alloc(void)
 }
 
 
-static void fsg_free(struct fsg_dev *fsg)
-{
-	kfree(fsg->luns);
-	kfree(fsg);
-}
-
-
 static int __init fsg_init(void)
 {
 	int		rc;
@@ -4085,7 +4106,7 @@ static int __init fsg_init(void)
 		return rc;
 	fsg = the_fsg;
 	if ((rc = usb_gadget_register_driver(&fsg_driver)) != 0)
-		fsg_free(fsg);
+		kref_put(&fsg->ref, fsg_release);
 	return rc;
 }
 module_init(fsg_init);
@@ -4103,6 +4124,6 @@ static void __exit fsg_cleanup(void)
 	wait_for_completion(&fsg->thread_notifier);
 
 	close_all_backing_files(fsg);
-	fsg_free(fsg);
+	kref_put(&fsg->ref, fsg_release);
 }
 module_exit(fsg_cleanup);
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index b35ac6d334f8..65e084a2c87e 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -890,10 +890,12 @@ static void gs_close(struct tty_struct *tty, struct file *file)
 	/* wait for write buffer to drain, or */
 	/* at most GS_CLOSE_TIMEOUT seconds */
 	if (gs_buf_data_avail(port->port_write_buf) > 0) {
+		spin_unlock_irqrestore(&port->port_lock, flags);
 		wait_cond_interruptible_timeout(port->port_write_wait,
 		port->port_dev == NULL
 		|| gs_buf_data_avail(port->port_write_buf) == 0,
 		&port->port_lock, flags, GS_CLOSE_TIMEOUT * HZ);
+		spin_lock_irqsave(&port->port_lock, flags);
 	}
 
 	/* free disconnected port on final close */
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 58321d3f314c..e3020f4b17be 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -2,6 +2,10 @@
 # Makefile for USB Host Controller Drivers
 #
 
+ifeq ($(CONFIG_USB_DEBUG),y)
+	EXTRA_CFLAGS		+= -DDEBUG
+endif
+
 obj-$(CONFIG_PCI)		+= pci-quirks.o
 
 obj-$(CONFIG_USB_EHCI_HCD)	+= ehci-hcd.o
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 29f52a44b928..9dd3d14c64f3 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -17,13 +17,6 @@
  */
 
 #include <linux/config.h>
-
-#ifdef CONFIG_USB_DEBUG
-	#define DEBUG
-#else
-	#undef DEBUG
-#endif
-
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/dmapool.h>
@@ -624,7 +617,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs)
 	}
 
 	/* remote wakeup [4.3.1] */
-	if ((status & STS_PCD) && hcd->remote_wakeup) {
+	if (status & STS_PCD) {
 		unsigned	i = HCS_N_PORTS (ehci->hcs_params);
 
 		/* resume root hub? */
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 82caf336e9b6..69b0b9be7a64 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -59,7 +59,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
 
 		if ((t1 & PORT_PE) && !(t1 & PORT_OWNER))
 			t2 |= PORT_SUSPEND;
-		if (hcd->remote_wakeup)
+		if (device_may_wakeup(&hcd->self.root_hub->dev))
 			t2 |= PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E;
 		else
 			t2 &= ~(PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E);
@@ -517,7 +517,7 @@ static int ehci_hub_control (
 			if ((temp & PORT_PE) == 0
 					|| (temp & PORT_RESET) != 0)
 				goto error;
-			if (hcd->remote_wakeup)
+			if (device_may_wakeup(&hcd->self.root_hub->dev))
 				temp |= PORT_WAKE_BITS;
 			writel (temp | PORT_SUSPEND,
 				&ehci->regs->port_status [wIndex]);
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 13f73a836e45..08ca0f849dab 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -210,7 +210,16 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
 	/* Serial Bus Release Number is at PCI 0x60 offset */
 	pci_read_config_byte(pdev, 0x60, &ehci->sbrn);
 
-	/* REVISIT:  per-port wake capability (PCI 0x62) currently unused */
+	/* Workaround current PCI init glitch:  wakeup bits aren't
+	 * being set from PCI PM capability.
+	 */
+	if (!device_can_wakeup(&pdev->dev)) {
+		u16	port_wake;
+
+		pci_read_config_word(pdev, 0x62, &port_wake);
+		if (port_wake & 0x0001)
+			device_init_wakeup(&pdev->dev, 1);
+	}
 
 	retval = ehci_pci_reinit(ehci, pdev);
 done:
@@ -269,7 +278,6 @@ static int ehci_pci_resume(struct usb_hcd *hcd)
 {
 	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
 	unsigned		port;
-	struct usb_device	*root = hcd->self.root_hub;
 	struct pci_dev		*pdev = to_pci_dev(hcd->self.controller);
 	int			retval = -EINVAL;
 
@@ -303,13 +311,7 @@ static int ehci_pci_resume(struct usb_hcd *hcd)
 
 restart:
 	ehci_dbg(ehci, "lost power, restarting\n");
-	for (port = HCS_N_PORTS(ehci->hcs_params); port > 0; ) {
-		port--;
-		if (!root->children [port])
-			continue;
-		usb_set_device_state(root->children[port],
-					USB_STATE_NOTATTACHED);
-	}
+	usb_root_hub_lost_power(hcd->self.root_hub);
 
 	/* Else reset, to cope with power loss or flush-to-storage
 	 * style "resume" having let BIOS kick in during reboot.
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index bf03ec0d8ee2..9b13bf2fa98d 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -514,18 +514,18 @@ qh_urb_transaction (
 		qtd->urb = urb;
 		qtd_prev->hw_next = QTD_NEXT (qtd->qtd_dma);
 		list_add_tail (&qtd->qtd_list, head);
+
+		/* for zero length DATA stages, STATUS is always IN */
+		if (len == 0)
+			token |= (1 /* "in" */ << 8);
 	} 
 
 	/*
 	 * data transfer stage:  buffer setup
 	 */
-	if (likely (len > 0))
-		buf = urb->transfer_dma;
-	else
-		buf = 0;
+	buf = urb->transfer_dma;
 
-	/* for zero length DATA stages, STATUS is always IN */
-	if (!buf || is_input)
+	if (is_input)
 		token |= (1 /* "in" */ << 8);
 	/* else it's already initted to "out" pid (0 << 8) */
 
@@ -572,7 +572,7 @@ qh_urb_transaction (
 	 * control requests may need a terminating data "status" ack;
 	 * bulk ones may need a terminating short packet (zero length).
 	 */
-	if (likely (buf != 0)) {
+	if (likely (urb->transfer_buffer_length != 0)) {
 		int	one_more = 0;
 
 		if (usb_pipecontrol (urb->pipe)) {
diff --git a/drivers/usb/host/hc_crisv10.c b/drivers/usb/host/hc_crisv10.c
index 0eaabeb37ac3..641268d7e6f3 100644
--- a/drivers/usb/host/hc_crisv10.c
+++ b/drivers/usb/host/hc_crisv10.c
@@ -4397,7 +4397,7 @@ static int __init etrax_usb_hc_init(void)
         device_initialize(&fake_device);
         kobject_set_name(&fake_device.kobj, "etrax_usb");
         kobject_add(&fake_device.kobj);
-        kobject_hotplug(&fake_device.kobj, KOBJ_ADD);
+	kobject_uevent(&fake_device.kobj, KOBJ_ADD);
         hc->bus->controller = &fake_device;
 	usb_register_bus(hc->bus);
 
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index 82f64986bc22..584b8dc65119 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -55,19 +55,13 @@
 /* enqueuing/finishing log of urbs */
 //#define URB_TRACE
 
-#include <linux/config.h>
 #include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
 #include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/list.h>
-#include <linux/interrupt.h>
 #include <linux/usb.h>
 #include <linux/usb_isp116x.h>
 #include <linux/platform_device.h>
@@ -77,14 +71,10 @@
 #include <asm/system.h>
 #include <asm/byteorder.h>
 
-#ifndef DEBUG
-#	define	STUB_DEBUG_FILE
-#endif
-
 #include "../core/hcd.h"
 #include "isp116x.h"
 
-#define DRIVER_VERSION	"05 Aug 2005"
+#define DRIVER_VERSION	"03 Nov 2005"
 #define DRIVER_DESC	"ISP116x USB Host Controller Driver"
 
 MODULE_DESCRIPTION(DRIVER_DESC);
@@ -164,13 +154,11 @@ static void pack_fifo(struct isp116x *isp116x)
 	struct ptd *ptd;
 	int buflen = isp116x->atl_last_dir == PTD_DIR_IN
 	    ? isp116x->atl_bufshrt : isp116x->atl_buflen;
-	int ptd_count = 0;
 
 	isp116x_write_reg16(isp116x, HCuPINT, HCuPINT_AIIEOT);
 	isp116x_write_reg16(isp116x, HCXFERCTR, buflen);
 	isp116x_write_addr(isp116x, HCATLPORT | ISP116x_WRITE_OFFSET);
 	for (ep = isp116x->atl_active; ep; ep = ep->active) {
-		++ptd_count;
 		ptd = &ep->ptd;
 		dump_ptd(ptd);
 		dump_ptd_out_data(ptd, ep->data);
@@ -305,9 +293,8 @@ static void postproc_atl_queue(struct isp116x *isp116x)
 		udev = urb->dev;
 		ptd = &ep->ptd;
 		cc = PTD_GET_CC(ptd);
-
-		spin_lock(&urb->lock);
 		short_not_ok = 1;
+		spin_lock(&urb->lock);
 
 		/* Data underrun is special. For allowed underrun
 		   we clear the error and continue as normal. For
@@ -420,7 +407,7 @@ static void postproc_atl_queue(struct isp116x *isp116x)
 			ep->nextpid = 0;
 			break;
 		default:
-			BUG_ON(1);
+			BUG();
 		}
 		spin_unlock(&urb->lock);
 	}
@@ -628,8 +615,12 @@ static irqreturn_t isp116x_irq(struct usb_hcd *hcd, struct pt_regs *regs)
 		u32 intstat = isp116x_read_reg32(isp116x, HCINTSTAT);
 		isp116x_write_reg32(isp116x, HCINTSTAT, intstat);
 		if (intstat & HCINT_UE) {
-			ERR("Unrecoverable error\n");
-			/* What should we do here? Reset?  */
+			ERR("Unrecoverable error, HC is dead!\n");
+			/* IRQ's are off, we do no DMA,
+			   perfectly ready to die ... */
+			hcd->state = HC_STATE_HALT;
+			ret = IRQ_HANDLED;
+			goto done;
 		}
 		if (intstat & HCINT_RHSC)
 			/* When root hub or any of its ports is going
@@ -640,7 +631,6 @@ static irqreturn_t isp116x_irq(struct usb_hcd *hcd, struct pt_regs *regs)
 		if (intstat & HCINT_RD) {
 			DBG("---- remote wakeup\n");
 			usb_hcd_resume_root_hub(hcd);
-			ret = IRQ_HANDLED;
 		}
 		irqstat &= ~HCuPINT_OPR;
 		ret = IRQ_HANDLED;
@@ -651,6 +641,7 @@ static irqreturn_t isp116x_irq(struct usb_hcd *hcd, struct pt_regs *regs)
 	}
 
 	isp116x_write_reg16(isp116x, HCuPINTENB, isp116x->irqenb);
+      done:
 	spin_unlock(&isp116x->lock);
 	return ret;
 }
@@ -724,6 +715,7 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd,
 
 	spin_lock_irqsave(&isp116x->lock, flags);
 	if (!HC_IS_RUNNING(hcd->state)) {
+		kfree(ep);
 		ret = -ENODEV;
 		goto fail;
 	}
@@ -888,7 +880,7 @@ static void isp116x_endpoint_disable(struct usb_hcd *hcd,
 				     struct usb_host_endpoint *hep)
 {
 	int i;
-	struct isp116x_ep *ep = hep->hcpriv;;
+	struct isp116x_ep *ep = hep->hcpriv;
 
 	if (!ep)
 		return;
@@ -916,8 +908,6 @@ static int isp116x_get_frame(struct usb_hcd *hcd)
 	return (int)fmnum;
 }
 
-/*----------------------------------------------------------------*/
-
 /*
   Adapted from ohci-hub.c. Currently we don't support autosuspend.
 */
@@ -968,11 +958,10 @@ static void isp116x_hub_descriptor(struct isp116x *isp116x,
 	desc->bHubContrCurrent = 0;
 	desc->bNbrPorts = (u8) (reg & 0x3);
 	/* Power switching, device type, overcurrent. */
-	desc->wHubCharacteristics =
-	    (__force __u16) cpu_to_le16((u16) ((reg >> 8) & 0x1f));
+	desc->wHubCharacteristics = cpu_to_le16((u16) ((reg >> 8) & 0x1f));
 	desc->bPwrOn2PwrGood = (u8) ((reg >> 24) & 0xff);
 	/* two bitmaps:  ports removable, and legacy PortPwrCtrlMask */
-	desc->bitmap[0] = desc->bNbrPorts == 1 ? 1 << 1 : 3 << 1;
+	desc->bitmap[0] = 0;
 	desc->bitmap[1] = ~0;
 }
 
@@ -1159,135 +1148,9 @@ static int isp116x_hub_control(struct usb_hcd *hcd,
 	return ret;
 }
 
-#ifdef	CONFIG_PM
-
-static int isp116x_bus_suspend(struct usb_hcd *hcd)
-{
-	struct isp116x *isp116x = hcd_to_isp116x(hcd);
-	unsigned long flags;
-	u32 val;
-	int ret = 0;
-
-	spin_lock_irqsave(&isp116x->lock, flags);
-
-	val = isp116x_read_reg32(isp116x, HCCONTROL);
-	switch (val & HCCONTROL_HCFS) {
-	case HCCONTROL_USB_OPER:
-		hcd->state = HC_STATE_QUIESCING;
-		val &= (~HCCONTROL_HCFS & ~HCCONTROL_RWE);
-		val |= HCCONTROL_USB_SUSPEND;
-		if (hcd->remote_wakeup)
-			val |= HCCONTROL_RWE;
-		/* Wait for usb transfers to finish */
-		mdelay(2);
-		isp116x_write_reg32(isp116x, HCCONTROL, val);
-		hcd->state = HC_STATE_SUSPENDED;
-		/* Wait for devices to suspend */
-		mdelay(5);
-	case HCCONTROL_USB_SUSPEND:
-		break;
-	case HCCONTROL_USB_RESUME:
-		isp116x_write_reg32(isp116x, HCCONTROL,
-				    (val & ~HCCONTROL_HCFS) |
-				    HCCONTROL_USB_RESET);
-	case HCCONTROL_USB_RESET:
-		ret = -EBUSY;
-		break;
-	default:
-		ret = -EINVAL;
-	}
-
-	spin_unlock_irqrestore(&isp116x->lock, flags);
-	return ret;
-}
-
-static int isp116x_bus_resume(struct usb_hcd *hcd)
-{
-	struct isp116x *isp116x = hcd_to_isp116x(hcd);
-	u32 val;
-	int ret = -EINPROGRESS;
-
-	msleep(5);
-	spin_lock_irq(&isp116x->lock);
-
-	val = isp116x_read_reg32(isp116x, HCCONTROL);
-	switch (val & HCCONTROL_HCFS) {
-	case HCCONTROL_USB_SUSPEND:
-		val &= ~HCCONTROL_HCFS;
-		val |= HCCONTROL_USB_RESUME;
-		isp116x_write_reg32(isp116x, HCCONTROL, val);
-	case HCCONTROL_USB_RESUME:
-		break;
-	case HCCONTROL_USB_OPER:
-		/* Without setting power_state here the
-		   SUSPENDED state won't be removed from
-		   sysfs/usbN/power.state as a response to remote
-		   wakeup. Maybe in the future. */
-		hcd->self.root_hub->dev.power.power_state = PMSG_ON;
-		ret = 0;
-		break;
-	default:
-		ret = -EBUSY;
-	}
-
-	if (ret != -EINPROGRESS) {
-		spin_unlock_irq(&isp116x->lock);
-		return ret;
-	}
-
-	val = isp116x->rhdesca & RH_A_NDP;
-	while (val--) {
-		u32 stat =
-		    isp116x_read_reg32(isp116x, val ? HCRHPORT2 : HCRHPORT1);
-		/* force global, not selective, resume */
-		if (!(stat & RH_PS_PSS))
-			continue;
-		DBG("%s: Resuming port %d\n", __func__, val);
-		isp116x_write_reg32(isp116x, RH_PS_POCI, val
-				    ? HCRHPORT2 : HCRHPORT1);
-	}
-	spin_unlock_irq(&isp116x->lock);
-
-	hcd->state = HC_STATE_RESUMING;
-	mdelay(20);
-
-	/* Go operational */
-	spin_lock_irq(&isp116x->lock);
-	val = isp116x_read_reg32(isp116x, HCCONTROL);
-	isp116x_write_reg32(isp116x, HCCONTROL,
-			    (val & ~HCCONTROL_HCFS) | HCCONTROL_USB_OPER);
-	spin_unlock_irq(&isp116x->lock);
-	/* see analogous comment above */
-	hcd->self.root_hub->dev.power.power_state = PMSG_ON;
-	hcd->state = HC_STATE_RUNNING;
-
-	return 0;
-}
-
-
-#else
-
-#define	isp116x_bus_suspend	NULL
-#define	isp116x_bus_resume	NULL
-
-#endif
-
 /*-----------------------------------------------------------------*/
 
-#ifdef STUB_DEBUG_FILE
-
-static inline void create_debug_file(struct isp116x *isp116x)
-{
-}
-
-static inline void remove_debug_file(struct isp116x *isp116x)
-{
-}
-
-#else
-
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
+#ifdef CONFIG_DEBUG_FS
 
 static void dump_irq(struct seq_file *s, char *label, u16 mask)
 {
@@ -1311,13 +1174,9 @@ static void dump_int(struct seq_file *s, char *label, u32 mask)
 		   mask & HCINT_SF ? " sof" : "", mask & HCINT_SO ? " so" : "");
 }
 
-static int proc_isp116x_show(struct seq_file *s, void *unused)
+static int isp116x_show_dbg(struct seq_file *s, void *unused)
 {
 	struct isp116x *isp116x = s->private;
-	struct isp116x_ep *ep;
-	struct urb *urb;
-	unsigned i;
-	char *str;
 
 	seq_printf(s, "%s\n%s version %s\n",
 		   isp116x_to_hcd(isp116x)->product_desc, hcd_name,
@@ -1333,105 +1192,50 @@ static int proc_isp116x_show(struct seq_file *s, void *unused)
 	}
 
 	spin_lock_irq(&isp116x->lock);
-
 	dump_irq(s, "hc_irq_enable", isp116x_read_reg16(isp116x, HCuPINTENB));
 	dump_irq(s, "hc_irq_status", isp116x_read_reg16(isp116x, HCuPINT));
 	dump_int(s, "hc_int_enable", isp116x_read_reg32(isp116x, HCINTENB));
 	dump_int(s, "hc_int_status", isp116x_read_reg32(isp116x, HCINTSTAT));
-
-	list_for_each_entry(ep, &isp116x->async, schedule) {
-
-		switch (ep->nextpid) {
-		case USB_PID_IN:
-			str = "in";
-			break;
-		case USB_PID_OUT:
-			str = "out";
-			break;
-		case USB_PID_SETUP:
-			str = "setup";
-			break;
-		case USB_PID_ACK:
-			str = "status";
-			break;
-		default:
-			str = "?";
-			break;
-		};
-		seq_printf(s, "%p, ep%d%s, maxpacket %d:\n", ep,
-			   ep->epnum, str, ep->maxpacket);
-		list_for_each_entry(urb, &ep->hep->urb_list, urb_list) {
-			seq_printf(s, "  urb%p, %d/%d\n", urb,
-				   urb->actual_length,
-				   urb->transfer_buffer_length);
-		}
-	}
-	if (!list_empty(&isp116x->async))
-		seq_printf(s, "\n");
-
-	seq_printf(s, "periodic size= %d\n", PERIODIC_SIZE);
-
-	for (i = 0; i < PERIODIC_SIZE; i++) {
-		ep = isp116x->periodic[i];
-		if (!ep)
-			continue;
-		seq_printf(s, "%2d [%3d]:\n", i, isp116x->load[i]);
-
-		/* DUMB: prints shared entries multiple times */
-		do {
-			seq_printf(s, "   %d/%p (%sdev%d ep%d%s max %d)\n",
-				   ep->period, ep,
-				   (ep->udev->speed ==
-				    USB_SPEED_FULL) ? "" : "ls ",
-				   ep->udev->devnum, ep->epnum,
-				   (ep->epnum ==
-				    0) ? "" : ((ep->nextpid ==
-						USB_PID_IN) ? "in" : "out"),
-				   ep->maxpacket);
-			ep = ep->next;
-		} while (ep);
-	}
+	isp116x_show_regs_seq(isp116x, s);
 	spin_unlock_irq(&isp116x->lock);
 	seq_printf(s, "\n");
 
 	return 0;
 }
 
-static int proc_isp116x_open(struct inode *inode, struct file *file)
+static int isp116x_open_seq(struct inode *inode, struct file *file)
 {
-	return single_open(file, proc_isp116x_show, PDE(inode)->data);
+	return single_open(file, isp116x_show_dbg, inode->u.generic_ip);
 }
 
-static struct file_operations proc_ops = {
-	.open = proc_isp116x_open,
+static struct file_operations isp116x_debug_fops = {
+	.open = isp116x_open_seq,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 };
 
-/* expect just one isp116x per system */
-static const char proc_filename[] = "driver/isp116x";
-
-static void create_debug_file(struct isp116x *isp116x)
+static int create_debug_file(struct isp116x *isp116x)
 {
-	struct proc_dir_entry *pde;
-
-	pde = create_proc_entry(proc_filename, 0, NULL);
-	if (pde == NULL)
-		return;
-
-	pde->proc_fops = &proc_ops;
-	pde->data = isp116x;
-	isp116x->pde = pde;
+	isp116x->dentry = debugfs_create_file(hcd_name,
+					      S_IRUGO, NULL, isp116x,
+					      &isp116x_debug_fops);
+	if (!isp116x->dentry)
+		return -ENOMEM;
+	return 0;
 }
 
 static void remove_debug_file(struct isp116x *isp116x)
 {
-	if (isp116x->pde)
-		remove_proc_entry(proc_filename, NULL);
+	debugfs_remove(isp116x->dentry);
 }
 
-#endif
+#else
+
+#define	create_debug_file(d)	0
+#define	remove_debug_file(d)	do{}while(0)
+
+#endif				/* CONFIG_DEBUG_FS */
 
 /*-----------------------------------------------------------------*/
 
@@ -1466,7 +1270,7 @@ static int isp116x_reset(struct usb_hcd *hcd)
 	struct isp116x *isp116x = hcd_to_isp116x(hcd);
 	unsigned long t;
 	u16 clkrdy = 0;
-	int ret = 0, timeout = 15 /* ms */ ;
+	int ret, timeout = 15 /* ms */ ;
 
 	ret = isp116x_sw_reset(isp116x);
 	if (ret)
@@ -1482,7 +1286,7 @@ static int isp116x_reset(struct usb_hcd *hcd)
 			break;
 	}
 	if (!clkrdy) {
-		ERR("Clock not ready after 20ms\n");
+		ERR("Clock not ready after %dms\n", timeout);
 		/* After sw_reset the clock won't report to be ready, if
 		   H_WAKEUP pin is high. */
 		ERR("Please make sure that the H_WAKEUP pin is pulled low!\n");
@@ -1572,7 +1376,8 @@ static int isp116x_start(struct usb_hcd *hcd)
 
 	val = 0;
 	if (board->remote_wakeup_enable) {
-		hcd->can_wakeup = 1;
+		if (!device_can_wakeup(hcd->self.controller))
+			device_init_wakeup(hcd->self.controller, 1);
 		val |= RH_HS_DRWE;
 	}
 	isp116x_write_reg32(isp116x, HCRHSTATUS, val);
@@ -1600,12 +1405,126 @@ static int isp116x_start(struct usb_hcd *hcd)
 	isp116x_write_reg32(isp116x, HCRHPORT1, RH_PS_CCS);
 	isp116x_write_reg32(isp116x, HCRHPORT2, RH_PS_CCS);
 
-	isp116x_show_regs(isp116x);
+	isp116x_show_regs_log(isp116x);
 	spin_unlock_irqrestore(&isp116x->lock, flags);
 	return 0;
 }
 
-/*-----------------------------------------------------------------*/
+#ifdef	CONFIG_PM
+
+static int isp116x_bus_suspend(struct usb_hcd *hcd)
+{
+	struct isp116x *isp116x = hcd_to_isp116x(hcd);
+	unsigned long flags;
+	u32 val;
+	int ret = 0;
+
+	spin_lock_irqsave(&isp116x->lock, flags);
+
+	val = isp116x_read_reg32(isp116x, HCCONTROL);
+	switch (val & HCCONTROL_HCFS) {
+	case HCCONTROL_USB_OPER:
+		val &= (~HCCONTROL_HCFS & ~HCCONTROL_RWE);
+		val |= HCCONTROL_USB_SUSPEND;
+		if (device_may_wakeup(&hcd->self.root_hub->dev))
+			val |= HCCONTROL_RWE;
+		/* Wait for usb transfers to finish */
+		mdelay(2);
+		isp116x_write_reg32(isp116x, HCCONTROL, val);
+		/* Wait for devices to suspend */
+		mdelay(5);
+	case HCCONTROL_USB_SUSPEND:
+		break;
+	case HCCONTROL_USB_RESUME:
+		isp116x_write_reg32(isp116x, HCCONTROL,
+				    (val & ~HCCONTROL_HCFS) |
+				    HCCONTROL_USB_RESET);
+	case HCCONTROL_USB_RESET:
+		ret = -EBUSY;
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	spin_unlock_irqrestore(&isp116x->lock, flags);
+	return ret;
+}
+
+static int isp116x_bus_resume(struct usb_hcd *hcd)
+{
+	struct isp116x *isp116x = hcd_to_isp116x(hcd);
+	u32 val;
+
+	msleep(5);
+	spin_lock_irq(&isp116x->lock);
+
+	val = isp116x_read_reg32(isp116x, HCCONTROL);
+	switch (val & HCCONTROL_HCFS) {
+	case HCCONTROL_USB_SUSPEND:
+		val &= ~HCCONTROL_HCFS;
+		val |= HCCONTROL_USB_RESUME;
+		isp116x_write_reg32(isp116x, HCCONTROL, val);
+	case HCCONTROL_USB_RESUME:
+		break;
+	case HCCONTROL_USB_OPER:
+		spin_unlock_irq(&isp116x->lock);
+		/* Without setting power_state here the
+		   SUSPENDED state won't be removed from
+		   sysfs/usbN/power.state as a response to remote
+		   wakeup. Maybe in the future. */
+		hcd->self.root_hub->dev.power.power_state = PMSG_ON;
+		return 0;
+	default:
+		/* HCCONTROL_USB_RESET: this may happen, when during
+		   suspension the HC lost power. Reinitialize completely */
+		spin_unlock_irq(&isp116x->lock);
+		DBG("Chip has been reset while suspended. Reinit from scratch.\n");
+		isp116x_reset(hcd);
+		isp116x_start(hcd);
+		isp116x_hub_control(hcd, SetPortFeature,
+				    USB_PORT_FEAT_POWER, 1, NULL, 0);
+		if ((isp116x->rhdesca & RH_A_NDP) == 2)
+			isp116x_hub_control(hcd, SetPortFeature,
+					    USB_PORT_FEAT_POWER, 2, NULL, 0);
+		hcd->self.root_hub->dev.power.power_state = PMSG_ON;
+		return 0;
+	}
+
+	val = isp116x->rhdesca & RH_A_NDP;
+	while (val--) {
+		u32 stat =
+		    isp116x_read_reg32(isp116x, val ? HCRHPORT2 : HCRHPORT1);
+		/* force global, not selective, resume */
+		if (!(stat & RH_PS_PSS))
+			continue;
+		DBG("%s: Resuming port %d\n", __func__, val);
+		isp116x_write_reg32(isp116x, RH_PS_POCI, val
+				    ? HCRHPORT2 : HCRHPORT1);
+	}
+	spin_unlock_irq(&isp116x->lock);
+
+	hcd->state = HC_STATE_RESUMING;
+	msleep(20);
+
+	/* Go operational */
+	spin_lock_irq(&isp116x->lock);
+	val = isp116x_read_reg32(isp116x, HCCONTROL);
+	isp116x_write_reg32(isp116x, HCCONTROL,
+			    (val & ~HCCONTROL_HCFS) | HCCONTROL_USB_OPER);
+	spin_unlock_irq(&isp116x->lock);
+	/* see analogous comment above */
+	hcd->self.root_hub->dev.power.power_state = PMSG_ON;
+	hcd->state = HC_STATE_RUNNING;
+
+	return 0;
+}
+
+#else
+
+#define	isp116x_bus_suspend	NULL
+#define	isp116x_bus_resume	NULL
+
+#endif
 
 static struct hc_driver isp116x_hc_driver = {
 	.description = hcd_name,
@@ -1735,12 +1654,19 @@ static int __init isp116x_probe(struct platform_device *pdev)
 	}
 
 	ret = usb_add_hcd(hcd, irq, SA_INTERRUPT);
-	if (ret != 0)
+	if (ret)
 		goto err6;
 
-	create_debug_file(isp116x);
+	ret = create_debug_file(isp116x);
+	if (ret) {
+		ERR("Couldn't create debugfs entry\n");
+		goto err7;
+	}
+
 	return 0;
 
+      err7:
+	usb_remove_hcd(hcd);
       err6:
 	usb_put_hcd(hcd);
       err5:
@@ -1762,13 +1688,9 @@ static int __init isp116x_probe(struct platform_device *pdev)
 */
 static int isp116x_suspend(struct platform_device *dev, pm_message_t state)
 {
-	int ret = 0;
-
-	VDBG("%s: state %x\n", __func__, state);
-
+	VDBG("%s: state %x\n", __func__, state.event);
 	dev->dev.power.power_state = state;
-
-	return ret;
+	return 0;
 }
 
 /*
@@ -1776,13 +1698,9 @@ static int isp116x_suspend(struct platform_device *dev, pm_message_t state)
 */
 static int isp116x_resume(struct platform_device *dev)
 {
-	int ret = 0;
-
-	VDBG("%s:  state %x\n", __func__, dev->dev.power.power_state);
-
+	VDBG("%s:  state %x\n", __func__, dev->power.power_state.event);
 	dev->dev.power.power_state = PMSG_ON;
-
-	return ret;
+	return 0;
 }
 
 #else
diff --git a/drivers/usb/host/isp116x.h b/drivers/usb/host/isp116x.h
index c6fec96785fe..a1b7c3813d3a 100644
--- a/drivers/usb/host/isp116x.h
+++ b/drivers/usb/host/isp116x.h
@@ -259,7 +259,7 @@ struct isp116x {
 
 	struct isp116x_platform_data *board;
 
-	struct proc_dir_entry *pde;
+	struct dentry *dentry;
 	unsigned long stat1, stat2, stat4, stat8, stat16;
 
 	/* HC registers */
@@ -450,7 +450,7 @@ static void isp116x_write_reg32(struct isp116x *isp116x, unsigned reg,
 	isp116x_write_data32(isp116x, (u32) val);
 }
 
-#define isp116x_show_reg(d,r) {					\
+#define isp116x_show_reg_log(d,r,s) {				\
 	if ((r) < 0x20) {			                \
 		DBG("%-12s[%02x]: %08x\n", #r,			\
 			r, isp116x_read_reg32(d, r));		\
@@ -459,35 +459,60 @@ static void isp116x_write_reg32(struct isp116x *isp116x, unsigned reg,
 			r, isp116x_read_reg16(d, r));	    	\
 	}							\
 }
+#define isp116x_show_reg_seq(d,r,s) {				\
+	if ((r) < 0x20) {					\
+		seq_printf(s, "%-12s[%02x]: %08x\n", #r,	\
+			r, isp116x_read_reg32(d, r));		\
+	} else {						\
+		seq_printf(s, "%-12s[%02x]:     %04x\n", #r,	\
+			r, isp116x_read_reg16(d, r));		\
+	}							\
+}
 
-static inline void isp116x_show_regs(struct isp116x *isp116x)
+#define isp116x_show_regs(d,type,s) {			\
+	isp116x_show_reg_##type(d, HCREVISION, s);	\
+	isp116x_show_reg_##type(d, HCCONTROL, s);	\
+	isp116x_show_reg_##type(d, HCCMDSTAT, s);	\
+	isp116x_show_reg_##type(d, HCINTSTAT, s);	\
+	isp116x_show_reg_##type(d, HCINTENB, s);	\
+	isp116x_show_reg_##type(d, HCFMINTVL, s);	\
+	isp116x_show_reg_##type(d, HCFMREM, s);		\
+	isp116x_show_reg_##type(d, HCFMNUM, s);		\
+	isp116x_show_reg_##type(d, HCLSTHRESH, s);	\
+	isp116x_show_reg_##type(d, HCRHDESCA, s);	\
+	isp116x_show_reg_##type(d, HCRHDESCB, s);	\
+	isp116x_show_reg_##type(d, HCRHSTATUS, s);	\
+	isp116x_show_reg_##type(d, HCRHPORT1, s);	\
+	isp116x_show_reg_##type(d, HCRHPORT2, s);	\
+	isp116x_show_reg_##type(d, HCHWCFG, s);		\
+	isp116x_show_reg_##type(d, HCDMACFG, s);	\
+	isp116x_show_reg_##type(d, HCXFERCTR, s);	\
+	isp116x_show_reg_##type(d, HCuPINT, s);		\
+	isp116x_show_reg_##type(d, HCuPINTENB, s);	\
+	isp116x_show_reg_##type(d, HCCHIPID, s);	\
+	isp116x_show_reg_##type(d, HCSCRATCH, s);	\
+	isp116x_show_reg_##type(d, HCITLBUFLEN, s);	\
+	isp116x_show_reg_##type(d, HCATLBUFLEN, s);	\
+	isp116x_show_reg_##type(d, HCBUFSTAT, s);	\
+	isp116x_show_reg_##type(d, HCRDITL0LEN, s);	\
+	isp116x_show_reg_##type(d, HCRDITL1LEN, s);	\
+}
+
+/*
+   Dump registers for debugfs.
+*/
+static inline void isp116x_show_regs_seq(struct isp116x *isp116x,
+					  struct seq_file *s)
+{
+	isp116x_show_regs(isp116x, seq, s);
+}
+
+/*
+   Dump registers to syslog.
+*/
+static inline void isp116x_show_regs_log(struct isp116x *isp116x)
 {
-	isp116x_show_reg(isp116x, HCREVISION);
-	isp116x_show_reg(isp116x, HCCONTROL);
-	isp116x_show_reg(isp116x, HCCMDSTAT);
-	isp116x_show_reg(isp116x, HCINTSTAT);
-	isp116x_show_reg(isp116x, HCINTENB);
-	isp116x_show_reg(isp116x, HCFMINTVL);
-	isp116x_show_reg(isp116x, HCFMREM);
-	isp116x_show_reg(isp116x, HCFMNUM);
-	isp116x_show_reg(isp116x, HCLSTHRESH);
-	isp116x_show_reg(isp116x, HCRHDESCA);
-	isp116x_show_reg(isp116x, HCRHDESCB);
-	isp116x_show_reg(isp116x, HCRHSTATUS);
-	isp116x_show_reg(isp116x, HCRHPORT1);
-	isp116x_show_reg(isp116x, HCRHPORT2);
-	isp116x_show_reg(isp116x, HCHWCFG);
-	isp116x_show_reg(isp116x, HCDMACFG);
-	isp116x_show_reg(isp116x, HCXFERCTR);
-	isp116x_show_reg(isp116x, HCuPINT);
-	isp116x_show_reg(isp116x, HCuPINTENB);
-	isp116x_show_reg(isp116x, HCCHIPID);
-	isp116x_show_reg(isp116x, HCSCRATCH);
-	isp116x_show_reg(isp116x, HCITLBUFLEN);
-	isp116x_show_reg(isp116x, HCATLBUFLEN);
-	isp116x_show_reg(isp116x, HCBUFSTAT);
-	isp116x_show_reg(isp116x, HCRDITL0LEN);
-	isp116x_show_reg(isp116x, HCRDITL1LEN);
+	isp116x_show_regs(isp116x, log, NULL);
 }
 
 #if defined(URB_TRACE)
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index bf1d9abc07ac..a4b12404ae08 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -75,13 +75,6 @@
  */
  
 #include <linux/config.h>
-
-#ifdef CONFIG_USB_DEBUG
-#	define DEBUG
-#else
-#	undef DEBUG
-#endif
-
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/pci.h>
@@ -802,7 +795,6 @@ static int ohci_restart (struct ohci_hcd *ohci)
 	int temp;
 	int i;
 	struct urb_priv *priv;
-	struct usb_device *root = ohci_to_hcd(ohci)->self.root_hub;
 
 	/* mark any devices gone, so they do nothing till khubd disconnects.
 	 * recycle any "live" eds/tds (and urbs) right away.
@@ -811,11 +803,7 @@ static int ohci_restart (struct ohci_hcd *ohci)
 	 */ 
 	spin_lock_irq(&ohci->lock);
 	disable (ohci);
-	for (i = 0; i < root->maxchild; i++) {
-		if (root->children [i])
-			usb_set_device_state (root->children[i],
-				USB_STATE_NOTATTACHED);
-	}
+	usb_root_hub_lost_power(ohci_to_hcd(ohci)->self.root_hub);
 	if (!list_empty (&ohci->pending))
 		ohci_dbg(ohci, "abort schedule...\n");
 	list_for_each_entry (priv, &ohci->pending, pending) {
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index 72e3b12a1926..4b2226d77b34 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -372,7 +372,7 @@ done:
 					& ohci->hc_control)
 				== OHCI_USB_OPER
 			&& time_after (jiffies, ohci->next_statechange)
-			&& usb_trylock_device (hcd->self.root_hub)
+			&& usb_trylock_device (hcd->self.root_hub) == 0
 			) {
 		ohci_vdbg (ohci, "autosuspend\n");
 		(void) ohci_bus_suspend (hcd);
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
index 9d65ec307990..acde8868da21 100644
--- a/drivers/usb/host/ohci-pxa27x.c
+++ b/drivers/usb/host/ohci-pxa27x.c
@@ -26,18 +26,12 @@
 #include <asm/mach-types.h>
 #include <asm/hardware.h>
 #include <asm/arch/pxa-regs.h>
-
-
-#define PMM_NPS_MODE           1
-#define PMM_GLOBAL_MODE        2
-#define PMM_PERPORT_MODE       3
+#include <asm/arch/ohci.h>
 
 #define PXA_UHC_MAX_PORTNUM    3
 
 #define UHCRHPS(x)              __REG2( 0x4C000050, (x)<<2 )
 
-static int pxa27x_ohci_pmm_state;
-
 /*
   PMM_NPS_MODE -- PMM Non-power switching mode
       Ports are powered continuously.
@@ -50,8 +44,6 @@ static int pxa27x_ohci_pmm_state;
  */
 static int pxa27x_ohci_select_pmm( int mode )
 {
-	pxa27x_ohci_pmm_state = mode;
-
 	switch ( mode ) {
 	case PMM_NPS_MODE:
 		UHCRHDA |= RH_A_NPS;
@@ -71,7 +63,6 @@ static int pxa27x_ohci_select_pmm( int mode )
 			"Invalid mode %d, set to non-power switch mode.\n", 
 			mode );
 
-		pxa27x_ohci_pmm_state = PMM_NPS_MODE;
 		UHCRHDA |= RH_A_NPS;
 	}
 
@@ -82,8 +73,13 @@ extern int usb_disabled(void);
 
 /*-------------------------------------------------------------------------*/
 
-static void pxa27x_start_hc(struct platform_device *dev)
+static int pxa27x_start_hc(struct device *dev)
 {
+	int retval = 0;
+	struct pxaohci_platform_data *inf;
+
+	inf = dev->platform_data;
+
 	pxa_set_cken(CKEN10_USBHOST, 1);
 
 	UHCHR |= UHCHR_FHR;
@@ -94,21 +90,11 @@ static void pxa27x_start_hc(struct platform_device *dev)
 	while (UHCHR & UHCHR_FSBIR)
 		cpu_relax();
 
-	/* This could be properly abstracted away through the
-	   device data the day more machines are supported and
-	   their differences can be figured out correctly. */
-	if (machine_is_mainstone()) {
-		/* setup Port1 GPIO pin. */
-		pxa_gpio_mode( 88 | GPIO_ALT_FN_1_IN);	/* USBHPWR1 */
-		pxa_gpio_mode( 89 | GPIO_ALT_FN_2_OUT);	/* USBHPEN1 */
-
-		/* Set the Power Control Polarity Low and Power Sense
-		   Polarity Low to active low. Supply power to USB ports. */
-		UHCHR = (UHCHR | UHCHR_PCPL | UHCHR_PSPL) &
-			~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSEP3 | UHCHR_SSE);
+	if (inf->init)
+		retval = inf->init(dev);
 
-		pxa27x_ohci_pmm_state = PMM_PERPORT_MODE;
-	}
+	if (retval < 0)
+		return retval;
 
 	UHCHR &= ~UHCHR_SSE;
 
@@ -117,10 +103,19 @@ static void pxa27x_start_hc(struct platform_device *dev)
 	/* Clear any OTG Pin Hold */
 	if (PSSR & PSSR_OTGPH)
 		PSSR |= PSSR_OTGPH;
+
+	return 0;
 }
 
-static void pxa27x_stop_hc(struct platform_device *dev)
+static void pxa27x_stop_hc(struct device *dev)
 {
+	struct pxaohci_platform_data *inf;
+
+	inf = dev->platform_data;
+
+	if (inf->exit)
+		inf->exit(dev);
+
 	UHCHR |= UHCHR_FHR;
 	udelay(11);
 	UHCHR &= ~UHCHR_FHR;
@@ -147,22 +142,27 @@ static void pxa27x_stop_hc(struct platform_device *dev)
  * through the hotplug entry's driver_data.
  *
  */
-int usb_hcd_pxa27x_probe (const struct hc_driver *driver,
-			  struct platform_device *dev)
+int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device *pdev)
 {
 	int retval;
 	struct usb_hcd *hcd;
+	struct pxaohci_platform_data *inf;
 
-	if (dev->resource[1].flags != IORESOURCE_IRQ) {
+	inf = pdev->dev.platform_data;
+
+	if (!inf)
+		return -ENODEV;
+
+	if (pdev->resource[1].flags != IORESOURCE_IRQ) {
 		pr_debug ("resource[1] is not IORESOURCE_IRQ");
 		return -ENOMEM;
 	}
 
-	hcd = usb_create_hcd (driver, &dev->dev, "pxa27x");
+	hcd = usb_create_hcd (driver, &pdev->dev, "pxa27x");
 	if (!hcd)
 		return -ENOMEM;
-	hcd->rsrc_start = dev->resource[0].start;
-	hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1;
+	hcd->rsrc_start = pdev->resource[0].start;
+	hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1;
 
 	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
 		pr_debug("request_mem_region failed");
@@ -177,18 +177,22 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver,
 		goto err2;
 	}
 
-	pxa27x_start_hc(dev);
+	if ((retval = pxa27x_start_hc(&pdev->dev)) < 0) {
+		pr_debug("pxa27x_start_hc failed");
+		goto err3;
+	}
 
 	/* Select Power Management Mode */
-	pxa27x_ohci_select_pmm(pxa27x_ohci_pmm_state);
+	pxa27x_ohci_select_pmm(inf->port_mode);
 
 	ohci_hcd_init(hcd_to_ohci(hcd));
 
-	retval = usb_add_hcd(hcd, dev->resource[1].start, SA_INTERRUPT);
+	retval = usb_add_hcd(hcd, pdev->resource[1].start, SA_INTERRUPT);
 	if (retval == 0)
 		return retval;
 
-	pxa27x_stop_hc(dev);
+	pxa27x_stop_hc(&pdev->dev);
+ err3:
 	iounmap(hcd->regs);
  err2:
 	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
@@ -211,10 +215,10 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver,
  * context, normally "rmmod", "apmd", or something similar.
  *
  */
-void usb_hcd_pxa27x_remove (struct usb_hcd *hcd, struct platform_device *dev)
+void usb_hcd_pxa27x_remove (struct usb_hcd *hcd, struct platform_device *pdev)
 {
 	usb_remove_hcd(hcd);
-	pxa27x_stop_hc(dev);
+	pxa27x_stop_hc(&pdev->dev);
 	iounmap(hcd->regs);
 	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 	usb_put_hcd(hcd);
@@ -292,15 +296,12 @@ static const struct hc_driver ohci_pxa27x_hc_driver = {
 
 static int ohci_hcd_pxa27x_drv_probe(struct platform_device *pdev)
 {
-	int ret;
-
 	pr_debug ("In ohci_hcd_pxa27x_drv_probe");
 
 	if (usb_disabled())
 		return -ENODEV;
 
-	ret = usb_hcd_pxa27x_probe(&ohci_pxa27x_hc_driver, pdev);
-	return ret;
+	return usb_hcd_pxa27x_probe(&ohci_pxa27x_hc_driver, pdev);
 }
 
 static int ohci_hcd_pxa27x_drv_remove(struct platform_device *pdev)
@@ -308,31 +309,55 @@ static int ohci_hcd_pxa27x_drv_remove(struct platform_device *pdev)
 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
 
 	usb_hcd_pxa27x_remove(hcd, pdev);
+	platform_set_drvdata(pdev, NULL);
 	return 0;
 }
 
-static int ohci_hcd_pxa27x_drv_suspend(struct platform_device *dev, pm_message_t state)
+#ifdef	CONFIG_PM
+static int ohci_hcd_pxa27x_drv_suspend(struct platform_device *pdev, pm_message_t state)
 {
-//	struct usb_hcd *hcd = platform_get_drvdata(dev);
-	printk("%s: not implemented yet\n", __FUNCTION__);
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+
+	if (time_before(jiffies, ohci->next_statechange))
+		msleep(5);
+	ohci->next_statechange = jiffies;
+
+	pxa27x_stop_hc(&pdev->dev);
+	hcd->state = HC_STATE_SUSPENDED;
+	pdev->dev.power.power_state = PMSG_SUSPEND;
 
 	return 0;
 }
 
-static int ohci_hcd_pxa27x_drv_resume(struct platform_device *dev)
+static int ohci_hcd_pxa27x_drv_resume(struct platform_device *pdev)
 {
-//	struct usb_hcd *hcd = platform_get_drvdata(dev);
-	printk("%s: not implemented yet\n", __FUNCTION__);
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+	int status;
+
+	if (time_before(jiffies, ohci->next_statechange))
+		msleep(5);
+	ohci->next_statechange = jiffies;
+
+	if ((status = pxa27x_start_hc(&pdev->dev)) < 0)
+		return status;
+
+	pdev->dev.power.power_state = PMSG_ON;
+	usb_hcd_resume_root_hub(hcd);
 
 	return 0;
 }
+#endif
 
 
 static struct platform_driver ohci_hcd_pxa27x_driver = {
 	.probe		= ohci_hcd_pxa27x_drv_probe,
 	.remove		= ohci_hcd_pxa27x_drv_remove,
+#ifdef CONFIG_PM
 	.suspend	= ohci_hcd_pxa27x_drv_suspend, 
 	.resume		= ohci_hcd_pxa27x_drv_resume,
+#endif
 	.driver		= {
 		.name	= "pxa27x-ohci",
 	},
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index e46528c825bf..3ef2c0cdf1db 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -9,12 +9,6 @@
  */
 
 #include <linux/config.h>
-#ifdef CONFIG_USB_DEBUG
-#define DEBUG
-#else
-#undef DEBUG
-#endif
-
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index a7722a6a5a5b..517360b77d8e 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -32,13 +32,6 @@
 #undef	PACKET_TRACE
 
 #include <linux/config.h>
-
-#ifdef CONFIG_USB_DEBUG
-#	define DEBUG
-#else
-#	undef DEBUG
-#endif
-
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
@@ -1581,7 +1574,9 @@ sl811h_start(struct usb_hcd *hcd)
 	hcd->state = HC_STATE_RUNNING;
 
 	if (sl811->board) {
-		hcd->can_wakeup = sl811->board->can_wakeup;
+		if (!device_can_wakeup(hcd->self.controller))
+			device_init_wakeup(hcd->self.controller,
+				sl811->board->can_wakeup);
 		hcd->power_budget = sl811->board->power * 2;
 	}
 
@@ -1805,9 +1800,10 @@ sl811h_resume(struct platform_device *dev)
 	 * let's assume it'd only be powered to enable remote wakeup.
 	 */
 	if (dev->dev.power.power_state.event == PM_EVENT_SUSPEND
-			|| !hcd->can_wakeup) {
+			|| !device_can_wakeup(&hcd->self.root_hub->dev)) {
 		sl811->port1 = 0;
 		port_power(sl811, 1);
+		usb_root_hub_lost_power(hcd->self.root_hub);
 		return 0;
 	}
 
diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c
index e73faf831b24..466384d7c79f 100644
--- a/drivers/usb/host/sl811_cs.c
+++ b/drivers/usb/host/sl811_cs.c
@@ -38,7 +38,7 @@ MODULE_LICENSE("GPL");
 /* MACROS                                                             */
 /*====================================================================*/
 
-#if defined(DEBUG) || defined(CONFIG_USB_DEBUG) || defined(PCMCIA_DEBUG)
+#if defined(DEBUG) || defined(PCMCIA_DEBUG)
 
 static int pc_debug = 0;
 module_param(pc_debug, int, 0644);
@@ -66,13 +66,13 @@ module_param(pc_debug, int, 0644);
 
 static const char driver_name[DEV_NAME_LEN]  = "sl811_cs";
 
-static dev_link_t *dev_list = NULL;
-
 typedef struct local_info_t {
 	dev_link_t		link;
 	dev_node_t		node;
 } local_info_t;
 
+static void sl811_cs_release(dev_link_t * link);
+
 /*====================================================================*/
 
 static void release_platform_dev(struct device * dev)
@@ -129,7 +129,8 @@ static int sl811_hc_init(struct device *parent, ioaddr_t base_addr, int irq)
 	resources[2].end   = base_addr + 1;
 
 	/* The driver core will probe for us.  We know sl811-hcd has been
-	 * initialized already because of the link order dependency.
+	 * initialized already because of the link order dependency created
+	 * by referencing "sl811h_driver".
 	 */
 	platform_dev.name = sl811h_driver.name;
 	return platform_device_register(&platform_dev);
@@ -137,26 +138,16 @@ static int sl811_hc_init(struct device *parent, ioaddr_t base_addr, int irq)
 
 /*====================================================================*/
 
-static void sl811_cs_detach(dev_link_t *link)
+static void sl811_cs_detach(struct pcmcia_device *p_dev)
 {
-	dev_link_t **linkp;
+	dev_link_t *link = dev_to_instance(p_dev);
 
 	DBG(0, "sl811_cs_detach(0x%p)\n", link);
 
-	/* Locate device structure */
-	for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) {
-		if (*linkp == link)
-			break;
-	}
-	if (*linkp == NULL)
-		return;
-
-	/* Break the link with Card Services */
-	if (link->handle)
-		pcmcia_deregister_client(link->handle);
+	link->state &= ~DEV_PRESENT;
+	if (link->state & DEV_CONFIG)
+		sl811_cs_release(link);
 
-	/* Unlink device structure, and free it */
-	*linkp = link->next;
 	/* This points to the parent local_info_t struct */
 	kfree(link->priv);
 }
@@ -166,13 +157,6 @@ static void sl811_cs_release(dev_link_t * link)
 
 	DBG(0, "sl811_cs_release(0x%p)\n", link);
 
-	if (link->open) {
-		DBG(1, "sl811_cs: release postponed, '%s' still open\n",
-		    link->dev->dev_name);
-		link->state |= DEV_STALE_CONFIG;
-		return;
-	}
-
 	/* Unlink the device chain */
 	link->dev = NULL;
 
@@ -183,9 +167,6 @@ static void sl811_cs_release(dev_link_t * link)
 	if (link->irq.AssignedIRQ)
 		pcmcia_release_irq(link->handle, &link->irq);
 	link->state &= ~DEV_CONFIG;
-
-	if (link->state & DEV_STALE_LINK)
-		sl811_cs_detach(link);
 }
 
 static void sl811_cs_config(dev_link_t *link)
@@ -322,55 +303,36 @@ cs_failed:
 	}
 }
 
-static int
-sl811_cs_event(event_t event, int priority, event_callback_args_t *args)
+static int sl811_suspend(struct pcmcia_device *dev)
 {
-	dev_link_t *link = args->client_data;
+	dev_link_t *link = dev_to_instance(dev);
 
-	DBG(1, "sl811_cs_event(0x%06x)\n", event);
+	link->state |= DEV_SUSPEND;
+	if (link->state & DEV_CONFIG)
+		pcmcia_release_configuration(link->handle);
 
-	switch (event) {
-	case CS_EVENT_CARD_REMOVAL:
-		link->state &= ~DEV_PRESENT;
-		if (link->state & DEV_CONFIG)
-			sl811_cs_release(link);
-		break;
+	return 0;
+}
 
-	case CS_EVENT_CARD_INSERTION:
-		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-		sl811_cs_config(link);
-		break;
+static int sl811_resume(struct pcmcia_device *dev)
+{
+	dev_link_t *link = dev_to_instance(dev);
 
-	case CS_EVENT_PM_SUSPEND:
-		link->state |= DEV_SUSPEND;
-		/* Fall through... */
-	case CS_EVENT_RESET_PHYSICAL:
-		if (link->state & DEV_CONFIG)
-			pcmcia_release_configuration(link->handle);
-		break;
+	link->state &= ~DEV_SUSPEND;
+	if (link->state & DEV_CONFIG)
+		pcmcia_request_configuration(link->handle, &link->conf);
 
-	case CS_EVENT_PM_RESUME:
-		link->state &= ~DEV_SUSPEND;
-		/* Fall through... */
-	case CS_EVENT_CARD_RESET:
-		if (link->state & DEV_CONFIG)
-			pcmcia_request_configuration(link->handle, &link->conf);
-		DBG(0, "reset sl811-hcd here?\n");
-		break;
-	}
 	return 0;
 }
 
-static dev_link_t *sl811_cs_attach(void)
+static int sl811_cs_attach(struct pcmcia_device *p_dev)
 {
 	local_info_t *local;
 	dev_link_t *link;
-	client_reg_t client_reg;
-	int ret;
 
 	local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
 	if (!local)
-		return NULL;
+		return -ENOMEM;
 	memset(local, 0, sizeof(local_info_t));
 	link = &local->link;
 	link->priv = local;
@@ -384,21 +346,13 @@ static dev_link_t *sl811_cs_attach(void)
 	link->conf.Vcc = 33;
 	link->conf.IntType = INT_MEMORY_AND_IO;
 
-	/* Register with Card Services */
-	link->next = dev_list;
-	dev_list = link;
-	client_reg.dev_info = (dev_info_t *) &driver_name;
-	client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
-	client_reg.Version = 0x0210;
-	client_reg.event_callback_args.client_data = link;
-	ret = pcmcia_register_client(&link->handle, &client_reg);
-	if (ret != CS_SUCCESS) {
-		cs_error(link->handle, RegisterClient, ret);
-		sl811_cs_detach(link);
-		return NULL;
-	}
+	link->handle = p_dev;
+	p_dev->instance = link;
 
-	return link;
+	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+	sl811_cs_config(link);
+
+	return 0;
 }
 
 static struct pcmcia_device_id sl811_ids[] = {
@@ -412,10 +366,11 @@ static struct pcmcia_driver sl811_cs_driver = {
 	.drv		= {
 		.name	= (char *)driver_name,
 	},
-	.attach		= sl811_cs_attach,
-	.event		= sl811_cs_event,
-	.detach		= sl811_cs_detach,
+	.probe		= sl811_cs_attach,
+	.remove		= sl811_cs_detach,
 	.id_table	= sl811_ids,
+	.suspend	= sl811_suspend,
+	.resume		= sl811_resume,
 };
 
 /*====================================================================*/
diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
index 151154df37fa..5832953086f8 100644
--- a/drivers/usb/host/uhci-debug.c
+++ b/drivers/usb/host/uhci-debug.c
@@ -2,8 +2,8 @@
  * UHCI-specific debugging code. Invaluable when something
  * goes wrong, but don't get in my face.
  *
- * Kernel visible pointers are surrounded in []'s and bus
- * visible pointers are surrounded in ()'s
+ * Kernel visible pointers are surrounded in []s and bus
+ * visible pointers are surrounded in ()s
  *
  * (C) Copyright 1999 Linus Torvalds
  * (C) Copyright 1999-2001 Johannes Erdfelt
@@ -19,7 +19,7 @@
 
 static struct dentry *uhci_debugfs_root = NULL;
 
-/* Handle REALLY large printk's so we don't overflow buffers */
+/* Handle REALLY large printks so we don't overflow buffers */
 static inline void lprintk(char *buf)
 {
 	char *p;
@@ -160,7 +160,7 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
 			}
 
 			if (active && ni > i) {
-				out += sprintf(out, "%*s[skipped %d active TD's]\n", space, "", ni - i);
+				out += sprintf(out, "%*s[skipped %d active TDs]\n", space, "", ni - i);
 				tmp = ntmp;
 				td = ntd;
 				i = ni;
@@ -173,7 +173,7 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
 	if (list_empty(&urbp->queue_list) || urbp->queued)
 		goto out;
 
-	out += sprintf(out, "%*sQueued QH's:\n", -space, "--");
+	out += sprintf(out, "%*sQueued QHs:\n", -space, "--");
 
 	head = &urbp->queue_list;
 	tmp = head->next;
@@ -197,7 +197,7 @@ out:
 	}
 
 #ifdef CONFIG_PROC_FS
-static const char *qh_names[] = {
+static const char * const qh_names[] = {
   "skel_int128_qh", "skel_int64_qh",
   "skel_int32_qh", "skel_int16_qh",
   "skel_int8_qh", "skel_int4_qh",
@@ -464,7 +464,7 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
 		} while (tmp != head);
 	}
 
-	out += sprintf(out, "Skeleton QH's\n");
+	out += sprintf(out, "Skeleton QHs\n");
 
 	for (i = 0; i < UHCI_NUM_SKELQH; ++i) {
 		int shown = 0;
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 79efaf7d86a3..dfe121d35887 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -23,11 +23,6 @@
  */
 
 #include <linux/config.h>
-#ifdef CONFIG_USB_DEBUG
-#define DEBUG
-#else
-#undef DEBUG
-#endif
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/kernel.h>
@@ -67,10 +62,10 @@ Alan Stern"
 
 /*
  * debug = 0, no debugging messages
- * debug = 1, dump failed URB's except for stalls
- * debug = 2, dump all failed URB's (including stalls)
+ * debug = 1, dump failed URBs except for stalls
+ * debug = 2, dump all failed URBs (including stalls)
  *            show all queues in /debug/uhci/[pci_addr]
- * debug = 3, show all TD's in URB's when dumping
+ * debug = 3, show all TDs in URBs when dumping
  */
 #ifdef DEBUG
 static int debug = 1;
@@ -93,7 +88,7 @@ static void uhci_get_current_frame_number(struct uhci_hcd *uhci);
 #define FSBR_DELAY	msecs_to_jiffies(50)
 
 /* When we timeout an idle transfer for FSBR, we'll switch it over to */
-/* depth first traversal. We'll do it in groups of this number of TD's */
+/* depth first traversal. We'll do it in groups of this number of TDs */
 /* to make sure it doesn't hog all of the bandwidth */
 #define DEPTH_INTERVAL 5
 
@@ -478,8 +473,6 @@ static int uhci_start(struct usb_hcd *hcd)
 	struct dentry *dentry;
 
 	hcd->uses_new_polling = 1;
-	if (pci_find_capability(to_pci_dev(uhci_dev(uhci)), PCI_CAP_ID_PM))
-		hcd->can_wakeup = 1;		/* Assume it supports PME# */
 
 	dentry = debugfs_create_file(hcd->self.bus_name,
 			S_IFREG|S_IRUGO|S_IWUSR, uhci_debugfs_root, uhci,
@@ -573,7 +566,7 @@ static int uhci_start(struct usb_hcd *hcd)
 	uhci->skel_bulk_qh->link = cpu_to_le32(uhci->skel_term_qh->dma_handle) | UHCI_PTR_QH;
 
 	/* This dummy TD is to work around a bug in Intel PIIX controllers */
-	uhci_fill_td(uhci->term_td, 0, (UHCI_NULL_DATA_SIZE << 21) |
+	uhci_fill_td(uhci->term_td, 0, uhci_explen(0) |
 		(0x7f << TD_TOKEN_DEVADDR_SHIFT) | USB_PID_IN, 0);
 	uhci->term_td->link = cpu_to_le32(uhci->term_td->dma_handle);
 
@@ -735,8 +728,9 @@ static int uhci_resume(struct usb_hcd *hcd)
 
 	dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__);
 
-	/* We aren't in D3 state anymore, we do that even if dead as I
-	 * really don't want to keep a stale HCD_FLAG_HW_ACCESSIBLE=0
+	/* Since we aren't in D3 any more, it's safe to set this flag
+	 * even if the controller was dead.  It might not even be dead
+	 * any more, if the firmware or quirks code has reset it.
 	 */
 	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
 	mb();
@@ -755,8 +749,12 @@ static int uhci_resume(struct usb_hcd *hcd)
 	check_and_reset_hc(uhci);
 	configure_hc(uhci);
 
-	if (uhci->rh_state == UHCI_RH_RESET)
+	if (uhci->rh_state == UHCI_RH_RESET) {
+
+		/* The controller had to be reset */
+		usb_root_hub_lost_power(hcd->self.root_hub);
 		suspend_rh(uhci, UHCI_RH_SUSPENDED);
+	}
 
 	spin_unlock_irq(&uhci->lock);
 
@@ -882,7 +880,7 @@ static int __init uhci_hcd_init(void)
 
 init_failed:
 	if (kmem_cache_destroy(uhci_up_cachep))
-		warn("not all urb_priv's were freed!");
+		warn("not all urb_privs were freed!");
 
 up_failed:
 	debugfs_remove(uhci_debugfs_root);
@@ -900,7 +898,7 @@ static void __exit uhci_hcd_cleanup(void)
 	pci_unregister_driver(&uhci_pci_driver);
 	
 	if (kmem_cache_destroy(uhci_up_cachep))
-		warn("not all urb_priv's were freed!");
+		warn("not all urb_privs were freed!");
 
 	debugfs_remove(uhci_debugfs_root);
 	kfree(errbuf);
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
index e576db57a926..8b4b887a7d41 100644
--- a/drivers/usb/host/uhci-hcd.h
+++ b/drivers/usb/host/uhci-hcd.h
@@ -71,8 +71,6 @@
 #define   USBLEGSUP_RWC		0x8f00	/* the R/WC bits */
 #define   USBLEGSUP_RO		0x5040	/* R/O and reserved bits */
 
-#define UHCI_NULL_DATA_SIZE	0x7FF	/* for UHCI controller TD */
-
 #define UHCI_PTR_BITS		cpu_to_le32(0x000F)
 #define UHCI_PTR_TERM		cpu_to_le32(0x0001)
 #define UHCI_PTR_QH		cpu_to_le32(0x0002)
@@ -168,9 +166,11 @@ static __le32 inline qh_element(struct uhci_qh *qh) {
 #define TD_TOKEN_EXPLEN_MASK	0x7FF		/* expected length, encoded as n - 1 */
 #define TD_TOKEN_PID_MASK	0xFF
 
-#define uhci_explen(len)	((len) << TD_TOKEN_EXPLEN_SHIFT)
+#define uhci_explen(len)	((((len) - 1) & TD_TOKEN_EXPLEN_MASK) << \
+					TD_TOKEN_EXPLEN_SHIFT)
 
-#define uhci_expected_length(token) ((((token) >> 21) + 1) & TD_TOKEN_EXPLEN_MASK)
+#define uhci_expected_length(token) ((((token) >> TD_TOKEN_EXPLEN_SHIFT) + \
+					1) & TD_TOKEN_EXPLEN_MASK)
 #define uhci_toggle(token)	(((token) >> TD_TOKEN_TOGGLE_SHIFT) & 1)
 #define uhci_endpoint(token)	(((token) >> 15) & 0xf)
 #define uhci_devaddr(token)	(((token) >> TD_TOKEN_DEVADDR_SHIFT) & 0x7f)
@@ -223,10 +223,10 @@ static u32 inline td_status(struct uhci_td *td) {
  */
 
 /*
- * The UHCI driver places Interrupt, Control and Bulk into QH's both
- * to group together TD's for one transfer, and also to faciliate queuing
- * of URB's. To make it easy to insert entries into the schedule, we have
- * a skeleton of QH's for each predefined Interrupt latency, low-speed
+ * The UHCI driver places Interrupt, Control and Bulk into QHs both
+ * to group together TDs for one transfer, and also to facilitate queuing
+ * of URBs. To make it easy to insert entries into the schedule, we have
+ * a skeleton of QHs for each predefined Interrupt latency, low-speed
  * control, full-speed control and terminating QH (see explanation for
  * the terminating QH below).
  *
@@ -257,8 +257,8 @@ static u32 inline td_status(struct uhci_td *td) {
  *   reclamation.
  *
  * Isochronous transfers are stored before the start of the skeleton
- * schedule and don't use QH's. While the UHCI spec doesn't forbid the
- * use of QH's for Isochronous, it doesn't use them either. And the spec
+ * schedule and don't use QHs. While the UHCI spec doesn't forbid the
+ * use of QHs for Isochronous, it doesn't use them either. And the spec
  * says that queues never advance on an error completion status, which
  * makes them totally unsuitable for Isochronous transfers.
  */
@@ -359,7 +359,7 @@ struct uhci_hcd {
 	struct dma_pool *td_pool;
 
 	struct uhci_td *term_td;	/* Terminating TD, see UHCI bug */
-	struct uhci_qh *skelqh[UHCI_NUM_SKELQH];	/* Skeleton QH's */
+	struct uhci_qh *skelqh[UHCI_NUM_SKELQH];	/* Skeleton QHs */
 
 	spinlock_t lock;
 
@@ -389,22 +389,22 @@ struct uhci_hcd {
 	unsigned long resuming_ports;
 	unsigned long ports_timeout;		/* Time to stop signalling */
 
-	/* Main list of URB's currently controlled by this HC */
+	/* Main list of URBs currently controlled by this HC */
 	struct list_head urb_list;
 
-	/* List of QH's that are done, but waiting to be unlinked (race) */
+	/* List of QHs that are done, but waiting to be unlinked (race) */
 	struct list_head qh_remove_list;
 	unsigned int qh_remove_age;		/* Age in frames */
 
-	/* List of TD's that are done, but waiting to be freed (race) */
+	/* List of TDs that are done, but waiting to be freed (race) */
 	struct list_head td_remove_list;
 	unsigned int td_remove_age;		/* Age in frames */
 
-	/* List of asynchronously unlinked URB's */
+	/* List of asynchronously unlinked URBs */
 	struct list_head urb_remove_list;
 	unsigned int urb_remove_age;		/* Age in frames */
 
-	/* List of URB's awaiting completion callback */
+	/* List of URBs awaiting completion callback */
 	struct list_head complete_list;
 
 	int rh_numports;			/* Number of root-hub ports */
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index 7e46887d9e12..b6076004a437 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/drivers/usb/host/uhci-q.c
@@ -80,7 +80,7 @@ static inline void uhci_fill_td(struct uhci_td *td, u32 status,
 }
 
 /*
- * We insert Isochronous URB's directly into the frame list at the beginning
+ * We insert Isochronous URBs directly into the frame list at the beginning
  */
 static void uhci_insert_td_frame_list(struct uhci_hcd *uhci, struct uhci_td *td, unsigned framenum)
 {
@@ -369,7 +369,7 @@ static void uhci_append_queued_urb(struct uhci_hcd *uhci, struct urb *eurb, stru
 				uhci_fixup_toggle(urb,
 					uhci_toggle(td_token(lltd)) ^ 1));
 
-	/* All qh's in the queue need to link to the next queue */
+	/* All qhs in the queue need to link to the next queue */
 	urbp->qh->link = eurbp->qh->link;
 
 	wmb();			/* Make sure we flush everything */
@@ -502,7 +502,7 @@ static void uhci_destroy_urb_priv(struct uhci_hcd *uhci, struct urb *urb)
 	}
 
 	/* Check to see if the remove list is empty. Set the IOC bit */
-	/* to force an interrupt so we can remove the TD's*/
+	/* to force an interrupt so we can remove the TDs*/
 	if (list_empty(&uhci->td_remove_list))
 		uhci_set_next_interrupt(uhci);
 
@@ -596,7 +596,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur
 		return -ENOMEM;
 
 	uhci_add_td_to_urb(urb, td);
-	uhci_fill_td(td, status, destination | uhci_explen(7),
+	uhci_fill_td(td, status, destination | uhci_explen(8),
 		urb->setup_dma);
 
 	/*
@@ -612,7 +612,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur
 	}
 
 	/*
-	 * Build the DATA TD's
+	 * Build the DATA TDs
 	 */
 	while (len > 0) {
 		int pktsze = len;
@@ -628,7 +628,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur
 		destination ^= TD_TOKEN_TOGGLE;
 	
 		uhci_add_td_to_urb(urb, td);
-		uhci_fill_td(td, status, destination | uhci_explen(pktsze - 1),
+		uhci_fill_td(td, status, destination | uhci_explen(pktsze),
 			data);
 
 		data += pktsze;
@@ -658,7 +658,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur
 
 	uhci_add_td_to_urb(urb, td);
 	uhci_fill_td(td, status | TD_CTRL_IOC,
-		destination | uhci_explen(UHCI_NULL_DATA_SIZE), 0);
+		destination | uhci_explen(0), 0);
 
 	qh = uhci_alloc_qh(uhci);
 	if (!qh)
@@ -744,7 +744,7 @@ static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb)
 
 	urb->actual_length = 0;
 
-	/* The rest of the TD's (but the last) are data */
+	/* The rest of the TDs (but the last) are data */
 	tmp = tmp->next;
 	while (tmp != head && tmp->next != head) {
 		unsigned int ctrlstat;
@@ -848,7 +848,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb
 		status |= TD_CTRL_SPD;
 
 	/*
-	 * Build the DATA TD's
+	 * Build the DATA TDs
 	 */
 	do {	/* Allow zero length packets */
 		int pktsze = maxsze;
@@ -864,7 +864,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb
 			return -ENOMEM;
 
 		uhci_add_td_to_urb(urb, td);
-		uhci_fill_td(td, status, destination | uhci_explen(pktsze - 1) |
+		uhci_fill_td(td, status, destination | uhci_explen(pktsze) |
 			(usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe),
 			 usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT),
 			data);
@@ -890,7 +890,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb
 			return -ENOMEM;
 
 		uhci_add_td_to_urb(urb, td);
-		uhci_fill_td(td, status, destination | uhci_explen(UHCI_NULL_DATA_SIZE) |
+		uhci_fill_td(td, status, destination | uhci_explen(0) |
 			(usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe),
 			 usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT),
 			data);
@@ -1025,7 +1025,7 @@ static int isochronous_find_limits(struct uhci_hcd *uhci, struct urb *urb, unsig
 	list_for_each_entry(up, &uhci->urb_list, urb_list) {
 		struct urb *u = up->urb;
 
-		/* look for pending URB's with identical pipe handle */
+		/* look for pending URBs with identical pipe handle */
 		if ((urb->pipe == u->pipe) && (urb->dev == u->dev) &&
 		    (u->status == -EINPROGRESS) && (u != urb)) {
 			if (!last_urb)
@@ -1092,7 +1092,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb)
 			return -ENOMEM;
 
 		uhci_add_td_to_urb(urb, td);
-		uhci_fill_td(td, status, destination | uhci_explen(urb->iso_frame_desc[i].length - 1),
+		uhci_fill_td(td, status, destination | uhci_explen(urb->iso_frame_desc[i].length),
 			urb->transfer_dma + urb->iso_frame_desc[i].offset);
 
 		if (i + 1 >= urb->number_of_packets)
@@ -1355,7 +1355,7 @@ static void uhci_unlink_generic(struct uhci_hcd *uhci, struct urb *urb)
 
 	uhci_delete_queued_urb(uhci, urb);
 
-	/* The interrupt loop will reclaim the QH's */
+	/* The interrupt loop will reclaim the QHs */
 	uhci_remove_qh(uhci, urbp->qh);
 	urbp->qh = NULL;
 }
@@ -1413,7 +1413,7 @@ static int uhci_fsbr_timeout(struct uhci_hcd *uhci, struct urb *urb)
 	list_for_each_entry(td, head, list) {
 		/*
 		 * Make sure we don't do the last one (since it'll have the
-		 * TERM bit set) as well as we skip every so many TD's to
+		 * TERM bit set) as well as we skip every so many TDs to
 		 * make sure it doesn't hog the bandwidth
 		 */
 		if (td->list.next != head && (count % DEPTH_INTERVAL) ==
diff --git a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c
index 1d973bcf56aa..049871145d63 100644
--- a/drivers/usb/image/mdc800.c
+++ b/drivers/usb/image/mdc800.c
@@ -962,7 +962,6 @@ MODULE_DEVICE_TABLE (usb, mdc800_table);
  */
 static struct usb_driver mdc800_usb_driver =
 {
-	.owner =	THIS_MODULE,
 	.name =		"mdc800",
 	.probe =	mdc800_usb_probe,
 	.disconnect =	mdc800_usb_disconnect,
diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c
index 950543aa5ac7..458f2acdeb0a 100644
--- a/drivers/usb/image/microtek.c
+++ b/drivers/usb/image/microtek.c
@@ -160,7 +160,6 @@ static void mts_usb_disconnect(struct usb_interface *intf);
 static struct usb_device_id mts_usb_ids [];
 
 static struct usb_driver mts_usb_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"microtekX6",
 	.probe =	mts_usb_probe,
 	.disconnect =	mts_usb_disconnect,
diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig
index 1e53934907c0..509dd0a04c54 100644
--- a/drivers/usb/input/Kconfig
+++ b/drivers/usb/input/Kconfig
@@ -273,6 +273,20 @@ config USB_ATI_REMOTE
 	  To compile this driver as a module, choose M here: the module will be
 	  called ati_remote.
 
+config USB_ATI_REMOTE2
+	tristate "ATI / Philips USB RF remote control"
+	depends on USB && INPUT
+	---help---
+	  Say Y here if you want to use an ATI or Philips USB RF remote control.
+	  These are RF remotes with USB receivers.
+	  ATI Remote Wonder II comes with some ATI's All-In-Wonder video cards
+	  and is also available as a separate product.
+	  This driver provides mouse pointer, left and right mouse buttons,
+	  and maps all the other remote buttons to keypress events.
+
+	  To compile this driver as a module, choose M here: the module will be
+	  called ati_remote2.
+
 config USB_KEYSPAN_REMOTE
 	tristate "Keyspan DMR USB remote control (EXPERIMENTAL)"
 	depends on USB && INPUT && EXPERIMENTAL
diff --git a/drivers/usb/input/Makefile b/drivers/usb/input/Makefile
index 07cb17db42fc..d512d9f488fe 100644
--- a/drivers/usb/input/Makefile
+++ b/drivers/usb/input/Makefile
@@ -28,6 +28,7 @@ endif
 
 obj-$(CONFIG_USB_AIPTEK)	+= aiptek.o
 obj-$(CONFIG_USB_ATI_REMOTE)	+= ati_remote.o
+obj-$(CONFIG_USB_ATI_REMOTE2)	+= ati_remote2.o
 obj-$(CONFIG_USB_HID)		+= usbhid.o
 obj-$(CONFIG_USB_KBD)		+= usbkbd.o
 obj-$(CONFIG_USB_KBTAB)		+= kbtab.o
diff --git a/drivers/usb/input/acecad.c b/drivers/usb/input/acecad.c
index a32558b4048e..df29b8078b54 100644
--- a/drivers/usb/input/acecad.c
+++ b/drivers/usb/input/acecad.c
@@ -261,7 +261,6 @@ static struct usb_device_id usb_acecad_id_table [] = {
 MODULE_DEVICE_TABLE(usb, usb_acecad_id_table);
 
 static struct usb_driver usb_acecad_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"usb_acecad",
 	.probe =	usb_acecad_probe,
 	.disconnect =	usb_acecad_disconnect,
diff --git a/drivers/usb/input/aiptek.c b/drivers/usb/input/aiptek.c
index 0e2505c073db..a6693b0d1c4c 100644
--- a/drivers/usb/input/aiptek.c
+++ b/drivers/usb/input/aiptek.c
@@ -338,7 +338,7 @@ struct aiptek {
  * the bitmap which comes from the tablet. This hides the
  * issue that the F_keys are not sequentially numbered.
  */
-static int macroKeyEvents[] = {
+static const int macroKeyEvents[] = {
 	KEY_ESC, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5,
 	KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_F11,
 	KEY_F12, KEY_F13, KEY_F14, KEY_F15, KEY_F16, KEY_F17,
@@ -2093,7 +2093,7 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
 	/* Programming the tablet macro keys needs to be done with a for loop
 	 * as the keycodes are discontiguous.
 	 */
-	for (i = 0; i < sizeof(macroKeyEvents) / sizeof(macroKeyEvents[0]); ++i)
+	for (i = 0; i < ARRAY_SIZE(macroKeyEvents); ++i)
 		set_bit(macroKeyEvents[i], inputdev->keybit);
 
 	/*
@@ -2135,7 +2135,7 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
 	 * not an error :-)
 	 */
 
-	for (i = 0; i < sizeof(speeds) / sizeof(speeds[0]); ++i) {
+	for (i = 0; i < ARRAY_SIZE(speeds); ++i) {
 		aiptek->curSetting.programmableDelay = speeds[i];
 		(void)aiptek_program_tablet(aiptek);
 		if (aiptek->inputdev->absmax[ABS_X] > 0) {
@@ -2190,7 +2190,6 @@ fail1:	input_free_device(inputdev);
 static void aiptek_disconnect(struct usb_interface *intf);
 
 static struct usb_driver aiptek_driver = {
-	.owner = THIS_MODULE,
 	.name = "aiptek",
 	.probe = aiptek_probe,
 	.disconnect = aiptek_disconnect,
diff --git a/drivers/usb/input/appletouch.c b/drivers/usb/input/appletouch.c
index 15840db092a5..1949b54f41f2 100644
--- a/drivers/usb/input/appletouch.c
+++ b/drivers/usb/input/appletouch.c
@@ -452,7 +452,6 @@ static int atp_resume(struct usb_interface *iface)
 }
 
 static struct usb_driver atp_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "appletouch",
 	.probe		= atp_probe,
 	.disconnect	= atp_disconnect,
diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c
index 9a2a47db9494..f7bdc506e613 100644
--- a/drivers/usb/input/ati_remote.c
+++ b/drivers/usb/input/ati_remote.c
@@ -96,6 +96,7 @@
 #include <linux/usb.h>
 #include <linux/usb_input.h>
 #include <linux/wait.h>
+#include <linux/jiffies.h>
 
 /*
  * Module and Version Information, Module Parameters
@@ -146,7 +147,7 @@ static char init1[] = { 0x01, 0x00, 0x20, 0x14 };
 static char init2[] = { 0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20 };
 
 /* Acceleration curve for directional control pad */
-static char accel[] = { 1, 2, 4, 6, 9, 13, 20 };
+static const char accel[] = { 1, 2, 4, 6, 9, 13, 20 };
 
 /* Duplicate event filtering time.
  * Sequential, identical KIND_FILTERED inputs with less than
@@ -197,7 +198,7 @@ struct ati_remote {
 #define KIND_ACCEL      7   /* Directional keypad - left, right, up, down.*/
 
 /* Translation table from hardware messages to input events. */
-static struct {
+static const struct {
 	short kind;
 	unsigned char data1, data2;
 	int type;
@@ -295,7 +296,6 @@ static void ati_remote_disconnect	(struct usb_interface *interface);
 
 /* usb specific object to register with the usb subsystem */
 static struct usb_driver ati_remote_driver = {
-	.owner        = THIS_MODULE,
 	.name         = "ati_remote",
 	.probe        = ati_remote_probe,
 	.disconnect   = ati_remote_disconnect,
@@ -472,7 +472,7 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs)
 		/* Filter duplicate events which happen "too close" together. */
 		if ((ati_remote->old_data[0] == data[1]) &&
 			(ati_remote->old_data[1] == data[2]) &&
-			((ati_remote->old_jiffies + FILTER_TIME) > jiffies)) {
+			time_before(jiffies, ati_remote->old_jiffies + FILTER_TIME)) {
 			ati_remote->repeat_count++;
 		} else {
 			ati_remote->repeat_count = 0;
@@ -507,16 +507,16 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs)
 	 * pad down, so we increase acceleration, ramping up over two seconds to
 	 * a maximum speed.  The acceleration curve is #defined above.
 	 */
-	if ((jiffies - ati_remote->old_jiffies) > (HZ >> 2)) {
+	if (time_after(jiffies, ati_remote->old_jiffies + (HZ >> 2))) {
 		acc = 1;
 		ati_remote->acc_jiffies = jiffies;
 	}
-	else if ((jiffies - ati_remote->acc_jiffies) < (HZ >> 3))  acc = accel[0];
-	else if ((jiffies - ati_remote->acc_jiffies) < (HZ >> 2))  acc = accel[1];
-	else if ((jiffies - ati_remote->acc_jiffies) < (HZ >> 1))  acc = accel[2];
-	else if ((jiffies - ati_remote->acc_jiffies) < HZ )        acc = accel[3];
-	else if ((jiffies - ati_remote->acc_jiffies) < HZ+(HZ>>1)) acc = accel[4];
-	else if ((jiffies - ati_remote->acc_jiffies) < (HZ << 1))  acc = accel[5];
+	else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ >> 3)))  acc = accel[0];
+	else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ >> 2)))  acc = accel[1];
+	else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ >> 1)))  acc = accel[2];
+	else if (time_before(jiffies, ati_remote->acc_jiffies + HZ))         acc = accel[3];
+	else if (time_before(jiffies, ati_remote->acc_jiffies + HZ+(HZ>>1))) acc = accel[4];
+	else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ << 1)))  acc = accel[5];
 	else acc = accel[6];
 
 	input_regs(dev, regs);
diff --git a/drivers/usb/input/ati_remote2.c b/drivers/usb/input/ati_remote2.c
new file mode 100644
index 000000000000..ab1a1ae24be9
--- /dev/null
+++ b/drivers/usb/input/ati_remote2.c
@@ -0,0 +1,477 @@
+/*
+ * ati_remote2 - ATI/Philips USB RF remote driver
+ *
+ * Copyright (C) 2005 Ville Syrjala <syrjala@sci.fi>
+ *
+ * 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/usb_input.h>
+
+#define DRIVER_DESC    "ATI/Philips USB RF remote driver"
+#define DRIVER_VERSION "0.1"
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_AUTHOR("Ville Syrjala <syrjala@sci.fi>");
+MODULE_LICENSE("GPL");
+
+static unsigned int mode_mask = 0x1F;
+module_param(mode_mask, uint, 0644);
+MODULE_PARM_DESC(mode_mask, "Bitmask of modes to accept <4:PC><3:AUX4><2:AUX3><1:AUX2><0:AUX1>");
+
+static struct usb_device_id ati_remote2_id_table[] = {
+	{ USB_DEVICE(0x0471, 0x0602) },	/* ATI Remote Wonder II */
+	{ }
+};
+MODULE_DEVICE_TABLE(usb, ati_remote2_id_table);
+
+static struct {
+	int hw_code;
+	int key_code;
+} ati_remote2_key_table[] = {
+	{ 0x00, KEY_0 },
+	{ 0x01, KEY_1 },
+	{ 0x02, KEY_2 },
+	{ 0x03, KEY_3 },
+	{ 0x04, KEY_4 },
+	{ 0x05, KEY_5 },
+	{ 0x06, KEY_6 },
+	{ 0x07, KEY_7 },
+	{ 0x08, KEY_8 },
+	{ 0x09, KEY_9 },
+	{ 0x0c, KEY_POWER },
+	{ 0x0d, KEY_MUTE },
+	{ 0x10, KEY_VOLUMEUP },
+	{ 0x11, KEY_VOLUMEDOWN },
+	{ 0x20, KEY_CHANNELUP },
+	{ 0x21, KEY_CHANNELDOWN },
+	{ 0x28, KEY_FORWARD },
+	{ 0x29, KEY_REWIND },
+	{ 0x2c, KEY_PLAY },
+	{ 0x30, KEY_PAUSE },
+	{ 0x31, KEY_STOP },
+	{ 0x37, KEY_RECORD },
+	{ 0x38, KEY_DVD },
+	{ 0x39, KEY_TV },
+	{ 0x54, KEY_MENU },
+	{ 0x58, KEY_UP },
+	{ 0x59, KEY_DOWN },
+	{ 0x5a, KEY_LEFT },
+	{ 0x5b, KEY_RIGHT },
+	{ 0x5c, KEY_OK },
+	{ 0x78, KEY_A },
+	{ 0x79, KEY_B },
+	{ 0x7a, KEY_C },
+	{ 0x7b, KEY_D },
+	{ 0x7c, KEY_E },
+	{ 0x7d, KEY_F },
+	{ 0x82, KEY_ENTER },
+	{ 0x8e, KEY_VENDOR },
+	{ 0x96, KEY_COFFEE },
+	{ 0xa9, BTN_LEFT },
+	{ 0xaa, BTN_RIGHT },
+	{ 0xbe, KEY_QUESTION },
+	{ 0xd5, KEY_FRONT },
+	{ 0xd0, KEY_EDIT },
+	{ 0xf9, KEY_INFO },
+	{ (0x00 << 8) | 0x3f, KEY_PROG1 },
+	{ (0x01 << 8) | 0x3f, KEY_PROG2 },
+	{ (0x02 << 8) | 0x3f, KEY_PROG3 },
+	{ (0x03 << 8) | 0x3f, KEY_PROG4 },
+	{ (0x04 << 8) | 0x3f, KEY_PC },
+	{ 0, KEY_RESERVED }
+};
+
+struct ati_remote2 {
+	struct input_dev *idev;
+	struct usb_device *udev;
+
+	struct usb_interface *intf[2];
+	struct usb_endpoint_descriptor *ep[2];
+	struct urb *urb[2];
+	void *buf[2];
+	dma_addr_t buf_dma[2];
+
+	unsigned long jiffies;
+	int mode;
+
+	char name[64];
+	char phys[64];
+};
+
+static int ati_remote2_probe(struct usb_interface *interface, const struct usb_device_id *id);
+static void ati_remote2_disconnect(struct usb_interface *interface);
+
+static struct usb_driver ati_remote2_driver = {
+	.name       = "ati_remote2",
+	.probe      = ati_remote2_probe,
+	.disconnect = ati_remote2_disconnect,
+	.id_table   = ati_remote2_id_table,
+};
+
+static int ati_remote2_open(struct input_dev *idev)
+{
+	struct ati_remote2 *ar2 = idev->private;
+	int r;
+
+	r = usb_submit_urb(ar2->urb[0], GFP_KERNEL);
+	if (r) {
+		dev_err(&ar2->intf[0]->dev,
+			"%s: usb_submit_urb() = %d\n", __FUNCTION__, r);
+		return r;
+	}
+	r = usb_submit_urb(ar2->urb[1], GFP_KERNEL);
+	if (r) {
+		usb_kill_urb(ar2->urb[0]);
+		dev_err(&ar2->intf[1]->dev,
+			"%s: usb_submit_urb() = %d\n", __FUNCTION__, r);
+		return r;
+	}
+
+	return 0;
+}
+
+static void ati_remote2_close(struct input_dev *idev)
+{
+	struct ati_remote2 *ar2 = idev->private;
+
+	usb_kill_urb(ar2->urb[0]);
+	usb_kill_urb(ar2->urb[1]);
+}
+
+static void ati_remote2_input_mouse(struct ati_remote2 *ar2, struct pt_regs *regs)
+{
+	struct input_dev *idev = ar2->idev;
+	u8 *data = ar2->buf[0];
+
+	if (data[0] > 4) {
+		dev_err(&ar2->intf[0]->dev,
+			"Unknown mode byte (%02x %02x %02x %02x)\n",
+			data[3], data[2], data[1], data[0]);
+		return;
+	}
+
+	if (!((1 << data[0]) & mode_mask))
+		return;
+
+	input_regs(idev, regs);
+	input_event(idev, EV_REL, REL_X, (s8) data[1]);
+	input_event(idev, EV_REL, REL_Y, (s8) data[2]);
+	input_sync(idev);
+}
+
+static int ati_remote2_lookup(unsigned int hw_code)
+{
+	int i;
+
+	for (i = 0; ati_remote2_key_table[i].key_code != KEY_RESERVED; i++)
+		if (ati_remote2_key_table[i].hw_code == hw_code)
+			return i;
+
+	return -1;
+}
+
+static void ati_remote2_input_key(struct ati_remote2 *ar2, struct pt_regs *regs)
+{
+	struct input_dev *idev = ar2->idev;
+	u8 *data = ar2->buf[1];
+	int hw_code, index;
+
+	if (data[0] > 4) {
+		dev_err(&ar2->intf[1]->dev,
+			"Unknown mode byte (%02x %02x %02x %02x)\n",
+			data[3], data[2], data[1], data[0]);
+		return;
+	}
+
+	hw_code = data[2];
+	/*
+	 * Mode keys (AUX1-AUX4, PC) all generate the same code byte.
+	 * Use the mode byte to figure out which one was pressed.
+	 */
+	if (hw_code == 0x3f) {
+		/*
+		 * For some incomprehensible reason the mouse pad generates
+		 * events which look identical to the events from the last
+		 * pressed mode key. Naturally we don't want to generate key
+		 * events for the mouse pad so we filter out any subsequent
+		 * events from the same mode key.
+		 */
+		if (ar2->mode == data[0])
+			return;
+
+		if (data[1] == 0)
+			ar2->mode = data[0];
+
+		hw_code |= data[0] << 8;
+	}
+
+	if (!((1 << data[0]) & mode_mask))
+		return;
+
+	index = ati_remote2_lookup(hw_code);
+	if (index < 0) {
+		dev_err(&ar2->intf[1]->dev,
+			"Unknown code byte (%02x %02x %02x %02x)\n",
+			data[3], data[2], data[1], data[0]);
+		return;
+	}
+
+	switch (data[1]) {
+	case 0:	/* release */
+		break;
+	case 1:	/* press */
+		ar2->jiffies = jiffies + msecs_to_jiffies(idev->rep[REP_DELAY]);
+		break;
+	case 2:	/* repeat */
+
+		/* No repeat for mouse buttons. */
+		if (ati_remote2_key_table[index].key_code == BTN_LEFT ||
+		    ati_remote2_key_table[index].key_code == BTN_RIGHT)
+			return;
+
+		if (!time_after_eq(jiffies, ar2->jiffies))
+			return;
+
+		ar2->jiffies = jiffies + msecs_to_jiffies(idev->rep[REP_PERIOD]);
+		break;
+	default:
+		dev_err(&ar2->intf[1]->dev,
+			"Unknown state byte (%02x %02x %02x %02x)\n",
+			data[3], data[2], data[1], data[0]);
+		return;
+	}
+
+	input_regs(idev, regs);
+	input_event(idev, EV_KEY, ati_remote2_key_table[index].key_code, data[1]);
+	input_sync(idev);
+}
+
+static void ati_remote2_complete_mouse(struct urb *urb, struct pt_regs *regs)
+{
+	struct ati_remote2 *ar2 = urb->context;
+	int r;
+
+	switch (urb->status) {
+	case 0:
+		ati_remote2_input_mouse(ar2, regs);
+		break;
+	case -ENOENT:
+	case -EILSEQ:
+	case -ECONNRESET:
+	case -ESHUTDOWN:
+		dev_dbg(&ar2->intf[0]->dev,
+			"%s(): urb status = %d\n", __FUNCTION__, urb->status);
+		return;
+	default:
+		dev_err(&ar2->intf[0]->dev,
+			"%s(): urb status = %d\n", __FUNCTION__, urb->status);
+	}
+
+	r = usb_submit_urb(urb, GFP_ATOMIC);
+	if (r)
+		dev_err(&ar2->intf[0]->dev,
+			"%s(): usb_submit_urb() = %d\n", __FUNCTION__, r);
+}
+
+static void ati_remote2_complete_key(struct urb *urb, struct pt_regs *regs)
+{
+	struct ati_remote2 *ar2 = urb->context;
+	int r;
+
+	switch (urb->status) {
+	case 0:
+		ati_remote2_input_key(ar2, regs);
+		break;
+	case -ENOENT:
+	case -EILSEQ:
+	case -ECONNRESET:
+	case -ESHUTDOWN:
+		dev_dbg(&ar2->intf[1]->dev,
+			"%s(): urb status = %d\n", __FUNCTION__, urb->status);
+		return;
+	default:
+		dev_err(&ar2->intf[1]->dev,
+			"%s(): urb status = %d\n", __FUNCTION__, urb->status);
+	}
+
+	r = usb_submit_urb(urb, GFP_ATOMIC);
+	if (r)
+		dev_err(&ar2->intf[1]->dev,
+			"%s(): usb_submit_urb() = %d\n", __FUNCTION__, r);
+}
+
+static int ati_remote2_input_init(struct ati_remote2 *ar2)
+{
+	struct input_dev *idev;
+	int i;
+
+	idev = input_allocate_device();
+	if (!idev)
+		return -ENOMEM;
+
+	ar2->idev = idev;
+	idev->private = ar2;
+
+	idev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_REL);
+	idev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT);
+	idev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
+	for (i = 0; ati_remote2_key_table[i].key_code != KEY_RESERVED; i++)
+		set_bit(ati_remote2_key_table[i].key_code, idev->keybit);
+
+	idev->rep[REP_DELAY]  = 250;
+	idev->rep[REP_PERIOD] = 33;
+
+	idev->open = ati_remote2_open;
+	idev->close = ati_remote2_close;
+
+	idev->name = ar2->name;
+	idev->phys = ar2->phys;
+
+	usb_to_input_id(ar2->udev, &idev->id);
+	idev->cdev.dev = &ar2->udev->dev;
+
+	i = input_register_device(idev);
+	if (i)
+		input_free_device(idev);
+
+	return i;
+}
+
+static int ati_remote2_urb_init(struct ati_remote2 *ar2)
+{
+	struct usb_device *udev = ar2->udev;
+	int i, pipe, maxp;
+
+	for (i = 0; i < 2; i++) {
+		ar2->buf[i] = usb_buffer_alloc(udev, 4, GFP_KERNEL, &ar2->buf_dma[i]);
+		if (!ar2->buf[i])
+			return -ENOMEM;
+
+		ar2->urb[i] = usb_alloc_urb(0, GFP_KERNEL);
+		if (!ar2->urb[i])
+			return -ENOMEM;
+
+		pipe = usb_rcvintpipe(udev, ar2->ep[i]->bEndpointAddress);
+		maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
+		maxp = maxp > 4 ? 4 : maxp;
+
+		usb_fill_int_urb(ar2->urb[i], udev, pipe, ar2->buf[i], maxp,
+				 i ? ati_remote2_complete_key : ati_remote2_complete_mouse,
+				 ar2, ar2->ep[i]->bInterval);
+		ar2->urb[i]->transfer_dma = ar2->buf_dma[i];
+		ar2->urb[i]->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+	}
+
+	return 0;
+}
+
+static void ati_remote2_urb_cleanup(struct ati_remote2 *ar2)
+{
+	int i;
+
+	for (i = 0; i < 2; i++) {
+		if (ar2->urb[i])
+			usb_free_urb(ar2->urb[i]);
+
+		if (ar2->buf[i])
+			usb_buffer_free(ar2->udev, 4, ar2->buf[i], ar2->buf_dma[i]);
+	}
+}
+
+static int ati_remote2_probe(struct usb_interface *interface, const struct usb_device_id *id)
+{
+	struct usb_device *udev = interface_to_usbdev(interface);
+	struct usb_host_interface *alt = interface->cur_altsetting;
+	struct ati_remote2 *ar2;
+	int r;
+
+	if (alt->desc.bInterfaceNumber)
+		return -ENODEV;
+
+	ar2 = kzalloc(sizeof (struct ati_remote2), GFP_KERNEL);
+	if (!ar2)
+		return -ENOMEM;
+
+	ar2->udev = udev;
+
+	ar2->intf[0] = interface;
+	ar2->ep[0] = &alt->endpoint[0].desc;
+
+	ar2->intf[1] = usb_ifnum_to_if(udev, 1);
+	r = usb_driver_claim_interface(&ati_remote2_driver, ar2->intf[1], ar2);
+	if (r)
+		goto fail1;
+	alt = ar2->intf[1]->cur_altsetting;
+	ar2->ep[1] = &alt->endpoint[0].desc;
+
+	r = ati_remote2_urb_init(ar2);
+	if (r)
+		goto fail2;
+
+	usb_make_path(udev, ar2->phys, sizeof(ar2->phys));
+	strlcat(ar2->phys, "/input0", sizeof(ar2->phys));
+
+	strlcat(ar2->name, "ATI Remote Wonder II", sizeof(ar2->name));
+
+	r = ati_remote2_input_init(ar2);
+	if (r)
+		goto fail2;
+
+	usb_set_intfdata(interface, ar2);
+
+	return 0;
+
+ fail2:
+	ati_remote2_urb_cleanup(ar2);
+
+	usb_driver_release_interface(&ati_remote2_driver, ar2->intf[1]);
+ fail1:
+	kfree(ar2);
+
+	return r;
+}
+
+static void ati_remote2_disconnect(struct usb_interface *interface)
+{
+	struct ati_remote2 *ar2;
+	struct usb_host_interface *alt = interface->cur_altsetting;
+
+	if (alt->desc.bInterfaceNumber)
+		return;
+
+	ar2 = usb_get_intfdata(interface);
+	usb_set_intfdata(interface, NULL);
+
+	input_unregister_device(ar2->idev);
+
+	ati_remote2_urb_cleanup(ar2);
+
+	usb_driver_release_interface(&ati_remote2_driver, ar2->intf[1]);
+
+	kfree(ar2);
+}
+
+static int __init ati_remote2_init(void)
+{
+	int r;
+
+	r = usb_register(&ati_remote2_driver);
+	if (r)
+		printk(KERN_ERR "ati_remote2: usb_register() = %d\n", r);
+	else
+		printk(KERN_INFO "ati_remote2: " DRIVER_DESC " " DRIVER_VERSION "\n");
+
+	return r;
+}
+
+static void __exit ati_remote2_exit(void)
+{
+	usb_deregister(&ati_remote2_driver);
+}
+
+module_init(ati_remote2_init);
+module_exit(ati_remote2_exit);
diff --git a/drivers/usb/input/fixp-arith.h b/drivers/usb/input/fixp-arith.h
index 26ca5b890a61..b44d398de071 100644
--- a/drivers/usb/input/fixp-arith.h
+++ b/drivers/usb/input/fixp-arith.h
@@ -38,7 +38,7 @@ typedef s16 fixp_t;
 #define FRAC_MASK ((1<<FRAC_N)-1)
 
 // Not to be used directly. Use fixp_{cos,sin}
-static fixp_t cos_table[45] = {
+static const fixp_t cos_table[45] = {
 	0x0100,	0x00FF,	0x00FF,	0x00FE,	0x00FD,	0x00FC,	0x00FA,	0x00F8,
 	0x00F6,	0x00F3,	0x00F0,	0x00ED,	0x00E9,	0x00E6,	0x00E2,	0x00DD,
 	0x00D9,	0x00D4,	0x00CF,	0x00C9,	0x00C4,	0x00BE,	0x00B8,	0x00B1,
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
index a3e44ef1df43..5f52979af1c7 100644
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -1454,7 +1454,7 @@ void hid_init_reports(struct hid_device *hid)
  * Alphabetically sorted blacklist by quirk type.
  */
 
-static struct hid_blacklist {
+static const struct hid_blacklist {
 	__u16 idVendor;
 	__u16 idProduct;
 	unsigned quirks;
@@ -1930,7 +1930,6 @@ static struct usb_device_id hid_usb_ids [] = {
 MODULE_DEVICE_TABLE (usb, hid_usb_ids);
 
 static struct usb_driver hid_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"usbhid",
 	.probe =	hid_probe,
 	.disconnect =	hid_disconnect,
diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c
index 1220a5004a5c..192a03b28971 100644
--- a/drivers/usb/input/hid-input.c
+++ b/drivers/usb/input/hid-input.c
@@ -39,7 +39,7 @@
 
 #define unk	KEY_UNKNOWN
 
-static unsigned char hid_keyboard[256] = {
+static const unsigned char hid_keyboard[256] = {
 	  0,  0,  0,  0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
 	 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44,  2,  3,
 	  4,  5,  6,  7,  8,  9, 10, 11, 28,  1, 14, 15, 57, 12, 13, 26,
@@ -58,7 +58,7 @@ static unsigned char hid_keyboard[256] = {
 	150,158,159,128,136,177,178,176,142,152,173,140,unk,unk,unk,unk
 };
 
-static struct {
+static const struct {
 	__s32 x;
 	__s32 y;
 }  hid_hat_to_axis[] = {{ 0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}};
diff --git a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c
index 440377c7a0da..4dff8473553d 100644
--- a/drivers/usb/input/hiddev.c
+++ b/drivers/usb/input/hiddev.c
@@ -826,7 +826,6 @@ static int hiddev_usbd_probe(struct usb_interface *intf,
 
 
 static /* const */ struct usb_driver hiddev_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"hiddev",
 	.probe =	hiddev_usbd_probe,
 };
diff --git a/drivers/usb/input/itmtouch.c b/drivers/usb/input/itmtouch.c
index 4a50acb39d29..7618ae5c104f 100644
--- a/drivers/usb/input/itmtouch.c
+++ b/drivers/usb/input/itmtouch.c
@@ -250,7 +250,6 @@ static void itmtouch_disconnect(struct usb_interface *intf)
 MODULE_DEVICE_TABLE(usb, itmtouch_ids);
 
 static struct usb_driver itmtouch_driver = {
-	.owner =        THIS_MODULE,
 	.name =         "itmtouch",
 	.probe =        itmtouch_probe,
 	.disconnect =   itmtouch_disconnect,
diff --git a/drivers/usb/input/kbtab.c b/drivers/usb/input/kbtab.c
index fd48e74e78ed..f6d5cead542b 100644
--- a/drivers/usb/input/kbtab.c
+++ b/drivers/usb/input/kbtab.c
@@ -197,7 +197,6 @@ static void kbtab_disconnect(struct usb_interface *intf)
 }
 
 static struct usb_driver kbtab_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"kbtab",
 	.probe =	kbtab_probe,
 	.disconnect =	kbtab_disconnect,
diff --git a/drivers/usb/input/keyspan_remote.c b/drivers/usb/input/keyspan_remote.c
index a32cfe51b77d..b4a051b549d1 100644
--- a/drivers/usb/input/keyspan_remote.c
+++ b/drivers/usb/input/keyspan_remote.c
@@ -95,7 +95,7 @@ struct usb_keyspan {
  * Currently there are 15 and 17 button models so RESERVED codes
  * are blank areas in the mapping.
  */
-static int keyspan_key_table[] = {
+static const int keyspan_key_table[] = {
 	KEY_RESERVED,		/* 0 is just a place holder. */
 	KEY_RESERVED,
 	KEY_STOP,
@@ -559,7 +559,6 @@ static void keyspan_disconnect(struct usb_interface *interface)
  */
 static struct usb_driver keyspan_driver =
 {
-	.owner =	THIS_MODULE,
 	.name =		"keyspan_remote",
 	.probe =	keyspan_probe,
 	.disconnect =	keyspan_disconnect,
diff --git a/drivers/usb/input/mtouchusb.c b/drivers/usb/input/mtouchusb.c
index 52cc18cd247d..f018953a5485 100644
--- a/drivers/usb/input/mtouchusb.c
+++ b/drivers/usb/input/mtouchusb.c
@@ -310,7 +310,6 @@ static void mtouchusb_disconnect(struct usb_interface *intf)
 MODULE_DEVICE_TABLE(usb, mtouchusb_devices);
 
 static struct usb_driver mtouchusb_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "mtouchusb",
 	.probe		= mtouchusb_probe,
 	.disconnect	= mtouchusb_disconnect,
diff --git a/drivers/usb/input/powermate.c b/drivers/usb/input/powermate.c
index b7476233ef5d..fdf0f788062c 100644
--- a/drivers/usb/input/powermate.c
+++ b/drivers/usb/input/powermate.c
@@ -441,7 +441,6 @@ static struct usb_device_id powermate_devices [] = {
 MODULE_DEVICE_TABLE (usb, powermate_devices);
 
 static struct usb_driver powermate_driver = {
-	.owner =	THIS_MODULE,
         .name =         "powermate",
         .probe =        powermate_probe,
         .disconnect =   powermate_disconnect,
diff --git a/drivers/usb/input/touchkitusb.c b/drivers/usb/input/touchkitusb.c
index 7420c6b84284..3b3c7b4120a2 100644
--- a/drivers/usb/input/touchkitusb.c
+++ b/drivers/usb/input/touchkitusb.c
@@ -1,7 +1,7 @@
 /******************************************************************************
  * touchkitusb.c  --  Driver for eGalax TouchKit USB Touchscreens
  *
- * Copyright (C) 2004 by Daniel Ritz
+ * Copyright (C) 2004-2005 by Daniel Ritz <daniel.ritz@gmx.ch>
  * Copyright (C) by Todd E. Johnson (mtouchusb.c)
  *
  * This program is free software; you can redistribute it and/or
@@ -41,15 +41,13 @@
 #define TOUCHKIT_MAX_YC			0x07ff
 #define TOUCHKIT_YC_FUZZ		0x0
 #define TOUCHKIT_YC_FLAT		0x0
-#define TOUCHKIT_REPORT_DATA_SIZE	8
+#define TOUCHKIT_REPORT_DATA_SIZE	16
 
 #define TOUCHKIT_DOWN			0x01
-#define TOUCHKIT_POINT_TOUCH		0x81
-#define TOUCHKIT_POINT_NOTOUCH		0x80
 
-#define TOUCHKIT_GET_TOUCHED(dat)	((((dat)[0]) & TOUCHKIT_DOWN) ? 1 : 0)
-#define TOUCHKIT_GET_X(dat)		(((dat)[3] << 7) | (dat)[4])
-#define TOUCHKIT_GET_Y(dat)		(((dat)[1] << 7) | (dat)[2])
+#define TOUCHKIT_PKT_TYPE_MASK		0xFE
+#define TOUCHKIT_PKT_TYPE_REPT		0x80
+#define TOUCHKIT_PKT_TYPE_DIAG		0x0A
 
 #define DRIVER_VERSION			"v0.1"
 #define DRIVER_AUTHOR			"Daniel Ritz <daniel.ritz@gmx.ch>"
@@ -62,6 +60,8 @@ MODULE_PARM_DESC(swap_xy, "If set X and Y axes are swapped.");
 struct touchkit_usb {
 	unsigned char *data;
 	dma_addr_t data_dma;
+	char buffer[TOUCHKIT_REPORT_DATA_SIZE];
+	int buf_len;
 	struct urb *irq;
 	struct usb_device *udev;
 	struct input_dev *input;
@@ -77,11 +77,128 @@ static struct usb_device_id touchkit_devices[] = {
 	{}
 };
 
+/* helpers to read the data */
+static inline int touchkit_get_touched(char *data)
+{
+	return (data[0] & TOUCHKIT_DOWN) ? 1 : 0;
+}
+
+static inline int touchkit_get_x(char *data)
+{
+	return ((data[3] & 0x0F) << 7) | (data[4] & 0x7F);
+}
+
+static inline int touchkit_get_y(char *data)
+{
+	return ((data[1] & 0x0F) << 7) | (data[2] & 0x7F);
+}
+
+
+/* processes one input packet. */
+static void touchkit_process_pkt(struct touchkit_usb *touchkit,
+                                 struct pt_regs *regs, char *pkt)
+{
+	int x, y;
+
+	/* only process report packets */
+	if ((pkt[0] & TOUCHKIT_PKT_TYPE_MASK) != TOUCHKIT_PKT_TYPE_REPT)
+		return;
+
+	if (swap_xy) {
+		y = touchkit_get_x(pkt);
+		x = touchkit_get_y(pkt);
+	} else {
+		x = touchkit_get_x(pkt);
+		y = touchkit_get_y(pkt);
+	}
+
+	input_regs(touchkit->input, regs);
+	input_report_key(touchkit->input, BTN_TOUCH, touchkit_get_touched(pkt));
+	input_report_abs(touchkit->input, ABS_X, x);
+	input_report_abs(touchkit->input, ABS_Y, y);
+	input_sync(touchkit->input);
+}
+
+
+static int touchkit_get_pkt_len(char *buf)
+{
+	switch (buf[0] & TOUCHKIT_PKT_TYPE_MASK) {
+	case TOUCHKIT_PKT_TYPE_REPT:
+		return 5;
+
+	case TOUCHKIT_PKT_TYPE_DIAG:
+		return buf[1] + 2;
+	}
+
+	return 0;
+}
+
+static void touchkit_process(struct touchkit_usb *touchkit, int len,
+                             struct pt_regs *regs)
+{
+	char *buffer;
+	int pkt_len, buf_len, pos;
+
+	/* if the buffer contains data, append */
+	if (unlikely(touchkit->buf_len)) {
+		int tmp;
+
+		/* if only 1 byte in buffer, add another one to get length */
+		if (touchkit->buf_len == 1)
+			touchkit->buffer[1] = touchkit->data[0];
+
+		pkt_len = touchkit_get_pkt_len(touchkit->buffer);
+
+		/* unknown packet: drop everything */
+		if (!pkt_len)
+			return;
+
+		/* append, process */
+		tmp = pkt_len - touchkit->buf_len;
+		memcpy(touchkit->buffer + touchkit->buf_len, touchkit->data, tmp);
+		touchkit_process_pkt(touchkit, regs, touchkit->buffer);
+
+		buffer = touchkit->data + tmp;
+		buf_len = len - tmp;
+	} else {
+		buffer = touchkit->data;
+		buf_len = len;
+	}
+
+	/* only one byte left in buffer */
+	if (unlikely(buf_len == 1)) {
+		touchkit->buffer[0] = buffer[0];
+		touchkit->buf_len = 1;
+		return;
+	}
+
+	/* loop over the buffer */
+	pos = 0;
+	while (pos < buf_len) {
+		/* get packet len */
+		pkt_len = touchkit_get_pkt_len(buffer + pos);
+
+		/* unknown packet: drop everything */
+		if (unlikely(!pkt_len))
+			return;
+
+		/* full packet: process */
+		if (likely(pkt_len <= buf_len)) {
+			touchkit_process_pkt(touchkit, regs, buffer + pos);
+		} else {
+			/* incomplete packet: save in buffer */
+			memcpy(touchkit->buffer, buffer + pos, buf_len - pos);
+			touchkit->buf_len = buf_len - pos;
+		}
+		pos += pkt_len;
+	}
+}
+
+
 static void touchkit_irq(struct urb *urb, struct pt_regs *regs)
 {
 	struct touchkit_usb *touchkit = urb->context;
 	int retval;
-	int x, y;
 
 	switch (urb->status) {
 	case 0:
@@ -105,20 +222,7 @@ static void touchkit_irq(struct urb *urb, struct pt_regs *regs)
 		goto exit;
 	}
 
-	if (swap_xy) {
-		y = TOUCHKIT_GET_X(touchkit->data);
-		x = TOUCHKIT_GET_Y(touchkit->data);
-	} else {
-		x = TOUCHKIT_GET_X(touchkit->data);
-		y = TOUCHKIT_GET_Y(touchkit->data);
-	}
-
-	input_regs(touchkit->input, regs);
-	input_report_key(touchkit->input, BTN_TOUCH,
-	                 TOUCHKIT_GET_TOUCHED(touchkit->data));
-	input_report_abs(touchkit->input, ABS_X, x);
-	input_report_abs(touchkit->input, ABS_Y, y);
-	input_sync(touchkit->input);
+	touchkit_process(touchkit, urb->actual_length, regs);
 
 exit:
 	retval = usb_submit_urb(urb, GFP_ATOMIC);
@@ -267,7 +371,6 @@ static void touchkit_disconnect(struct usb_interface *intf)
 MODULE_DEVICE_TABLE(usb, touchkit_devices);
 
 static struct usb_driver touchkit_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "touchkitusb",
 	.probe		= touchkit_probe,
 	.disconnect	= touchkit_disconnect,
diff --git a/drivers/usb/input/usbkbd.c b/drivers/usb/input/usbkbd.c
index 226b6f90a907..2f3edc26cb50 100644
--- a/drivers/usb/input/usbkbd.c
+++ b/drivers/usb/input/usbkbd.c
@@ -345,7 +345,6 @@ static struct usb_device_id usb_kbd_id_table [] = {
 MODULE_DEVICE_TABLE (usb, usb_kbd_id_table);
 
 static struct usb_driver usb_kbd_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"usbkbd",
 	.probe =	usb_kbd_probe,
 	.disconnect =	usb_kbd_disconnect,
diff --git a/drivers/usb/input/usbmouse.c b/drivers/usb/input/usbmouse.c
index 230f6b1b314a..af526135d210 100644
--- a/drivers/usb/input/usbmouse.c
+++ b/drivers/usb/input/usbmouse.c
@@ -226,7 +226,6 @@ static struct usb_device_id usb_mouse_id_table [] = {
 MODULE_DEVICE_TABLE (usb, usb_mouse_id_table);
 
 static struct usb_driver usb_mouse_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "usbmouse",
 	.probe		= usb_mouse_probe,
 	.disconnect	= usb_mouse_disconnect,
diff --git a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c
index dc099bbe12bf..48df4cfd5a42 100644
--- a/drivers/usb/input/wacom.c
+++ b/drivers/usb/input/wacom.c
@@ -945,7 +945,6 @@ static void wacom_disconnect(struct usb_interface *intf)
 }
 
 static struct usb_driver wacom_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"wacom",
 	.probe =	wacom_probe,
 	.disconnect =	wacom_disconnect,
diff --git a/drivers/usb/input/xpad.c b/drivers/usb/input/xpad.c
index 43112f040b6d..e278489a80c6 100644
--- a/drivers/usb/input/xpad.c
+++ b/drivers/usb/input/xpad.c
@@ -70,7 +70,7 @@
 
 #define XPAD_PKT_LEN 32
 
-static struct xpad_device {
+static const struct xpad_device {
 	u16 idVendor;
 	u16 idProduct;
 	char *name;
@@ -81,13 +81,13 @@ static struct xpad_device {
 	{ 0x0000, 0x0000, "X-Box pad" }
 };
 
-static signed short xpad_btn[] = {
+static const signed short xpad_btn[] = {
 	BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z,	/* "analog" buttons */
 	BTN_START, BTN_BACK, BTN_THUMBL, BTN_THUMBR,	/* start/back/sticks */
 	-1						/* terminating entry */
 };
 
-static signed short xpad_abs[] = {
+static const signed short xpad_abs[] = {
 	ABS_X, ABS_Y,		/* left stick */
 	ABS_RX, ABS_RY,		/* right stick */
 	ABS_Z, ABS_RZ,		/* triggers left/right */
@@ -316,7 +316,6 @@ static void xpad_disconnect(struct usb_interface *intf)
 }
 
 static struct usb_driver xpad_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "xpad",
 	.probe		= xpad_probe,
 	.disconnect	= xpad_disconnect,
diff --git a/drivers/usb/input/yealink.c b/drivers/usb/input/yealink.c
index f526aebea502..1bfc105ad4d6 100644
--- a/drivers/usb/input/yealink.c
+++ b/drivers/usb/input/yealink.c
@@ -987,7 +987,6 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
 }
 
 static struct usb_driver yealink_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "yealink",
 	.probe		= usb_probe,
 	.disconnect	= usb_disconnect,
diff --git a/drivers/usb/media/dabusb.c b/drivers/usb/media/dabusb.c
index 27b23c55bbc7..18d8eaf408d5 100644
--- a/drivers/usb/media/dabusb.c
+++ b/drivers/usb/media/dabusb.c
@@ -812,7 +812,6 @@ static struct usb_device_id dabusb_ids [] = {
 MODULE_DEVICE_TABLE (usb, dabusb_ids);
 
 static struct usb_driver dabusb_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"dabusb",
 	.probe =	dabusb_probe,
 	.disconnect =	dabusb_disconnect,
diff --git a/drivers/usb/media/dsbr100.c b/drivers/usb/media/dsbr100.c
index 7503f5b96f59..6a5700e9d428 100644
--- a/drivers/usb/media/dsbr100.c
+++ b/drivers/usb/media/dsbr100.c
@@ -150,7 +150,6 @@ MODULE_DEVICE_TABLE (usb, usb_dsbr100_device_table);
 
 /* USB subsystem interface */
 static struct usb_driver usb_dsbr100_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"dsbr100",
 	.probe =	usb_dsbr100_probe,
 	.disconnect =	usb_dsbr100_disconnect,
diff --git a/drivers/usb/media/ibmcam.c b/drivers/usb/media/ibmcam.c
index ba41fc7b95c2..a42c22294124 100644
--- a/drivers/usb/media/ibmcam.c
+++ b/drivers/usb/media/ibmcam.c
@@ -3457,7 +3457,7 @@ static void ibmcam_model3_setup_after_video_if(struct uvd *uvd)
 	if(init_model3_input) {
 		if (debug > 0)
 			info("Setting input to RCA.");
-		for (i=0; i < (sizeof(initData)/sizeof(initData[0])); i++) {
+		for (i=0; i < ARRAY_SIZE(initData); i++) {
 			ibmcam_veio(uvd, initData[i].req, initData[i].value, initData[i].index);
 		}
 	}
diff --git a/drivers/usb/media/konicawc.c b/drivers/usb/media/konicawc.c
index 9fe2c2710d13..e2ede583518f 100644
--- a/drivers/usb/media/konicawc.c
+++ b/drivers/usb/media/konicawc.c
@@ -77,14 +77,14 @@ static int saturation =	MAX_SATURATION/2;
 static int sharpness =	MAX_SHARPNESS/2;
 static int whitebal =	3*(MAX_WHITEBAL/4);
 
-static int spd_to_iface[] = { 1, 0, 3, 2, 4, 5, 6 };
+static const int spd_to_iface[] = { 1, 0, 3, 2, 4, 5, 6 };
 
 /* These FPS speeds are from the windows config box. They are
  * indexed on size (0-2) and speed (0-6). Divide by 3 to get the
  * real fps.
  */
 
-static int spd_to_fps[][7] = { { 24, 40, 48, 60, 72, 80, 100 },
+static const int spd_to_fps[][7] = { { 24, 40, 48, 60, 72, 80, 100 },
 			       { 24, 40, 48, 60, 72, 80, 100 },
 			       { 18, 30, 36, 45, 54, 60, 75  },
 			       { 6,  10, 12, 15, 18, 21, 25  } };
@@ -95,7 +95,7 @@ struct cam_size {
 	u8	cmd;
 };
 
-static struct cam_size camera_sizes[] = { { 160, 120, 0x7 },
+static const struct cam_size camera_sizes[] = { { 160, 120, 0x7 },
 					  { 160, 136, 0xa },
 					  { 176, 144, 0x4 },
 					  { 320, 240, 0x5 } };
diff --git a/drivers/usb/media/ov511.c b/drivers/usb/media/ov511.c
index 036c485d1d1e..3a0e8ce67ebe 100644
--- a/drivers/usb/media/ov511.c
+++ b/drivers/usb/media/ov511.c
@@ -211,7 +211,7 @@ static struct ov51x_decomp_ops *ov518_mmx_decomp_ops;
 
 /* Number of times to retry a failed I2C transaction. Increase this if you
  * are getting "Failed to read sensor ID..." */
-static int i2c_detect_tries = 5;
+static const int i2c_detect_tries = 5;
 
 /* MMX support is present in kernel and CPU. Checked upon decomp module load. */
 #if defined(__i386__) || defined(__x86_64__)
@@ -6008,7 +6008,6 @@ ov51x_disconnect(struct usb_interface *intf)
 }
 
 static struct usb_driver ov511_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"ov511",
 	.id_table =	device_table,
 	.probe =	ov51x_probe,
diff --git a/drivers/usb/media/pwc/pwc-ctrl.c b/drivers/usb/media/pwc/pwc-ctrl.c
index 53099190952c..359c4b2df735 100644
--- a/drivers/usb/media/pwc/pwc-ctrl.c
+++ b/drivers/usb/media/pwc/pwc-ctrl.c
@@ -109,7 +109,7 @@
 #define PT_RESET_CONTROL_FORMATTER		0x02
 #define PT_STATUS_FORMATTER			0x03
 
-static char *size2name[PSZ_MAX] =
+static const char *size2name[PSZ_MAX] =
 {
 	"subQCIF",
 	"QSIF",
diff --git a/drivers/usb/media/pwc/pwc-if.c b/drivers/usb/media/pwc/pwc-if.c
index 5524fd70210b..09ca6128ac20 100644
--- a/drivers/usb/media/pwc/pwc-if.c
+++ b/drivers/usb/media/pwc/pwc-if.c
@@ -111,7 +111,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
 static void usb_pwc_disconnect(struct usb_interface *intf);
 
 static struct usb_driver pwc_driver = {
-	.owner =		THIS_MODULE,
 	.name =			"Philips webcam",	/* name */
 	.id_table =		pwc_device_table,
 	.probe =		usb_pwc_probe,		/* probe() */
diff --git a/drivers/usb/media/se401.c b/drivers/usb/media/se401.c
index f69e443cd1bc..b2ae29af5940 100644
--- a/drivers/usb/media/se401.c
+++ b/drivers/usb/media/se401.c
@@ -1401,7 +1401,6 @@ static void se401_disconnect(struct usb_interface *intf)
 }
 
 static struct usb_driver se401_driver = {
-	.owner		= THIS_MODULE,
         .name		= "se401",
         .id_table	= device_table,
 	.probe		= se401_probe,
diff --git a/drivers/usb/media/sn9c102_core.c b/drivers/usb/media/sn9c102_core.c
index b2e66e3b90aa..8d1a1c357d5a 100644
--- a/drivers/usb/media/sn9c102_core.c
+++ b/drivers/usb/media/sn9c102_core.c
@@ -1316,7 +1316,7 @@ static int sn9c102_init(struct sn9c102_device* cam)
 	struct v4l2_control ctrl;
 	struct v4l2_queryctrl *qctrl;
 	struct v4l2_rect* rect;
-	u8 i = 0, n = 0;
+	u8 i = 0;
 	int err = 0;
 
 	if (!(cam->state & DEV_INITIALIZED)) {
@@ -1352,7 +1352,7 @@ static int sn9c102_init(struct sn9c102_device* cam)
 		return err;
 
 	if (s->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X)
-		DBG(3, "Compressed video format is active, quality %d", 
+		DBG(3, "Compressed video format is active, quality %d",
 		    cam->compression.quality)
 	else
 		DBG(3, "Uncompressed video format is active")
@@ -1364,9 +1364,8 @@ static int sn9c102_init(struct sn9c102_device* cam)
 		}
 
 	if (s->set_ctrl) {
-		n = sizeof(s->qctrl) / sizeof(s->qctrl[0]);
-		for (i = 0; i < n; i++)
-			if (s->qctrl[i].id != 0 && 
+		for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
+			if (s->qctrl[i].id != 0 &&
 			    !(s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED)) {
 				ctrl.id = s->qctrl[i].id;
 				ctrl.value = qctrl[i].default_value;
@@ -1388,7 +1387,7 @@ static int sn9c102_init(struct sn9c102_device* cam)
 		init_waitqueue_head(&cam->wait_stream);
 		cam->nreadbuffers = 2;
 		memcpy(s->_qctrl, s->qctrl, sizeof(s->qctrl));
-		memcpy(&(s->_rect), &(s->cropcap.defrect), 
+		memcpy(&(s->_rect), &(s->cropcap.defrect),
 		       sizeof(struct v4l2_rect));
 		cam->state |= DEV_INITIALIZED;
 	}
@@ -1810,13 +1809,12 @@ static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp,
 	{
 		struct sn9c102_sensor* s = cam->sensor;
 		struct v4l2_queryctrl qc;
-		u8 i, n;
+		u8 i;
 
 		if (copy_from_user(&qc, arg, sizeof(qc)))
 			return -EFAULT;
 
-		n = sizeof(s->qctrl) / sizeof(s->qctrl[0]);
-		for (i = 0; i < n; i++)
+		for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
 			if (qc.id && qc.id == s->qctrl[i].id) {
 				memcpy(&qc, &(s->qctrl[i]), sizeof(qc));
 				if (copy_to_user(arg, &qc, sizeof(qc)))
@@ -1852,7 +1850,7 @@ static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp,
 	{
 		struct sn9c102_sensor* s = cam->sensor;
 		struct v4l2_control ctrl;
-		u8 i, n;
+		u8 i;
 		int err = 0;
 
 		if (!s->set_ctrl)
@@ -1861,8 +1859,7 @@ static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp,
 		if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
 			return -EFAULT;
 
-		n = sizeof(s->qctrl) / sizeof(s->qctrl[0]);
-		for (i = 0; i < n; i++)
+		for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
 			if (ctrl.id == s->qctrl[i].id) {
 				if (ctrl.value < s->qctrl[i].minimum ||
 				    ctrl.value > s->qctrl[i].maximum)
@@ -2544,7 +2541,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
 	unsigned int i, n;
 	int err = 0, r;
 
-	n = sizeof(sn9c102_id_table)/sizeof(sn9c102_id_table[0]);
+	n = ARRAY_SIZE(sn9c102_id_table);
 	for (i = 0; i < n-1; i++)
 		if (le16_to_cpu(udev->descriptor.idVendor) == 
 		    sn9c102_id_table[i].idVendor &&
@@ -2711,7 +2708,6 @@ static void sn9c102_usb_disconnect(struct usb_interface* intf)
 
 
 static struct usb_driver sn9c102_usb_driver = {
-	.owner =      THIS_MODULE,
 	.name =       "sn9c102",
 	.id_table =   sn9c102_id_table,
 	.probe =      sn9c102_usb_probe,
diff --git a/drivers/usb/media/stv680.c b/drivers/usb/media/stv680.c
index 0fd0fa9fec21..774038b352cd 100644
--- a/drivers/usb/media/stv680.c
+++ b/drivers/usb/media/stv680.c
@@ -1477,7 +1477,6 @@ static void stv680_disconnect (struct usb_interface *intf)
 }
 
 static struct usb_driver stv680_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"stv680",
 	.probe =	stv680_probe,
 	.disconnect =	stv680_disconnect,
diff --git a/drivers/usb/media/stv680.h b/drivers/usb/media/stv680.h
index 445940612603..b0551cdb280b 100644
--- a/drivers/usb/media/stv680.h
+++ b/drivers/usb/media/stv680.h
@@ -151,7 +151,7 @@ struct usb_stv {
 };
 
 
-static unsigned char red[256] = { 
+static const unsigned char red[256] = {
 	0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 
 	18, 18, 18, 18, 18, 18, 18, 25, 30, 35, 38, 42, 
 	44, 47, 50, 53, 54, 57, 59, 61, 63, 65, 67, 69, 
@@ -176,7 +176,7 @@ static unsigned char red[256] = {
 	220, 220, 221, 221 
 }; 
 
-static unsigned char green[256] = {
+static const unsigned char green[256] = {
 	0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 
 	21, 21, 21, 21, 21, 21, 21, 28, 34, 39, 43, 47, 
 	50, 53, 56, 59, 61, 64, 66, 68, 71, 73, 75, 77, 
@@ -201,7 +201,7 @@ static unsigned char green[256] = {
 	245, 245, 246, 246 
 }; 
 
-static unsigned char blue[256] = {
+static const unsigned char blue[256] = {
 	0, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 
 	23, 23, 23, 23, 23, 23, 23, 30, 37, 42, 47, 51, 
 	55, 58, 61, 64, 67, 70, 72, 74, 78, 80, 82, 84, 
diff --git a/drivers/usb/media/usbvideo.c b/drivers/usb/media/usbvideo.c
index 24efb21969c6..4bd113325ef9 100644
--- a/drivers/usb/media/usbvideo.c
+++ b/drivers/usb/media/usbvideo.c
@@ -725,7 +725,7 @@ int usbvideo_register(
 		/* Allocate user_data separately because of kmalloc's limits */
 		if (num_extra > 0) {
 			up->user_size = num_cams * num_extra;
-			up->user_data = (char *) kmalloc(up->user_size, GFP_KERNEL);
+			up->user_data = kmalloc(up->user_size, GFP_KERNEL);
 			if (up->user_data == NULL) {
 				err("%s: Failed to allocate user_data (%d. bytes)",
 				    __FUNCTION__, up->user_size);
@@ -955,7 +955,7 @@ static struct file_operations usbvideo_fops = {
 	.ioctl =  usbvideo_v4l_ioctl,
 	.llseek = no_llseek,
 };
-static struct video_device usbvideo_template = {
+static const struct video_device usbvideo_template = {
 	.owner =      THIS_MODULE,
 	.type =       VID_TYPE_CAPTURE,
 	.hardware =   VID_HARDWARE_CPIA,
diff --git a/drivers/usb/media/vicam.c b/drivers/usb/media/vicam.c
index 0bc0b1247a6b..1c73155c8d77 100644
--- a/drivers/usb/media/vicam.c
+++ b/drivers/usb/media/vicam.c
@@ -1257,7 +1257,6 @@ static struct usb_device_id vicam_table[] = {
 MODULE_DEVICE_TABLE(usb, vicam_table);
 
 static struct usb_driver vicam_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "vicam",
 	.probe		= vicam_probe,
 	.disconnect	= vicam_disconnect,
diff --git a/drivers/usb/media/w9968cf.c b/drivers/usb/media/w9968cf.c
index 67612c81cb9f..3605a6f3067b 100644
--- a/drivers/usb/media/w9968cf.c
+++ b/drivers/usb/media/w9968cf.c
@@ -1533,12 +1533,12 @@ static int w9968cf_i2c_attach_inform(struct i2c_client* client)
 		}
 	} else {
 		DBG(4, "Rejected client [%s] with driver [%s]", 
-		    client->name, client->driver->name)
+		    client->name, client->driver->driver.name)
 		return -EINVAL;
 	}
 
 	DBG(5, "I2C attach client [%s] with driver [%s]",
-	    client->name, client->driver->name)
+	    client->name, client->driver->driver.name)
 
 	return 0;
 }
@@ -2958,7 +2958,7 @@ static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp,
 	};
 
 	#define V4L1_IOCTL(cmd) \
-	        ((_IOC_NR((cmd)) < sizeof(v4l1_ioctls)/sizeof(char*)) ? \
+	        ((_IOC_NR((cmd)) < ARRAY_SIZE(v4l1_ioctls)) ? \
 	        v4l1_ioctls[_IOC_NR((cmd))] : "?")
 
 	cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp));
@@ -3554,7 +3554,7 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
 
 
 	/* Allocate 2 bytes of memory for camera control USB transfers */
-	if (!(cam->control_buffer = (u16*)kmalloc(2, GFP_KERNEL))) {
+	if (!(cam->control_buffer = kmalloc(2, GFP_KERNEL))) {
 		DBG(1,"Couldn't allocate memory for camera control transfers")
 		err = -ENOMEM;
 		goto fail;
@@ -3562,7 +3562,7 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
 	memset(cam->control_buffer, 0, 2);
 
 	/* Allocate 8 bytes of memory for USB data transfers to the FSB */
-	if (!(cam->data_buffer = (u16*)kmalloc(8, GFP_KERNEL))) {
+	if (!(cam->data_buffer = kmalloc(8, GFP_KERNEL))) {
 		DBG(1, "Couldn't allocate memory for data "
 		       "transfers to the FSB")
 		err = -ENOMEM;
@@ -3668,7 +3668,6 @@ static void w9968cf_usb_disconnect(struct usb_interface* intf)
 
 
 static struct usb_driver w9968cf_usb_driver = {
-	.owner =      THIS_MODULE,
 	.name =       "w9968cf",
 	.id_table =   winbond_id_table,
 	.probe =      w9968cf_usb_probe,
diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c
index b293db3c28c3..449b2501acf3 100644
--- a/drivers/usb/misc/auerswald.c
+++ b/drivers/usb/misc/auerswald.c
@@ -767,7 +767,7 @@ static int auerbuf_setup (pauerbufctl_t bcp, unsigned int numElements, unsigned
 	        memset (bep, 0, sizeof (auerbuf_t));
                 bep->list = bcp;
                 INIT_LIST_HEAD (&bep->buff_list);
-                bep->bufp = (char *) kmalloc (bufsize, GFP_KERNEL);
+                bep->bufp = kmalloc (bufsize, GFP_KERNEL);
                 if (!bep->bufp)
 			goto bl_fail;
                 bep->dr = (struct usb_ctrlrequest *) kmalloc (sizeof (struct usb_ctrlrequest), GFP_KERNEL);
@@ -1123,7 +1123,7 @@ static int auerswald_int_open (pauerswald_t cp)
                 }
         }
         if (!cp->intbufp) {
-                cp->intbufp = (char *) kmalloc (irqsize, GFP_KERNEL);
+                cp->intbufp = kmalloc (irqsize, GFP_KERNEL);
                 if (!cp->intbufp) {
                         ret = -ENOMEM;
                         goto intoend;
@@ -2103,7 +2103,6 @@ MODULE_DEVICE_TABLE (usb, auerswald_ids);
 
 /* Standard usb driver struct */
 static struct usb_driver auerswald_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"auerswald",
 	.probe =	auerswald_probe,
 	.disconnect =	auerswald_disconnect,
diff --git a/drivers/usb/misc/cytherm.c b/drivers/usb/misc/cytherm.c
index b33044d56a1e..6671317b495f 100644
--- a/drivers/usb/misc/cytherm.c
+++ b/drivers/usb/misc/cytherm.c
@@ -50,7 +50,6 @@ static void cytherm_disconnect(struct usb_interface *interface);
 
 /* usb specific object needed to register this driver with the usb subsystem */
 static struct usb_driver cytherm_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"cytherm",
 	.probe =	cytherm_probe,
 	.disconnect =	cytherm_disconnect,
diff --git a/drivers/usb/misc/emi26.c b/drivers/usb/misc/emi26.c
index c8155209bf4b..3824df33094e 100644
--- a/drivers/usb/misc/emi26.c
+++ b/drivers/usb/misc/emi26.c
@@ -227,7 +227,6 @@ static void emi26_disconnect(struct usb_interface *intf)
 }
 
 static struct usb_driver emi26_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "emi26 - firmware loader",
 	.probe		= emi26_probe,
 	.disconnect	= emi26_disconnect,
diff --git a/drivers/usb/misc/emi62.c b/drivers/usb/misc/emi62.c
index 189986af2ac7..52fea2e08db8 100644
--- a/drivers/usb/misc/emi62.c
+++ b/drivers/usb/misc/emi62.c
@@ -266,7 +266,6 @@ static void emi62_disconnect(struct usb_interface *intf)
 }
 
 static struct usb_driver emi62_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "emi62 - firmware loader",
 	.probe		= emi62_probe,
 	.disconnect	= emi62_disconnect,
diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c
index 1dc3e0f73014..d8cde1017985 100644
--- a/drivers/usb/misc/idmouse.c
+++ b/drivers/usb/misc/idmouse.c
@@ -114,7 +114,6 @@ static struct usb_class_driver idmouse_class = {
 
 /* usb specific object needed to register this driver with the usb subsystem */
 static struct usb_driver idmouse_driver = {
-	.owner = THIS_MODULE,
 	.name = DRIVER_SHORT,
 	.probe = idmouse_probe,
 	.disconnect = idmouse_disconnect,
diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c
index 7e93ac96490f..981d8a5fbfd9 100644
--- a/drivers/usb/misc/ldusb.c
+++ b/drivers/usb/misc/ldusb.c
@@ -763,7 +763,6 @@ static void ld_usb_disconnect(struct usb_interface *intf)
 
 /* usb specific object needed to register this driver with the usb subsystem */
 static struct usb_driver ld_usb_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"ldusb",
 	.probe =	ld_usb_probe,
 	.disconnect =	ld_usb_disconnect,
diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c
index 2703e205bc8f..1336745b8f55 100644
--- a/drivers/usb/misc/legousbtower.c
+++ b/drivers/usb/misc/legousbtower.c
@@ -282,7 +282,6 @@ static struct usb_class_driver tower_class = {
 
 /* usb specific object needed to register this driver with the usb subsystem */
 static struct usb_driver tower_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"legousbtower",
 	.probe =	tower_probe,
 	.disconnect =	tower_disconnect,
diff --git a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c
index 067a81486921..605a3c87e05c 100644
--- a/drivers/usb/misc/phidgetkit.c
+++ b/drivers/usb/misc/phidgetkit.c
@@ -555,7 +555,6 @@ static void interfacekit_disconnect(struct usb_interface *interface)
 }
 
 static struct usb_driver interfacekit_driver = {
-	.owner = THIS_MODULE,
 	.name = "phidgetkit",
 	.probe = interfacekit_probe,
 	.disconnect = interfacekit_disconnect,
diff --git a/drivers/usb/misc/phidgetservo.c b/drivers/usb/misc/phidgetservo.c
index a30d4a6ee824..b3418d2bcc69 100644
--- a/drivers/usb/misc/phidgetservo.c
+++ b/drivers/usb/misc/phidgetservo.c
@@ -306,7 +306,6 @@ servo_disconnect(struct usb_interface *interface)
 }
 
 static struct usb_driver servo_driver = {
-	.owner = THIS_MODULE,
 	.name = "phidgetservo",
 	.probe = servo_probe,
 	.disconnect = servo_disconnect,
diff --git a/drivers/usb/misc/rio500.c b/drivers/usb/misc/rio500.c
index 9590dbac5d9a..384fa3769805 100644
--- a/drivers/usb/misc/rio500.c
+++ b/drivers/usb/misc/rio500.c
@@ -465,14 +465,14 @@ static int probe_rio(struct usb_interface *intf,
 
 	rio->rio_dev = dev;
 
-	if (!(rio->obuf = (char *) kmalloc(OBUF_SIZE, GFP_KERNEL))) {
+	if (!(rio->obuf = kmalloc(OBUF_SIZE, GFP_KERNEL))) {
 		err("probe_rio: Not enough memory for the output buffer");
 		usb_deregister_dev(intf, &usb_rio_class);
 		return -ENOMEM;
 	}
 	dbg("probe_rio: obuf address:%p", rio->obuf);
 
-	if (!(rio->ibuf = (char *) kmalloc(IBUF_SIZE, GFP_KERNEL))) {
+	if (!(rio->ibuf = kmalloc(IBUF_SIZE, GFP_KERNEL))) {
 		err("probe_rio: Not enough memory for the input buffer");
 		usb_deregister_dev(intf, &usb_rio_class);
 		kfree(rio->obuf);
@@ -522,7 +522,6 @@ static struct usb_device_id rio_table [] = {
 MODULE_DEVICE_TABLE (usb, rio_table);
 
 static struct usb_driver rio_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"rio500",
 	.probe =	probe_rio,
 	.disconnect =	disconnect_rio,
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
index 41ef2b606751..3260d595441f 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.c
+++ b/drivers/usb/misc/sisusbvga/sisusb.c
@@ -863,9 +863,6 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
 
 	    switch (length) {
 
-		case 0:
-			return ret;
-
 		case 1:
 			if (userbuffer) {
 				if (get_user(swap8, (u8 __user *)userbuffer))
@@ -1221,9 +1218,6 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
 
 	    switch (length) {
 
-		case 0:
-			return ret;
-
 		case 1:
 
 			ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM,
@@ -2443,8 +2437,8 @@ sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init)
 	u8 *tempbuf;
 	u16 *tempbufb;
 	size_t written;
-	static char bootstring[] = "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer.";
-	static char bootlogo[] = "(o_ //\\ V_/_";
+	static const char bootstring[] = "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer.";
+	static const char bootlogo[] = "(o_ //\\ V_/_";
 
 	/* sisusb->lock is down */
 
@@ -3489,7 +3483,6 @@ static struct usb_device_id sisusb_table [] = {
 MODULE_DEVICE_TABLE (usb, sisusb_table);
 
 static struct usb_driver sisusb_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"sisusb",
 	.probe =	sisusb_probe,
 	.disconnect =	sisusb_disconnect,
diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c
index 85f3725334b0..cc3dae3f34e0 100644
--- a/drivers/usb/misc/usblcd.c
+++ b/drivers/usb/misc/usblcd.c
@@ -371,7 +371,6 @@ static void lcd_disconnect(struct usb_interface *interface)
 }
 
 static struct usb_driver lcd_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"usblcd",
 	.probe =	lcd_probe,
 	.disconnect =	lcd_disconnect,
diff --git a/drivers/usb/misc/usbled.c b/drivers/usb/misc/usbled.c
index 3c93921cb6b3..877b081a3a6e 100644
--- a/drivers/usb/misc/usbled.c
+++ b/drivers/usb/misc/usbled.c
@@ -148,7 +148,6 @@ static void led_disconnect(struct usb_interface *interface)
 }
 
 static struct usb_driver led_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"usbled",
 	.probe =	led_probe,
 	.disconnect =	led_disconnect,
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index 605a2afe34ed..84fa1728f052 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -2134,7 +2134,6 @@ static struct usb_device_id id_table [] = {
 MODULE_DEVICE_TABLE (usb, id_table);
 
 static struct usb_driver usbtest_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"usbtest",
 	.id_table =	id_table,
 	.probe =	usbtest_probe,
diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c
index 1cabe7ed91f5..4081990b7d1a 100644
--- a/drivers/usb/misc/uss720.c
+++ b/drivers/usb/misc/uss720.c
@@ -780,7 +780,6 @@ MODULE_DEVICE_TABLE (usb, uss720_table);
 
 
 static struct usb_driver uss720_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"uss720",
 	.probe =	uss720_probe,
 	.disconnect =	uss720_disconnect,
diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c
index 17d0190ef64e..611612146ae9 100644
--- a/drivers/usb/mon/mon_text.c
+++ b/drivers/usb/mon/mon_text.c
@@ -97,19 +97,12 @@ static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb,
 	if (len >= DATA_MAX)
 		len = DATA_MAX;
 
-	/*
-	 * Bulk is easy to shortcut reliably. 
-	 * XXX Other pipe types need consideration. Currently, we overdo it
-	 * and collect garbage for them: better more than less.
-	 */
-	if (usb_pipebulk(pipe) || usb_pipecontrol(pipe)) {
-		if (usb_pipein(pipe)) {
-			if (ev_type == 'S')
-				return '<';
-		} else {
-			if (ev_type == 'C')
-				return '>';
-		}
+	if (usb_pipein(pipe)) {
+		if (ev_type == 'S')
+			return '<';
+	} else {
+		if (ev_type == 'C')
+			return '>';
 	}
 
 	/*
diff --git a/drivers/usb/net/asix.c b/drivers/usb/net/asix.c
index 542120ef1fd2..541181695040 100644
--- a/drivers/usb/net/asix.c
+++ b/drivers/usb/net/asix.c
@@ -912,13 +912,16 @@ static const struct usb_device_id	products [] = {
 	// ASIX AX88772 10/100
         USB_DEVICE (0x0b95, 0x7720),
         .driver_info = (unsigned long) &ax88772_info,
+}, {
+	// Linksys USB200M Rev 2
+	USB_DEVICE (0x13b1, 0x0018),
+	.driver_info = (unsigned long) &ax88772_info,
 },
 	{ },		// END
 };
 MODULE_DEVICE_TABLE(usb, products);
 
 static struct usb_driver asix_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"asix",
 	.id_table =	products,
 	.probe =	usbnet_probe,
diff --git a/drivers/usb/net/catc.c b/drivers/usb/net/catc.c
index 37ef365a2472..be5f5e142dd0 100644
--- a/drivers/usb/net/catc.c
+++ b/drivers/usb/net/catc.c
@@ -934,7 +934,6 @@ static struct usb_device_id catc_id_table [] = {
 MODULE_DEVICE_TABLE(usb, catc_id_table);
 
 static struct usb_driver catc_driver = {
-	.owner =	THIS_MODULE,
 	.name =		driver_name,
 	.probe =	catc_probe,
 	.disconnect =	catc_disconnect,
diff --git a/drivers/usb/net/cdc_ether.c b/drivers/usb/net/cdc_ether.c
index c008c981862b..63f1f3ba8e0b 100644
--- a/drivers/usb/net/cdc_ether.c
+++ b/drivers/usb/net/cdc_ether.c
@@ -476,7 +476,6 @@ static const struct usb_device_id	products [] = {
 MODULE_DEVICE_TABLE(usb, products);
 
 static struct usb_driver cdc_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"cdc_ether",
 	.id_table =	products,
 	.probe =	usbnet_probe,
diff --git a/drivers/usb/net/cdc_subset.c b/drivers/usb/net/cdc_subset.c
index f05cfb83c82d..ec801e8bb1bb 100644
--- a/drivers/usb/net/cdc_subset.c
+++ b/drivers/usb/net/cdc_subset.c
@@ -306,7 +306,6 @@ MODULE_DEVICE_TABLE(usb, products);
 /*-------------------------------------------------------------------------*/
 
 static struct usb_driver cdc_subset_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"cdc_subset",
 	.probe =	usbnet_probe,
 	.suspend =	usbnet_suspend,
diff --git a/drivers/usb/net/gl620a.c b/drivers/usb/net/gl620a.c
index 2455e9a85674..faf1e86be687 100644
--- a/drivers/usb/net/gl620a.c
+++ b/drivers/usb/net/gl620a.c
@@ -377,7 +377,6 @@ static const struct usb_device_id	products [] = {
 MODULE_DEVICE_TABLE(usb, products);
 
 static struct usb_driver gl620a_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"gl620a",
 	.id_table =	products,
 	.probe =	usbnet_probe,
diff --git a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c
index b5776518020f..def3bb8e2290 100644
--- a/drivers/usb/net/kaweth.c
+++ b/drivers/usb/net/kaweth.c
@@ -175,7 +175,6 @@ MODULE_DEVICE_TABLE (usb, usb_klsi_table);
  *     kaweth_driver
  ****************************************************************/
 static struct usb_driver kaweth_driver = {
-	.owner =	THIS_MODULE,
 	.name =		driver_name,
 	.probe =	kaweth_probe,
 	.disconnect =	kaweth_disconnect,
diff --git a/drivers/usb/net/net1080.c b/drivers/usb/net/net1080.c
index b3799b1a2b0d..78e6a43b1087 100644
--- a/drivers/usb/net/net1080.c
+++ b/drivers/usb/net/net1080.c
@@ -593,7 +593,6 @@ static const struct usb_device_id	products [] = {
 MODULE_DEVICE_TABLE(usb, products);
 
 static struct usb_driver net1080_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"net1080",
 	.id_table =	products,
 	.probe =	usbnet_probe,
diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c
index 683e3df5d607..156a2f1cb39a 100644
--- a/drivers/usb/net/pegasus.c
+++ b/drivers/usb/net/pegasus.c
@@ -45,7 +45,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v0.6.12 (2005/01/13)"
+#define DRIVER_VERSION "v0.6.13 (2005/11/13)"
 #define DRIVER_AUTHOR "Petko Manolov <petkan@users.sourceforge.net>"
 #define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver"
 
@@ -57,12 +57,14 @@ static const char driver_name[] = "pegasus";
 
 static int loopback = 0;
 static int mii_mode = 0;
+static char *devid=NULL;
 
 static struct usb_eth_dev usb_dev_id[] = {
 #define	PEGASUS_DEV(pn, vid, pid, flags)	\
 	{.name = pn, .vendor = vid, .device = pid, .private = flags},
 #include "pegasus.h"
 #undef	PEGASUS_DEV
+	{NULL, 0, 0, 0},
 	{NULL, 0, 0, 0}
 };
 
@@ -71,6 +73,7 @@ static struct usb_device_id pegasus_ids[] = {
 	{.match_flags = USB_DEVICE_ID_MATCH_DEVICE, .idVendor = vid, .idProduct = pid},
 #include "pegasus.h"
 #undef	PEGASUS_DEV
+	{},
 	{}
 };
 
@@ -79,8 +82,10 @@ MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 module_param(loopback, bool, 0);
 module_param(mii_mode, bool, 0);
+module_param(devid, charp, 0);
 MODULE_PARM_DESC(loopback, "Enable MAC loopback mode (bit 0)");
 MODULE_PARM_DESC(mii_mode, "Enable HomePNA mode (bit 0),default=MII mode = 0");
+MODULE_PARM_DESC(devid, "The format is: 'DEV_name:VendorID:DeviceID:Flags'");
 
 /* use ethtool to change the level for any given device */
 static int msg_level = -1;
@@ -113,7 +118,7 @@ static void ctrl_callback(struct urb *urb, struct pt_regs *regs)
 		break;
 	default:
 		if (netif_msg_drv(pegasus))
-			dev_err(&pegasus->intf->dev, "%s, status %d\n",
+			dev_dbg(&pegasus->intf->dev, "%s, status %d\n",
 				__FUNCTION__, urb->status);
 	}
 	pegasus->flags &= ~ETH_REGS_CHANGED;
@@ -308,9 +313,9 @@ static int read_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 * regd)
 	__le16 regdi;
 	int ret;
 
-	ret = set_register(pegasus, PhyCtrl, 0);
-	ret = set_registers(pegasus, PhyAddr, sizeof (data), data);
-	ret = set_register(pegasus, PhyCtrl, (indx | PHY_READ));
+	set_register(pegasus, PhyCtrl, 0);
+	set_registers(pegasus, PhyAddr, sizeof (data), data);
+	set_register(pegasus, PhyCtrl, (indx | PHY_READ));
 	for (i = 0; i < REG_TIMEOUT; i++) {
 		ret = get_registers(pegasus, PhyCtrl, 1, data);
 		if (data[0] & PHY_DONE)
@@ -319,12 +324,12 @@ static int read_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 * regd)
 	if (i < REG_TIMEOUT) {
 		ret = get_registers(pegasus, PhyData, 2, &regdi);
 		*regd = le16_to_cpu(regdi);
-		return 1;
+		return ret;
 	}
 	if (netif_msg_drv(pegasus))
 		dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
 
-	return 0;
+	return ret;
 }
 
 static int mdio_read(struct net_device *dev, int phy_id, int loc)
@@ -344,20 +349,20 @@ static int write_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 regd)
 
 	data[1] = (u8) regd;
 	data[2] = (u8) (regd >> 8);
-	ret = set_register(pegasus, PhyCtrl, 0);
-	ret = set_registers(pegasus, PhyAddr, sizeof(data), data);
-	ret = set_register(pegasus, PhyCtrl, (indx | PHY_WRITE));
+	set_register(pegasus, PhyCtrl, 0);
+	set_registers(pegasus, PhyAddr, sizeof(data), data);
+	set_register(pegasus, PhyCtrl, (indx | PHY_WRITE));
 	for (i = 0; i < REG_TIMEOUT; i++) {
 		ret = get_registers(pegasus, PhyCtrl, 1, data);
 		if (data[0] & PHY_DONE)
 			break;
 	}
 	if (i < REG_TIMEOUT)
-		return 0;
+		return ret;
 
 	if (netif_msg_drv(pegasus))
 		dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
-	return 1;
+	return -ETIMEDOUT;
 }
 
 static void mdio_write(struct net_device *dev, int phy_id, int loc, int val)
@@ -374,9 +379,9 @@ static int read_eprom_word(pegasus_t * pegasus, __u8 index, __u16 * retdata)
 	__le16 retdatai;
 	int ret;
 
-	ret = set_register(pegasus, EpromCtrl, 0);
-	ret = set_register(pegasus, EpromOffset, index);
-	ret = set_register(pegasus, EpromCtrl, EPROM_READ);
+	set_register(pegasus, EpromCtrl, 0);
+	set_register(pegasus, EpromOffset, index);
+	set_register(pegasus, EpromCtrl, EPROM_READ);
 
 	for (i = 0; i < REG_TIMEOUT; i++) {
 		ret = get_registers(pegasus, EpromCtrl, 1, &tmp);
@@ -386,12 +391,12 @@ static int read_eprom_word(pegasus_t * pegasus, __u8 index, __u16 * retdata)
 	if (i < REG_TIMEOUT) {
 		ret = get_registers(pegasus, EpromData, 2, &retdatai);
 		*retdata = le16_to_cpu(retdatai);
-		return 0;
+		return ret;
 	}
 
 	if (netif_msg_drv(pegasus))
 		dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
-	return -1;
+	return -ETIMEDOUT;
 }
 
 #ifdef	PEGASUS_WRITE_EEPROM
@@ -400,8 +405,8 @@ static inline void enable_eprom_write(pegasus_t * pegasus)
 	__u8 tmp;
 	int ret;
 
-	ret = get_registers(pegasus, EthCtrl2, 1, &tmp);
-	ret = set_register(pegasus, EthCtrl2, tmp | EPROM_WR_ENABLE);
+	get_registers(pegasus, EthCtrl2, 1, &tmp);
+	set_register(pegasus, EthCtrl2, tmp | EPROM_WR_ENABLE);
 }
 
 static inline void disable_eprom_write(pegasus_t * pegasus)
@@ -409,9 +414,9 @@ static inline void disable_eprom_write(pegasus_t * pegasus)
 	__u8 tmp;
 	int ret;
 
-	ret = get_registers(pegasus, EthCtrl2, 1, &tmp);
-	ret = set_register(pegasus, EpromCtrl, 0);
-	ret = set_register(pegasus, EthCtrl2, tmp & ~EPROM_WR_ENABLE);
+	get_registers(pegasus, EthCtrl2, 1, &tmp);
+	set_register(pegasus, EpromCtrl, 0);
+	set_register(pegasus, EthCtrl2, tmp & ~EPROM_WR_ENABLE);
 }
 
 static int write_eprom_word(pegasus_t * pegasus, __u8 index, __u16 data)
@@ -420,11 +425,11 @@ static int write_eprom_word(pegasus_t * pegasus, __u8 index, __u16 data)
 	__u8 tmp, d[4] = { 0x3f, 0, 0, EPROM_WRITE };
 	int ret;
 
-	ret = set_registers(pegasus, EpromOffset, 4, d);
+	set_registers(pegasus, EpromOffset, 4, d);
 	enable_eprom_write(pegasus);
-	ret = set_register(pegasus, EpromOffset, index);
-	ret = set_registers(pegasus, EpromData, 2, &data);
-	ret = set_register(pegasus, EpromCtrl, EPROM_WRITE);
+	set_register(pegasus, EpromOffset, index);
+	set_registers(pegasus, EpromData, 2, &data);
+	set_register(pegasus, EpromCtrl, EPROM_WRITE);
 
 	for (i = 0; i < REG_TIMEOUT; i++) {
 		ret = get_registers(pegasus, EpromCtrl, 1, &tmp);
@@ -433,10 +438,10 @@ static int write_eprom_word(pegasus_t * pegasus, __u8 index, __u16 data)
 	}
 	disable_eprom_write(pegasus);
 	if (i < REG_TIMEOUT)
-		return 0;
+		return ret;
 	if (netif_msg_drv(pegasus))
 		dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
-	return -1;
+	return -ETIMEDOUT;
 }
 #endif				/* PEGASUS_WRITE_EEPROM */
 
@@ -454,10 +459,9 @@ static inline void get_node_id(pegasus_t * pegasus, __u8 * id)
 static void set_ethernet_addr(pegasus_t * pegasus)
 {
 	__u8 node_id[6];
-	int ret;
 
 	get_node_id(pegasus, node_id);
-	ret = set_registers(pegasus, EthID, sizeof (node_id), node_id);
+	set_registers(pegasus, EthID, sizeof (node_id), node_id);
 	memcpy(pegasus->net->dev_addr, node_id, sizeof (node_id));
 }
 
@@ -465,30 +469,29 @@ static inline int reset_mac(pegasus_t * pegasus)
 {
 	__u8 data = 0x8;
 	int i;
-	int ret;
 
-	ret = set_register(pegasus, EthCtrl1, data);
+	set_register(pegasus, EthCtrl1, data);
 	for (i = 0; i < REG_TIMEOUT; i++) {
-		ret = get_registers(pegasus, EthCtrl1, 1, &data);
+		get_registers(pegasus, EthCtrl1, 1, &data);
 		if (~data & 0x08) {
 			if (loopback & 1)
 				break;
 			if (mii_mode && (pegasus->features & HAS_HOME_PNA))
-				ret = set_register(pegasus, Gpio1, 0x34);
+				set_register(pegasus, Gpio1, 0x34);
 			else
-				ret = set_register(pegasus, Gpio1, 0x26);
-			ret = set_register(pegasus, Gpio0, pegasus->features);
-			ret = set_register(pegasus, Gpio0, DEFAULT_GPIO_SET);
+				set_register(pegasus, Gpio1, 0x26);
+			set_register(pegasus, Gpio0, pegasus->features);
+			set_register(pegasus, Gpio0, DEFAULT_GPIO_SET);
 			break;
 		}
 	}
 	if (i == REG_TIMEOUT)
-		return 1;
+		return -ETIMEDOUT;
 
 	if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_LINKSYS ||
 	    usb_dev_id[pegasus->dev_index].vendor == VENDOR_DLINK) {
-		ret = set_register(pegasus, Gpio0, 0x24);
-		ret = set_register(pegasus, Gpio0, 0x26);
+		set_register(pegasus, Gpio0, 0x24);
+		set_register(pegasus, Gpio0, 0x26);
 	}
 	if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_ELCON) {
 		__u16 auxmode;
@@ -527,7 +530,7 @@ static int enable_net_traffic(struct net_device *dev, struct usb_device *usb)
 		write_mii_word(pegasus, 0, 0x1b, auxmode | 4);
 	}
 
-	return 0;
+	return ret;
 }
 
 static void fill_skb_pool(pegasus_t * pegasus)
@@ -881,9 +884,8 @@ static struct net_device_stats *pegasus_netdev_stats(struct net_device *dev)
 static inline void disable_net_traffic(pegasus_t * pegasus)
 {
 	int tmp = 0;
-	int ret;
 
-	ret = set_registers(pegasus, EthCtrl0, 2, &tmp);
+	set_registers(pegasus, EthCtrl0, 2, &tmp);
 }
 
 static inline void get_interrupt_interval(pegasus_t * pegasus)
@@ -1206,18 +1208,17 @@ static __u8 mii_phy_probe(pegasus_t * pegasus)
 static inline void setup_pegasus_II(pegasus_t * pegasus)
 {
 	__u8 data = 0xa5;
-	int ret;
 	
-	ret = set_register(pegasus, Reg1d, 0);
-	ret = set_register(pegasus, Reg7b, 1);
+	set_register(pegasus, Reg1d, 0);
+	set_register(pegasus, Reg7b, 1);
 	mdelay(100);
 	if ((pegasus->features & HAS_HOME_PNA) && mii_mode)
-		ret = set_register(pegasus, Reg7b, 0);
+		set_register(pegasus, Reg7b, 0);
 	else
-		ret = set_register(pegasus, Reg7b, 2);
+		set_register(pegasus, Reg7b, 2);
 
-	ret = set_register(pegasus, 0x83, data);
-	ret = get_registers(pegasus, 0x83, 1, &data);
+	set_register(pegasus, 0x83, data);
+	get_registers(pegasus, 0x83, 1, &data);
 
 	if (data == 0xa5) {
 		pegasus->chip = 0x8513;
@@ -1225,14 +1226,14 @@ static inline void setup_pegasus_II(pegasus_t * pegasus)
 		pegasus->chip = 0;
 	}
 
-	ret = set_register(pegasus, 0x80, 0xc0);
-	ret = set_register(pegasus, 0x83, 0xff);
-	ret = set_register(pegasus, 0x84, 0x01);
+	set_register(pegasus, 0x80, 0xc0);
+	set_register(pegasus, 0x83, 0xff);
+	set_register(pegasus, 0x84, 0x01);
 	
 	if (pegasus->features & HAS_HOME_PNA && mii_mode)
-		ret = set_register(pegasus, Reg81, 6);
+		set_register(pegasus, Reg81, 6);
 	else
-		ret = set_register(pegasus, Reg81, 2);
+		set_register(pegasus, Reg81, 2);
 }
 
 
@@ -1414,9 +1415,42 @@ static struct usb_driver pegasus_driver = {
 	.resume = pegasus_resume,
 };
 
+static void parse_id(char *id)
+{
+	unsigned int vendor_id=0, device_id=0, flags=0, i=0;
+	char *token, *name=NULL;
+
+	if ((token = strsep(&id, ":")) != NULL)
+		name = token;
+	/* name now points to a null terminated string*/
+	if ((token = strsep(&id, ":")) != NULL)
+		vendor_id = simple_strtoul(token, NULL, 16);
+	if ((token = strsep(&id, ":")) != NULL)
+		device_id = simple_strtoul(token, NULL, 16);
+	flags = simple_strtoul(id, NULL, 16);
+	pr_info("%s: new device %s, vendor ID 0x%04x, device ID 0x%04x, flags: 0x%x\n",
+	        driver_name, name, vendor_id, device_id, flags);
+
+	if (vendor_id > 0x10000 || vendor_id == 0)
+		return;
+	if (device_id > 0x10000 || device_id == 0)
+		return;
+
+	for (i=0; usb_dev_id[i].name; i++);
+	usb_dev_id[i].name = name;
+	usb_dev_id[i].vendor = vendor_id;
+	usb_dev_id[i].device = device_id;
+	usb_dev_id[i].private = flags;
+	pegasus_ids[i].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
+	pegasus_ids[i].idVendor = vendor_id;
+	pegasus_ids[i].idProduct = device_id;
+}
+
 static int __init pegasus_init(void)
 {
 	pr_info("%s: %s, " DRIVER_DESC "\n", driver_name, DRIVER_VERSION);
+	if (devid)
+		parse_id(devid);
 	pegasus_workqueue = create_singlethread_workqueue("pegasus");
 	if (!pegasus_workqueue)
 		return -ENOMEM;
diff --git a/drivers/usb/net/plusb.c b/drivers/usb/net/plusb.c
index 89856aa0e3b8..4fe863389cb7 100644
--- a/drivers/usb/net/plusb.c
+++ b/drivers/usb/net/plusb.c
@@ -127,7 +127,6 @@ static const struct usb_device_id	products [] = {
 MODULE_DEVICE_TABLE(usb, products);
 
 static struct usb_driver plusb_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"plusb",
 	.id_table =	products,
 	.probe =	usbnet_probe,
diff --git a/drivers/usb/net/rndis_host.c b/drivers/usb/net/rndis_host.c
index c0ecbab6f6ba..49991ac1bf3b 100644
--- a/drivers/usb/net/rndis_host.c
+++ b/drivers/usb/net/rndis_host.c
@@ -586,7 +586,6 @@ static const struct usb_device_id	products [] = {
 MODULE_DEVICE_TABLE(usb, products);
 
 static struct usb_driver rndis_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"rndis_host",
 	.id_table =	products,
 	.probe =	usbnet_probe,
diff --git a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c
index 787dd3591d6a..8ca52be23976 100644
--- a/drivers/usb/net/rtl8150.c
+++ b/drivers/usb/net/rtl8150.c
@@ -177,7 +177,6 @@ static int rtl8150_probe(struct usb_interface *intf,
 static const char driver_name [] = "rtl8150";
 
 static struct usb_driver rtl8150_driver = {
-	.owner =	THIS_MODULE,
 	.name =		driver_name,
 	.probe =	rtl8150_probe,
 	.disconnect =	rtl8150_disconnect,
diff --git a/drivers/usb/net/zaurus.c b/drivers/usb/net/zaurus.c
index 680d13957af4..9c5ab251370c 100644
--- a/drivers/usb/net/zaurus.c
+++ b/drivers/usb/net/zaurus.c
@@ -357,7 +357,6 @@ static const struct usb_device_id	products [] = {
 MODULE_DEVICE_TABLE(usb, products);
 
 static struct usb_driver zaurus_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"zaurus",
 	.id_table =	products,
 	.probe =	usbnet_probe,
diff --git a/drivers/usb/net/zd1201.c b/drivers/usb/net/zd1201.c
index 2f52261c7cc1..f3a8e2807c3b 100644
--- a/drivers/usb/net/zd1201.c
+++ b/drivers/usb/net/zd1201.c
@@ -1722,7 +1722,7 @@ static const struct iw_priv_args zd1201_private_args[] = {
 	    IW_PRIV_TYPE_NONE, "sethostauth" },
 	{ ZD1201GIWHOSTAUTH, IW_PRIV_TYPE_NONE,
 	    IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethostauth" },
-	{ ZD1201SIWAUTHSTA, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 
+	{ ZD1201SIWAUTHSTA, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1,
 	    IW_PRIV_TYPE_NONE, "authstation" },
 	{ ZD1201SIWMAXASSOC, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
 	    IW_PRIV_TYPE_NONE, "setmaxassoc" },
@@ -1731,9 +1731,9 @@ static const struct iw_priv_args zd1201_private_args[] = {
 };
 
 static const struct iw_handler_def zd1201_iw_handlers = {
-	.num_standard 		= sizeof(zd1201_iw_handler)/sizeof(iw_handler),
-	.num_private 		= sizeof(zd1201_private_handler)/sizeof(iw_handler),
-	.num_private_args 	= sizeof(zd1201_private_args)/sizeof(struct iw_priv_args),
+	.num_standard 		= ARRAY_SIZE(zd1201_iw_handler),
+	.num_private 		= ARRAY_SIZE(zd1201_private_handler),
+	.num_private_args 	= ARRAY_SIZE(zd1201_private_args),
 	.standard 		= (iw_handler *)zd1201_iw_handler,
 	.private 		= (iw_handler *)zd1201_private_handler,
 	.private_args 		= (struct iw_priv_args *) zd1201_private_args,
@@ -1829,6 +1829,8 @@ static int zd1201_probe(struct usb_interface *interface,
 	if (err)
 		goto err_net;
 
+	SET_NETDEV_DEV(zd->dev, &usb->dev);
+
 	err = register_netdev(zd->dev);
 	if (err)
 		goto err_net;
@@ -1923,7 +1925,6 @@ static int zd1201_resume(struct usb_interface *interface)
 #endif
 
 static struct usb_driver zd1201_usb = {
-	.owner = THIS_MODULE,
 	.name = "zd1201",
 	.probe = zd1201_probe,
 	.disconnect = zd1201_disconnect,
diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c
index 1f29d8837327..dbf1f063098c 100644
--- a/drivers/usb/serial/airprime.c
+++ b/drivers/usb/serial/airprime.c
@@ -23,11 +23,11 @@ static struct usb_device_id id_table [] = {
 MODULE_DEVICE_TABLE(usb, id_table);
 
 static struct usb_driver airprime_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"airprime",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table,
+	.no_dynamic_id = 	1,
 };
 
 static struct usb_serial_driver airprime_device = {
diff --git a/drivers/usb/serial/anydata.c b/drivers/usb/serial/anydata.c
index 18022a74a3dc..343f6f228220 100644
--- a/drivers/usb/serial/anydata.c
+++ b/drivers/usb/serial/anydata.c
@@ -27,11 +27,11 @@ static int buffer_size;
 static int debug;
 
 static struct usb_driver anydata_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"anydata",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table,
+	.no_dynamic_id = 	1,
 };
 
 static int anydata_open(struct usb_serial_port *port, struct file *filp)
diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
index 84bc0ee4f061..4144777ea18b 100644
--- a/drivers/usb/serial/belkin_sa.c
+++ b/drivers/usb/serial/belkin_sa.c
@@ -113,11 +113,11 @@ static struct usb_device_id id_table_combined [] = {
 MODULE_DEVICE_TABLE (usb, id_table_combined);
 
 static struct usb_driver belkin_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"belkin",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table_combined,
+	.no_dynamic_id = 	1,
 };
 
 /* All of the device info needed for the serial converters */
diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c
index c9787001cf2a..da46b351e188 100644
--- a/drivers/usb/serial/cp2101.c
+++ b/drivers/usb/serial/cp2101.c
@@ -67,11 +67,11 @@ static struct usb_device_id id_table [] = {
 MODULE_DEVICE_TABLE (usb, id_table);
 
 static struct usb_driver cp2101_driver = {
-	.owner		= THIS_MODULE,
 	.name		= "cp2101",
 	.probe		= usb_serial_probe,
 	.disconnect	= usb_serial_disconnect,
 	.id_table	= id_table,
+	.no_dynamic_id	= 	1,
 };
 
 static struct usb_serial_driver cp2101_device = {
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
index e581e4ae8483..6d18d4eaba35 100644
--- a/drivers/usb/serial/cyberjack.c
+++ b/drivers/usb/serial/cyberjack.c
@@ -76,11 +76,11 @@ static struct usb_device_id id_table [] = {
 MODULE_DEVICE_TABLE (usb, id_table);
 
 static struct usb_driver cyberjack_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"cyberjack",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table,
+	.no_dynamic_id = 	1,
 };
 
 static struct usb_serial_driver cyberjack_device = {
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index af9290ed257b..af18355e94cc 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -112,6 +112,7 @@ static struct usb_driver cypress_driver = {
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table_combined,
+	.no_dynamic_id = 	1,
 };
 
 struct cypress_private {
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index dc74644a603d..8fc414bd5b24 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -493,11 +493,11 @@ static struct usb_device_id id_table_4 [] = {
 MODULE_DEVICE_TABLE (usb, id_table_combined);
 
 static struct usb_driver digi_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"digi_acceleport",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table_combined,
+	.no_dynamic_id = 	1,
 };
 
 
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
index 0b0546dcc7b9..79a766e9ca23 100644
--- a/drivers/usb/serial/empeg.c
+++ b/drivers/usb/serial/empeg.c
@@ -105,11 +105,11 @@ static struct usb_device_id id_table [] = {
 MODULE_DEVICE_TABLE (usb, id_table);
 
 static struct usb_driver empeg_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"empeg",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table,
+	.no_dynamic_id = 	1,
 };
 
 static struct usb_serial_driver empeg_device = {
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 06e04b442ff1..eb863b3f2d79 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -471,12 +471,15 @@ static struct usb_device_id id_table_combined [] = {
 	{ USB_DEVICE(FTDI_VID, FTDI_ACTIVE_ROBOTS_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_MHAM_Y6_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_MHAM_Y8_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_TERATRONIK_VCP_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_TERATRONIK_D2XX_PID) },
 	{ USB_DEVICE(EVOLUTION_VID, EVOLUTION_ER1_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ARTEMIS_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16HR_PID) },
 	{ USB_DEVICE(KOBIL_VID, KOBIL_CONV_B1_PID) },
 	{ USB_DEVICE(KOBIL_VID, KOBIL_CONV_KAAN_PID) },
+	{ USB_DEVICE(POSIFLEX_VID, POSIFLEX_PP7000_PID) },
 	{ },					/* Optional parameter entry */
 	{ }					/* Terminating entry */
 };
@@ -488,9 +491,10 @@ static struct usb_driver ftdi_driver = {
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table_combined,
+	.no_dynamic_id = 	1,
 };
 
-static char *ftdi_chip_name[] = {
+static const char *ftdi_chip_name[] = {
 	[SIO] = "SIO",	/* the serial part of FT8U100AX */
 	[FT8U232AM] = "FT8U232AM",
 	[FT232BM] = "FT232BM",
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index 773ea3eca086..00d45f8600de 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -343,6 +343,13 @@
 #define XSENS_CONVERTER_7_PID	0xD38F
 
 /*
+ * Teratronik product ids.
+ * Submitted by O. Wölfelschneider.
+ */
+#define FTDI_TERATRONIK_VCP_PID	 0xEC88	/* Teratronik device (preferring VCP driver on windows) */
+#define FTDI_TERATRONIK_D2XX_PID 0xEC89	/* Teratronik device (preferring D2XX driver on windows) */
+
+/*
  * Evolution Robotics products (http://www.evolution.com/).
  * Submitted by Shawn M. Lavelle.
  */
@@ -352,6 +359,12 @@
 /* Pyramid Computer GmbH */
 #define FTDI_PYRAMID_PID	0xE6C8	/* Pyramid Appliance Display */
 
+/*
+ * Posiflex inc retail equipment (http://www.posiflex.com.tw)
+ */
+#define POSIFLEX_VID		0x0d3a  /* Vendor ID */
+#define POSIFLEX_PP7000_PID	0x0300  /* PP-7000II thermal printer */
+
 /* Commands */
 #define FTDI_SIO_RESET 		0 /* Reset the port */
 #define FTDI_SIO_MODEM_CTRL 	1 /* Set the modem control register */
@@ -714,7 +727,7 @@ typedef enum {
  */
 
 /* FTDI_SIO_GET_MODEM_STATUS */
-/* Retreive the current value of the modem status register */
+/* Retrieve the current value of the modem status register */
 
 #define FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE 0xc0
 #define FTDI_SIO_GET_MODEM_STATUS_REQUEST FTDI_SIO_GET_MODEM_STATUS
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
index 35820bda7ae1..452efce72714 100644
--- a/drivers/usb/serial/garmin_gps.c
+++ b/drivers/usb/serial/garmin_gps.c
@@ -222,11 +222,11 @@ static struct usb_device_id id_table [] = {
 MODULE_DEVICE_TABLE (usb, id_table);
 
 static struct usb_driver garmin_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"garmin_gps",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table,
+	.no_dynamic_id = 	1,
 };
 
 
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index 53a47c31cd0e..4ddac620fc0c 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -68,11 +68,11 @@ static int generic_probe(struct usb_interface *interface,
 }
 
 static struct usb_driver generic_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"usbserial_generic",
 	.probe =	generic_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	generic_serial_ids,
+	.no_dynamic_id = 	1,
 };
 #endif
 
diff --git a/drivers/usb/serial/hp4x.c b/drivers/usb/serial/hp4x.c
index 8eadfb705601..e9719da2aca1 100644
--- a/drivers/usb/serial/hp4x.c
+++ b/drivers/usb/serial/hp4x.c
@@ -37,11 +37,11 @@ static struct usb_device_id id_table [] = {
 MODULE_DEVICE_TABLE(usb, id_table);
 
 static struct usb_driver hp49gp_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"hp4X",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table,
+	.no_dynamic_id = 	1,
 };
 
 static struct usb_serial_driver hp49gp_device = {
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index dc4c498bd1ed..faedbeb6ba49 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -184,7 +184,7 @@ struct divisor_table_entry {
 // These assume a 3.6864MHz crystal, the standard /16, and
 // MCR.7 = 0.
 //
-static struct divisor_table_entry divisor_table[] = {
+static const struct divisor_table_entry divisor_table[] = {
 	{   50,		4608},  
 	{   75,		3072},  
 	{   110,	2095},		/* 2094.545455 => 230450   => .0217 % over */
@@ -242,11 +242,11 @@ static void edge_shutdown		(struct usb_serial *serial);
 #include "io_tables.h"	/* all of the devices that this driver supports */
 
 static struct usb_driver io_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"io_edgeport",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table_combined,
+	.no_dynamic_id = 	1,
 };
 
 /* function prototypes for all of our local functions */
@@ -2353,7 +2353,7 @@ static int calc_baud_rate_divisor (int baudrate, int *divisor)
 
 	dbg("%s - %d", __FUNCTION__, baudrate);
 
-	for (i = 0; i < NUM_ENTRIES(divisor_table); i++) {
+	for (i = 0; i < ARRAY_SIZE(divisor_table); i++) {
 		if ( divisor_table[i].BaudRate == baudrate ) {
 			*divisor = divisor_table[i].Divisor;
 			return 0;
diff --git a/drivers/usb/serial/io_edgeport.h b/drivers/usb/serial/io_edgeport.h
index 5112d7aac055..123fa8a904e6 100644
--- a/drivers/usb/serial/io_edgeport.h
+++ b/drivers/usb/serial/io_edgeport.h
@@ -31,9 +31,6 @@
 #ifndef HIGH8
 	#define HIGH8(a)	((unsigned char)((a & 0xff00) >> 8))
 #endif
-#ifndef NUM_ENTRIES
-	#define NUM_ENTRIES(x)	(sizeof(x)/sizeof((x)[0]))
-#endif
 
 #ifndef __KERNEL__
 #define __KERNEL__
diff --git a/drivers/usb/serial/io_fw_boot2.h b/drivers/usb/serial/io_fw_boot2.h
index c7c3a3c305fe..e3463de99de4 100644
--- a/drivers/usb/serial/io_fw_boot2.h
+++ b/drivers/usb/serial/io_fw_boot2.h
@@ -537,7 +537,7 @@ static unsigned char IMAGE_ARRAY_NAME[] = {
 
 };
 
-static struct edge_firmware_version_info IMAGE_VERSION_NAME = {
+static const struct edge_firmware_version_info IMAGE_VERSION_NAME = {
 	2, 0, 3 };		// Major, Minor, Build
 
 #undef IMAGE_VERSION_NAME
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index 832b6d6734c0..2edf9cabad20 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -216,11 +216,11 @@ static struct usb_device_id id_table_combined [] = {
 MODULE_DEVICE_TABLE (usb, id_table_combined);
 
 static struct usb_driver io_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"io_ti",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table_combined,
+	.no_dynamic_id = 	1,
 };
 
 
@@ -2843,7 +2843,7 @@ static struct edge_buf *edge_buf_alloc(unsigned int size)
  * Free the buffer and all associated memory.
  */
 
-void edge_buf_free(struct edge_buf *eb)
+static void edge_buf_free(struct edge_buf *eb)
 {
 	if (eb) {
 		kfree(eb->buf_buf);
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index d5d066488100..06d07cea0b70 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -542,11 +542,11 @@ static struct usb_device_id ipaq_id_table [] = {
 MODULE_DEVICE_TABLE (usb, ipaq_id_table);
 
 static struct usb_driver ipaq_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"ipaq",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	ipaq_id_table,
+	.no_dynamic_id = 	1,
 };
 
 
diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c
index 7744b8148bc5..2dd191f5fe76 100644
--- a/drivers/usb/serial/ipw.c
+++ b/drivers/usb/serial/ipw.c
@@ -152,11 +152,11 @@ static struct usb_device_id usb_ipw_ids[] = {
 MODULE_DEVICE_TABLE(usb, usb_ipw_ids);
 
 static struct usb_driver usb_ipw_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"ipwtty",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	usb_ipw_ids,
+	.no_dynamic_id = 	1,
 };
 
 static int debug;
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c
index 19f329e9bdcf..a59010421444 100644
--- a/drivers/usb/serial/ir-usb.c
+++ b/drivers/usb/serial/ir-usb.c
@@ -125,11 +125,11 @@ static struct usb_device_id id_table [] = {
 MODULE_DEVICE_TABLE (usb, id_table);
 
 static struct usb_driver ir_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"ir-usb",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table,
+	.no_dynamic_id = 	1,
 };
 
 
diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h
index 5cfc13b5e56f..7472ed6bf626 100644
--- a/drivers/usb/serial/keyspan.h
+++ b/drivers/usb/serial/keyspan.h
@@ -520,11 +520,11 @@ static struct usb_device_id keyspan_ids_combined[] = {
 MODULE_DEVICE_TABLE(usb, keyspan_ids_combined);
 
 static struct usb_driver keyspan_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"keyspan",                
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	keyspan_ids_combined,
+	.no_dynamic_id = 	1,
 };
 
 /* usb_device_id table for the pre-firmware download keyspan devices */
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index cd4f48bd83b6..b0441c35f98f 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -150,11 +150,11 @@ static struct usb_device_id id_table_combined [] = {
 MODULE_DEVICE_TABLE (usb, id_table_combined);
 
 static struct usb_driver keyspan_pda_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"keyspan_pda",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table_combined,
+	.no_dynamic_id = 	1,
 };
 
 static struct usb_device_id id_table_std [] = {
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index a8951c0fd020..4e2f7dfb58b2 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -116,11 +116,11 @@ static struct usb_device_id id_table [] = {
 MODULE_DEVICE_TABLE (usb, id_table);
 
 static struct usb_driver kl5kusb105d_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"kl5kusb105d",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table,
+	.no_dynamic_id = 	1,
 };
 
 static struct usb_serial_driver kl5kusb105d_device = {
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index 9456dd9dd136..d9c21e275130 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -97,11 +97,11 @@ static struct usb_device_id id_table [] = {
 MODULE_DEVICE_TABLE (usb, id_table);
 
 static struct usb_driver kobil_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"kobil",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table,
+	.no_dynamic_id = 	1,
 };
 
 
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index ca5dbadb9b7e..b6d6cab9c859 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -125,11 +125,11 @@ static struct usb_device_id id_table_combined [] = {
 MODULE_DEVICE_TABLE (usb, id_table_combined);
 
 static struct usb_driver mct_u232_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"mct_u232",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table_combined,
+	.no_dynamic_id = 	1,
 };
 
 static struct usb_serial_driver mct_u232_device = {
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c
index 3caf97072ac0..762d8ff9a1e4 100644
--- a/drivers/usb/serial/omninet.c
+++ b/drivers/usb/serial/omninet.c
@@ -80,11 +80,11 @@ static struct usb_device_id id_table [] = {
 MODULE_DEVICE_TABLE (usb, id_table);
 
 static struct usb_driver omninet_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"omninet",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table,
+	.no_dynamic_id = 	1,
 };
 
 
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 7716000045b7..3fd2405304fd 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -95,11 +95,11 @@ static struct usb_device_id option_ids[] = {
 MODULE_DEVICE_TABLE(usb, option_ids);
 
 static struct usb_driver option_driver = {
-	.owner      = THIS_MODULE,
 	.name       = "option",
 	.probe      = usb_serial_probe,
 	.disconnect = usb_serial_disconnect,
 	.id_table   = option_ids,
+	.no_dynamic_id = 	1,
 };
 
 /* The card has three separate interfaces, wich the serial driver
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 41a45a5025b2..f03721056190 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -82,11 +82,11 @@ static struct usb_device_id id_table [] = {
 MODULE_DEVICE_TABLE (usb, id_table);
 
 static struct usb_driver pl2303_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"pl2303",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table,
+	.no_dynamic_id = 	1,
 };
 
 #define SET_LINE_REQUEST_TYPE		0x21
@@ -810,7 +810,7 @@ static void pl2303_update_line_status(struct usb_serial_port *port,
 	struct pl2303_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
 	u8 status_idx = UART_STATE;
-	u8 length = UART_STATE;
+	u8 length = UART_STATE + 1;
 
 	if ((le16_to_cpu(port->serial->dev->descriptor.idVendor) == SIEMENS_VENDOR_ID) &&
 	    (le16_to_cpu(port->serial->dev->descriptor.idProduct) == SIEMENS_PRODUCT_ID_X65 ||
diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c
index c22bdc0c4dfd..f0215f850d2d 100644
--- a/drivers/usb/serial/safe_serial.c
+++ b/drivers/usb/serial/safe_serial.c
@@ -160,14 +160,14 @@ static struct usb_device_id id_table[] = {
 MODULE_DEVICE_TABLE (usb, id_table);
 
 static struct usb_driver safe_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"safe_serial",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table,
+	.no_dynamic_id = 	1,
 };
 
-static __u16 crc10_table[256] = {
+static const __u16 crc10_table[256] = {
 	0x000, 0x233, 0x255, 0x066, 0x299, 0x0aa, 0x0cc, 0x2ff, 0x301, 0x132, 0x154, 0x367, 0x198, 0x3ab, 0x3cd, 0x1fe,
 	0x031, 0x202, 0x264, 0x057, 0x2a8, 0x09b, 0x0fd, 0x2ce, 0x330, 0x103, 0x165, 0x356, 0x1a9, 0x39a, 0x3fc, 0x1cf,
 	0x062, 0x251, 0x237, 0x004, 0x2fb, 0x0c8, 0x0ae, 0x29d, 0x363, 0x150, 0x136, 0x305, 0x1fa, 0x3c9, 0x3af, 0x19c,
@@ -425,7 +425,7 @@ static int __init safe_init (void)
 	if (vendor || product) {
 		info ("vendor: %x product: %x\n", vendor, product);
 
-		for (i = 0; i < (sizeof (id_table) / sizeof (struct usb_device_id)); i++) {
+		for (i = 0; i < ARRAY_SIZE(id_table); i++) {
 			if (!id_table[i].idVendor && !id_table[i].idProduct) {
 				id_table[i].idVendor = vendor;
 				id_table[i].idProduct = product;
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index 205dbf7201da..abb830cb77bd 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -248,11 +248,11 @@ static struct usb_device_id ti_id_table_combined[] = {
 };
 
 static struct usb_driver ti_usb_driver = {
-	.owner			= THIS_MODULE,
 	.name			= "ti_usb_3410_5052",
 	.probe			= usb_serial_probe,
 	.disconnect		= usb_serial_disconnect,
 	.id_table		= ti_id_table_combined,
+	.no_dynamic_id = 	1,
 };
 
 static struct usb_serial_driver ti_1port_device = {
@@ -351,17 +351,14 @@ static int __init ti_init(void)
 	int i,j;
 	int ret;
 
-
 	/* insert extra vendor and product ids */
-	j = sizeof(ti_id_table_3410)/sizeof(struct usb_device_id)
-		- TI_EXTRA_VID_PID_COUNT - 1;
+	j = ARRAY_SIZE(ti_id_table_3410) - TI_EXTRA_VID_PID_COUNT - 1;
 	for (i=0; i<min(vendor_3410_count,product_3410_count); i++,j++) {
 		ti_id_table_3410[j].idVendor = vendor_3410[i];
 		ti_id_table_3410[j].idProduct = product_3410[i];
 		ti_id_table_3410[j].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
 	}
-	j = sizeof(ti_id_table_5052)/sizeof(struct usb_device_id)
-		- TI_EXTRA_VID_PID_COUNT - 1;
+	j = ARRAY_SIZE(ti_id_table_5052) - TI_EXTRA_VID_PID_COUNT - 1;
 	for (i=0; i<min(vendor_5052_count,product_5052_count); i++,j++) {
 		ti_id_table_5052[j].idVendor = vendor_5052[i];
 		ti_id_table_5052[j].idProduct = product_5052[i];
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 0c4881d18cd5..8bc8337c99c4 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -30,6 +30,7 @@
 #include <linux/list.h>
 #include <linux/smp_lock.h>
 #include <asm/uaccess.h>
+#include <asm/semaphore.h>
 #include <linux/usb.h>
 #include "usb-serial.h"
 #include "pl2303.h"
@@ -42,10 +43,10 @@
 
 /* Driver structure we register with the USB core */
 static struct usb_driver usb_serial_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"usbserial",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
+	.no_dynamic_id = 	1,
 };
 
 /* There is no MODULE_DEVICE_TABLE for usbserial.c.  Instead
@@ -188,6 +189,11 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
 
 	portNumber = tty->index - serial->minor;
 	port = serial->port[portNumber];
+	if (!port)
+		return -ENODEV;
+
+	if (down_interruptible(&port->sem))
+		return -ERESTARTSYS;
 	 
 	++port->open_count;
 
@@ -213,6 +219,7 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
 			goto bailout_module_put;
 	}
 
+	up(&port->sem);
 	return 0;
 
 bailout_module_put:
@@ -220,6 +227,7 @@ bailout_module_put:
 bailout_kref_put:
 	kref_put(&serial->kref, destroy_serial);
 	port->open_count = 0;
+	up(&port->sem);
 	return retval;
 }
 
@@ -232,8 +240,10 @@ static void serial_close(struct tty_struct *tty, struct file * filp)
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
+	down(&port->sem);
+
 	if (port->open_count == 0)
-		return;
+		goto out;
 
 	--port->open_count;
 	if (port->open_count == 0) {
@@ -251,6 +261,9 @@ static void serial_close(struct tty_struct *tty, struct file * filp)
 	}
 
 	kref_put(&port->serial->kref, destroy_serial);
+
+out:
+	up(&port->sem);
 }
 
 static int serial_write (struct tty_struct * tty, const unsigned char *buf, int count)
@@ -258,6 +271,9 @@ static int serial_write (struct tty_struct * tty, const unsigned char *buf, int
 	struct usb_serial_port *port = tty->driver_data;
 	int retval = -EINVAL;
 
+	if (!port)
+		goto exit;
+
 	dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count);
 
 	if (!port->open_count) {
@@ -277,6 +293,9 @@ static int serial_write_room (struct tty_struct *tty)
 	struct usb_serial_port *port = tty->driver_data;
 	int retval = -EINVAL;
 
+	if (!port)
+		goto exit;
+
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	if (!port->open_count) {
@@ -296,6 +315,9 @@ static int serial_chars_in_buffer (struct tty_struct *tty)
 	struct usb_serial_port *port = tty->driver_data;
 	int retval = -EINVAL;
 
+	if (!port)
+		goto exit;
+
 	dbg("%s = port %d", __FUNCTION__, port->number);
 
 	if (!port->open_count) {
@@ -314,6 +336,9 @@ static void serial_throttle (struct tty_struct * tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
 
+	if (!port)
+		return;
+
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	if (!port->open_count) {
@@ -330,6 +355,9 @@ static void serial_unthrottle (struct tty_struct * tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
 
+	if (!port)
+		return;
+
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	if (!port->open_count) {
@@ -347,6 +375,9 @@ static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned in
 	struct usb_serial_port *port = tty->driver_data;
 	int retval = -ENODEV;
 
+	if (!port)
+		goto exit;
+
 	dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd);
 
 	if (!port->open_count) {
@@ -368,6 +399,9 @@ static void serial_set_termios (struct tty_struct *tty, struct termios * old)
 {
 	struct usb_serial_port *port = tty->driver_data;
 
+	if (!port)
+		return;
+
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	if (!port->open_count) {
@@ -384,6 +418,9 @@ static void serial_break (struct tty_struct *tty, int break_state)
 {
 	struct usb_serial_port *port = tty->driver_data;
 
+	if (!port)
+		return;
+
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	if (!port->open_count) {
@@ -445,6 +482,9 @@ static int serial_tiocmget (struct tty_struct *tty, struct file *file)
 {
 	struct usb_serial_port *port = tty->driver_data;
 
+	if (!port)
+		goto exit;
+
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	if (!port->open_count) {
@@ -464,6 +504,9 @@ static int serial_tiocmset (struct tty_struct *tty, struct file *file,
 {
 	struct usb_serial_port *port = tty->driver_data;
 
+	if (!port)
+		goto exit;
+
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	if (!port->open_count) {
@@ -742,6 +785,7 @@ int usb_serial_probe(struct usb_interface *interface,
 		port->number = i + serial->minor;
 		port->serial = serial;
 		spin_lock_init(&port->lock);
+		sema_init(&port->sem, 1);
 		INIT_WORK(&port->work, usb_serial_port_softint, port);
 		serial->port[i] = port;
 	}
diff --git a/drivers/usb/serial/usb-serial.h b/drivers/usb/serial/usb-serial.h
index 238a5a871ed6..d7d27c3385b3 100644
--- a/drivers/usb/serial/usb-serial.h
+++ b/drivers/usb/serial/usb-serial.h
@@ -16,6 +16,7 @@
 
 #include <linux/config.h>
 #include <linux/kref.h>
+#include <asm/semaphore.h>
 
 #define SERIAL_TTY_MAJOR	188	/* Nice legal number now */
 #define SERIAL_TTY_MINORS	255	/* loads of devices :) */
@@ -30,6 +31,8 @@
  * @serial: pointer back to the struct usb_serial owner of this port.
  * @tty: pointer to the corresponding tty for this port.
  * @lock: spinlock to grab when updating portions of this structure.
+ * @sem: semaphore used to synchronize serial_open() and serial_close()
+ *	access for this port.
  * @number: the number of the port (the minor number).
  * @interrupt_in_buffer: pointer to the interrupt in buffer for this port.
  * @interrupt_in_urb: pointer to the interrupt in struct urb for this port.
@@ -60,6 +63,7 @@ struct usb_serial_port {
 	struct usb_serial *	serial;
 	struct tty_struct *	tty;
 	spinlock_t		lock;
+	struct semaphore        sem;
 	unsigned char		number;
 
 	unsigned char *		interrupt_in_buffer;
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index a473c1c34559..49b1fbe61f25 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -173,11 +173,11 @@ static struct usb_device_id id_table_combined [] = {
 MODULE_DEVICE_TABLE (usb, id_table_combined);
 
 static struct usb_driver visor_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"visor",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table_combined,
+	.no_dynamic_id = 	1,
 };
 
 /* All of the device info needed for the Handspring Visor, and Palm 4.0 devices */
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index 18c3183be769..a7c3c4734d83 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -127,11 +127,11 @@ static struct usb_device_id id_table_combined [] = {
 MODULE_DEVICE_TABLE (usb, id_table_combined);
 
 static struct usb_driver whiteheat_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"whiteheat",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
 	.id_table =	id_table_combined,
+	.no_dynamic_id = 	1,
 };
 
 /* function prototypes for the Connect Tech WhiteHEAT prerenumeration device */
diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
index c41d64dbb0f0..92be101feba7 100644
--- a/drivers/usb/storage/Kconfig
+++ b/drivers/usb/storage/Kconfig
@@ -112,6 +112,15 @@ config USB_STORAGE_JUMPSHOT
 	  Say Y here to include additional code to support the Lexar Jumpshot
 	  USB CompactFlash reader.
 
+config USB_STORAGE_ALAUDA
+	bool "Olympus MAUSB-10/Fuji DPC-R1 support (EXPERIMENTAL)"
+	depends on USB_STORAGE && EXPERIMENTAL
+	help
+	  Say Y here to include additional code to support the Olympus MAUSB-10
+	  and Fujifilm DPC-R1 USB Card reader/writer devices.
+
+	  These devices are based on the Alauda chip and support support both
+	  XD and SmartMedia cards.
 
 config USB_STORAGE_ONETOUCH
 	bool "Support OneTouch Button on Maxtor Hard Drives (EXPERIMENTAL)"
@@ -124,3 +133,17 @@ config USB_STORAGE_ONETOUCH
 	  hard drive's as an input device. An action can be associated with
 	  this input in any keybinding software. (e.g. gnome's keyboard short-
 	  cuts)
+
+config USB_LIBUSUAL
+	bool "The shared table of common (or usual) storage devices"
+	depends on USB
+	help
+	  This module contains a table of common (or usual) devices
+	  for usb-storage and ub drivers, and allows to switch binding
+	  of these devices without rebuilding modules.
+
+	  Typical syntax of /etc/modprobe.conf is:
+
+		options libusual bias="ub"
+
+	  If unsure, say N.
diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile
index 44ab8f9978fe..8cbba22508a4 100644
--- a/drivers/usb/storage/Makefile
+++ b/drivers/usb/storage/Makefile
@@ -18,7 +18,12 @@ usb-storage-obj-$(CONFIG_USB_STORAGE_DPCM)	+= dpcm.o
 usb-storage-obj-$(CONFIG_USB_STORAGE_ISD200)	+= isd200.o
 usb-storage-obj-$(CONFIG_USB_STORAGE_DATAFAB)	+= datafab.o
 usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT)	+= jumpshot.o
+usb-storage-obj-$(CONFIG_USB_STORAGE_ALAUDA)	+= alauda.o
 usb-storage-obj-$(CONFIG_USB_STORAGE_ONETOUCH)	+= onetouch.o
 
 usb-storage-objs :=	scsiglue.o protocol.o transport.o usb.o \
 			initializers.o $(usb-storage-obj-y)
+
+ifneq ($(CONFIG_USB_LIBUSUAL),)
+	obj-$(CONFIG_USB)	+= libusual.o
+endif
diff --git a/drivers/usb/storage/alauda.c b/drivers/usb/storage/alauda.c
new file mode 100644
index 000000000000..4d3cbb12b713
--- /dev/null
+++ b/drivers/usb/storage/alauda.c
@@ -0,0 +1,1119 @@
+/*
+ * Driver for Alauda-based card readers
+ *
+ * Current development and maintenance by:
+ *   (c) 2005 Daniel Drake <dsd@gentoo.org>
+ *
+ * The 'Alauda' is a chip manufacturered by RATOC for OEM use.
+ *
+ * Alauda implements a vendor-specific command set to access two media reader
+ * ports (XD, SmartMedia). This driver converts SCSI commands to the commands
+ * which are accepted by these devices.
+ *
+ * The driver was developed through reverse-engineering, with the help of the
+ * sddr09 driver which has many similarities, and with some help from the
+ * (very old) vendor-supplied GPL sma03 driver.
+ *
+ * For protocol info, see http://alauda.sourceforge.net
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+
+#include "usb.h"
+#include "transport.h"
+#include "protocol.h"
+#include "debug.h"
+#include "alauda.h"
+
+#define short_pack(lsb,msb) ( ((u16)(lsb)) | ( ((u16)(msb))<<8 ) )
+#define LSB_of(s) ((s)&0xFF)
+#define MSB_of(s) ((s)>>8)
+
+#define MEDIA_PORT(us) us->srb->device->lun
+#define MEDIA_INFO(us) ((struct alauda_info *)us->extra)->port[MEDIA_PORT(us)]
+
+#define PBA_LO(pba) ((pba & 0xF) << 5)
+#define PBA_HI(pba) (pba >> 3)
+#define PBA_ZONE(pba) (pba >> 11)
+
+/*
+ * Media handling
+ */
+
+struct alauda_card_info {
+	unsigned char id;		/* id byte */
+	unsigned char chipshift;	/* 1<<cs bytes total capacity */
+	unsigned char pageshift;	/* 1<<ps bytes in a page */
+	unsigned char blockshift;	/* 1<<bs pages per block */
+	unsigned char zoneshift;	/* 1<<zs blocks per zone */
+};
+
+static struct alauda_card_info alauda_card_ids[] = {
+	/* NAND flash */
+	{ 0x6e, 20, 8, 4, 8},	/* 1 MB */
+	{ 0xe8, 20, 8, 4, 8},	/* 1 MB */
+	{ 0xec, 20, 8, 4, 8},	/* 1 MB */
+	{ 0x64, 21, 8, 4, 9}, 	/* 2 MB */
+	{ 0xea, 21, 8, 4, 9},	/* 2 MB */
+	{ 0x6b, 22, 9, 4, 9},	/* 4 MB */
+	{ 0xe3, 22, 9, 4, 9},	/* 4 MB */
+	{ 0xe5, 22, 9, 4, 9},	/* 4 MB */
+	{ 0xe6, 23, 9, 4, 10},	/* 8 MB */
+	{ 0x73, 24, 9, 5, 10},	/* 16 MB */
+	{ 0x75, 25, 9, 5, 10},	/* 32 MB */
+	{ 0x76, 26, 9, 5, 10},	/* 64 MB */
+	{ 0x79, 27, 9, 5, 10},	/* 128 MB */
+	{ 0x71, 28, 9, 5, 10},	/* 256 MB */
+
+	/* MASK ROM */
+	{ 0x5d, 21, 9, 4, 8},	/* 2 MB */
+	{ 0xd5, 22, 9, 4, 9},	/* 4 MB */
+	{ 0xd6, 23, 9, 4, 10},	/* 8 MB */
+	{ 0x57, 24, 9, 4, 11},	/* 16 MB */
+	{ 0x58, 25, 9, 4, 12},	/* 32 MB */
+	{ 0,}
+};
+
+static struct alauda_card_info *alauda_card_find_id(unsigned char id) {
+	int i;
+
+	for (i = 0; alauda_card_ids[i].id != 0; i++)
+		if (alauda_card_ids[i].id == id)
+			return &(alauda_card_ids[i]);
+	return NULL;
+}
+
+/*
+ * ECC computation.
+ */
+
+static unsigned char parity[256];
+static unsigned char ecc2[256];
+
+static void nand_init_ecc(void) {
+	int i, j, a;
+
+	parity[0] = 0;
+	for (i = 1; i < 256; i++)
+		parity[i] = (parity[i&(i-1)] ^ 1);
+
+	for (i = 0; i < 256; i++) {
+		a = 0;
+		for (j = 0; j < 8; j++) {
+			if (i & (1<<j)) {
+				if ((j & 1) == 0)
+					a ^= 0x04;
+				if ((j & 2) == 0)
+					a ^= 0x10;
+				if ((j & 4) == 0)
+					a ^= 0x40;
+			}
+		}
+		ecc2[i] = ~(a ^ (a<<1) ^ (parity[i] ? 0xa8 : 0));
+	}
+}
+
+/* compute 3-byte ecc on 256 bytes */
+static void nand_compute_ecc(unsigned char *data, unsigned char *ecc) {
+	int i, j, a;
+	unsigned char par, bit, bits[8];
+
+	par = 0;
+	for (j = 0; j < 8; j++)
+		bits[j] = 0;
+
+	/* collect 16 checksum bits */
+	for (i = 0; i < 256; i++) {
+		par ^= data[i];
+		bit = parity[data[i]];
+		for (j = 0; j < 8; j++)
+			if ((i & (1<<j)) == 0)
+				bits[j] ^= bit;
+	}
+
+	/* put 4+4+4 = 12 bits in the ecc */
+	a = (bits[3] << 6) + (bits[2] << 4) + (bits[1] << 2) + bits[0];
+	ecc[0] = ~(a ^ (a<<1) ^ (parity[par] ? 0xaa : 0));
+
+	a = (bits[7] << 6) + (bits[6] << 4) + (bits[5] << 2) + bits[4];
+	ecc[1] = ~(a ^ (a<<1) ^ (parity[par] ? 0xaa : 0));
+
+	ecc[2] = ecc2[par];
+}
+
+static int nand_compare_ecc(unsigned char *data, unsigned char *ecc) {
+	return (data[0] == ecc[0] && data[1] == ecc[1] && data[2] == ecc[2]);
+}
+
+static void nand_store_ecc(unsigned char *data, unsigned char *ecc) {
+	memcpy(data, ecc, 3);
+}
+
+/*
+ * Alauda driver
+ */
+
+/*
+ * Forget our PBA <---> LBA mappings for a particular port
+ */
+static void alauda_free_maps (struct alauda_media_info *media_info)
+{
+	unsigned int shift = media_info->zoneshift
+		+ media_info->blockshift + media_info->pageshift;
+	unsigned int num_zones = media_info->capacity >> shift;
+	unsigned int i;
+
+	if (media_info->lba_to_pba != NULL)
+		for (i = 0; i < num_zones; i++) {
+			kfree(media_info->lba_to_pba[i]);
+			media_info->lba_to_pba[i] = NULL;
+		}
+
+	if (media_info->pba_to_lba != NULL)
+		for (i = 0; i < num_zones; i++) {
+			kfree(media_info->pba_to_lba[i]);
+			media_info->pba_to_lba[i] = NULL;
+		}
+}
+
+/*
+ * Returns 2 bytes of status data
+ * The first byte describes media status, and second byte describes door status
+ */
+static int alauda_get_media_status(struct us_data *us, unsigned char *data)
+{
+	int rc;
+	unsigned char command;
+
+	if (MEDIA_PORT(us) == ALAUDA_PORT_XD)
+		command = ALAUDA_GET_XD_MEDIA_STATUS;
+	else
+		command = ALAUDA_GET_SM_MEDIA_STATUS;
+
+	rc = usb_stor_ctrl_transfer(us, us->recv_ctrl_pipe,
+		command, 0xc0, 0, 1, data, 2);
+
+	US_DEBUGP("alauda_get_media_status: Media status %02X %02X\n",
+		data[0], data[1]);
+
+	return rc;
+}
+
+/*
+ * Clears the "media was changed" bit so that we know when it changes again
+ * in the future.
+ */
+static int alauda_ack_media(struct us_data *us)
+{
+	unsigned char command;
+
+	if (MEDIA_PORT(us) == ALAUDA_PORT_XD)
+		command = ALAUDA_ACK_XD_MEDIA_CHANGE;
+	else
+		command = ALAUDA_ACK_SM_MEDIA_CHANGE;
+
+	return usb_stor_ctrl_transfer(us, us->send_ctrl_pipe,
+		command, 0x40, 0, 1, NULL, 0);
+}
+
+/*
+ * Retrieves a 4-byte media signature, which indicates manufacturer, capacity,
+ * and some other details.
+ */
+static int alauda_get_media_signature(struct us_data *us, unsigned char *data)
+{
+	unsigned char command;
+
+	if (MEDIA_PORT(us) == ALAUDA_PORT_XD)
+		command = ALAUDA_GET_XD_MEDIA_SIG;
+	else
+		command = ALAUDA_GET_SM_MEDIA_SIG;
+
+	return usb_stor_ctrl_transfer(us, us->recv_ctrl_pipe,
+		command, 0xc0, 0, 0, data, 4);
+}
+
+/*
+ * Resets the media status (but not the whole device?)
+ */
+static int alauda_reset_media(struct us_data *us)
+{
+	unsigned char *command = us->iobuf;
+
+	memset(command, 0, 9);
+	command[0] = ALAUDA_BULK_CMD;
+	command[1] = ALAUDA_BULK_RESET_MEDIA;
+	command[8] = MEDIA_PORT(us);
+
+	return usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
+		command, 9, NULL);
+}
+
+/*
+ * Examines the media and deduces capacity, etc.
+ */
+static int alauda_init_media(struct us_data *us)
+{
+	unsigned char *data = us->iobuf;
+	int ready = 0;
+	struct alauda_card_info *media_info;
+	unsigned int num_zones;
+
+	while (ready == 0) {
+		msleep(20);
+
+		if (alauda_get_media_status(us, data) != USB_STOR_XFER_GOOD)
+			return USB_STOR_TRANSPORT_ERROR;
+
+		if (data[0] & 0x10)
+			ready = 1;
+	}
+
+	US_DEBUGP("alauda_init_media: We are ready for action!\n");
+
+	if (alauda_ack_media(us) != USB_STOR_XFER_GOOD)
+		return USB_STOR_TRANSPORT_ERROR;
+
+	msleep(10);
+
+	if (alauda_get_media_status(us, data) != USB_STOR_XFER_GOOD)
+		return USB_STOR_TRANSPORT_ERROR;
+
+	if (data[0] != 0x14) {
+		US_DEBUGP("alauda_init_media: Media not ready after ack\n");
+		return USB_STOR_TRANSPORT_ERROR;
+	}
+
+	if (alauda_get_media_signature(us, data) != USB_STOR_XFER_GOOD)
+		return USB_STOR_TRANSPORT_ERROR;
+
+	US_DEBUGP("alauda_init_media: Media signature: %02X %02X %02X %02X\n",
+		data[0], data[1], data[2], data[3]);
+	media_info = alauda_card_find_id(data[1]);
+	if (media_info == NULL) {
+		printk("alauda_init_media: Unrecognised media signature: "
+			"%02X %02X %02X %02X\n",
+			data[0], data[1], data[2], data[3]);
+		return USB_STOR_TRANSPORT_ERROR;
+	}
+
+	MEDIA_INFO(us).capacity = 1 << media_info->chipshift;
+	US_DEBUGP("Found media with capacity: %ldMB\n",
+		MEDIA_INFO(us).capacity >> 20);
+
+	MEDIA_INFO(us).pageshift = media_info->pageshift;
+	MEDIA_INFO(us).blockshift = media_info->blockshift;
+	MEDIA_INFO(us).zoneshift = media_info->zoneshift;
+
+	MEDIA_INFO(us).pagesize = 1 << media_info->pageshift;
+	MEDIA_INFO(us).blocksize = 1 << media_info->blockshift;
+	MEDIA_INFO(us).zonesize = 1 << media_info->zoneshift;
+
+	MEDIA_INFO(us).uzonesize = ((1 << media_info->zoneshift) / 128) * 125;
+	MEDIA_INFO(us).blockmask = MEDIA_INFO(us).blocksize - 1;
+
+	num_zones = MEDIA_INFO(us).capacity >> (MEDIA_INFO(us).zoneshift
+		+ MEDIA_INFO(us).blockshift + MEDIA_INFO(us).pageshift);
+	MEDIA_INFO(us).pba_to_lba = kcalloc(num_zones, sizeof(u16*), GFP_NOIO);
+	MEDIA_INFO(us).lba_to_pba = kcalloc(num_zones, sizeof(u16*), GFP_NOIO);
+
+	if (alauda_reset_media(us) != USB_STOR_XFER_GOOD)
+		return USB_STOR_TRANSPORT_ERROR;
+
+	return USB_STOR_TRANSPORT_GOOD;
+}
+
+/*
+ * Examines the media status and does the right thing when the media has gone,
+ * appeared, or changed.
+ */
+static int alauda_check_media(struct us_data *us)
+{
+	struct alauda_info *info = (struct alauda_info *) us->extra;
+	unsigned char status[2];
+	int rc;
+
+	rc = alauda_get_media_status(us, status);
+
+	/* Check for no media or door open */
+	if ((status[0] & 0x80) || ((status[0] & 0x1F) == 0x10)
+		|| ((status[1] & 0x01) == 0)) {
+		US_DEBUGP("alauda_check_media: No media, or door open\n");
+		alauda_free_maps(&MEDIA_INFO(us));
+		info->sense_key = 0x02;
+		info->sense_asc = 0x3A;
+		info->sense_ascq = 0x00;
+		return USB_STOR_TRANSPORT_FAILED;
+	}
+
+	/* Check for media change */
+	if (status[0] & 0x08) {
+		US_DEBUGP("alauda_check_media: Media change detected\n");
+		alauda_free_maps(&MEDIA_INFO(us));
+		alauda_init_media(us);
+
+		info->sense_key = UNIT_ATTENTION;
+		info->sense_asc = 0x28;
+		info->sense_ascq = 0x00;
+		return USB_STOR_TRANSPORT_FAILED;
+	}
+
+	return USB_STOR_TRANSPORT_GOOD;
+}
+
+/*
+ * Checks the status from the 2nd status register
+ * Returns 3 bytes of status data, only the first is known
+ */
+static int alauda_check_status2(struct us_data *us)
+{
+	int rc;
+	unsigned char command[] = {
+		ALAUDA_BULK_CMD, ALAUDA_BULK_GET_STATUS2,
+		0, 0, 0, 0, 3, 0, MEDIA_PORT(us)
+	};
+	unsigned char data[3];
+
+	rc = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
+		command, 9, NULL);
+	if (rc != USB_STOR_XFER_GOOD)
+		return rc;
+
+	rc = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
+		data, 3, NULL);
+	if (rc != USB_STOR_XFER_GOOD)
+		return rc;
+
+	US_DEBUGP("alauda_check_status2: %02X %02X %02X\n", data[0], data[1], data[2]);
+	if (data[0] & ALAUDA_STATUS_ERROR)
+		return USB_STOR_XFER_ERROR;
+
+	return USB_STOR_XFER_GOOD;
+}
+
+/*
+ * Gets the redundancy data for the first page of a PBA
+ * Returns 16 bytes.
+ */
+static int alauda_get_redu_data(struct us_data *us, u16 pba, unsigned char *data)
+{
+	int rc;
+	unsigned char command[] = {
+		ALAUDA_BULK_CMD, ALAUDA_BULK_GET_REDU_DATA,
+		PBA_HI(pba), PBA_ZONE(pba), 0, PBA_LO(pba), 0, 0, MEDIA_PORT(us)
+	};
+
+	rc = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
+		command, 9, NULL);
+	if (rc != USB_STOR_XFER_GOOD)
+		return rc;
+
+	return usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
+		data, 16, NULL);
+}
+
+/*
+ * Finds the first unused PBA in a zone
+ * Returns the absolute PBA of an unused PBA, or 0 if none found.
+ */
+static u16 alauda_find_unused_pba(struct alauda_media_info *info,
+	unsigned int zone)
+{
+	u16 *pba_to_lba = info->pba_to_lba[zone];
+	unsigned int i;
+
+	for (i = 0; i < info->zonesize; i++)
+		if (pba_to_lba[i] == UNDEF)
+			return (zone << info->zoneshift) + i;
+
+	return 0;
+}
+
+/*
+ * Reads the redundancy data for all PBA's in a zone
+ * Produces lba <--> pba mappings
+ */
+static int alauda_read_map(struct us_data *us, unsigned int zone)
+{
+	unsigned char *data = us->iobuf;
+	int result;
+	int i, j;
+	unsigned int zonesize = MEDIA_INFO(us).zonesize;
+	unsigned int uzonesize = MEDIA_INFO(us).uzonesize;
+	unsigned int lba_offset, lba_real, blocknum;
+	unsigned int zone_base_lba = zone * uzonesize;
+	unsigned int zone_base_pba = zone * zonesize;
+	u16 *lba_to_pba = kcalloc(zonesize, sizeof(u16), GFP_NOIO);
+	u16 *pba_to_lba = kcalloc(zonesize, sizeof(u16), GFP_NOIO);
+	if (lba_to_pba == NULL || pba_to_lba == NULL) {
+		result = USB_STOR_TRANSPORT_ERROR;
+		goto error;
+	}
+
+	US_DEBUGP("alauda_read_map: Mapping blocks for zone %d\n", zone);
+
+	/* 1024 PBA's per zone */
+	for (i = 0; i < zonesize; i++)
+		lba_to_pba[i] = pba_to_lba[i] = UNDEF;
+
+	for (i = 0; i < zonesize; i++) {
+		blocknum = zone_base_pba + i;
+
+		result = alauda_get_redu_data(us, blocknum, data);
+		if (result != USB_STOR_XFER_GOOD) {
+			result = USB_STOR_TRANSPORT_ERROR;
+			goto error;
+		}
+
+		/* special PBAs have control field 0^16 */
+		for (j = 0; j < 16; j++)
+			if (data[j] != 0)
+				goto nonz;
+		pba_to_lba[i] = UNUSABLE;
+		US_DEBUGP("alauda_read_map: PBA %d has no logical mapping\n", blocknum);
+		continue;
+
+	nonz:
+		/* unwritten PBAs have control field FF^16 */
+		for (j = 0; j < 16; j++)
+			if (data[j] != 0xff)
+				goto nonff;
+		continue;
+
+	nonff:
+		/* normal PBAs start with six FFs */
+		if (j < 6) {
+			US_DEBUGP("alauda_read_map: PBA %d has no logical mapping: "
+			       "reserved area = %02X%02X%02X%02X "
+			       "data status %02X block status %02X\n",
+			       blocknum, data[0], data[1], data[2], data[3],
+			       data[4], data[5]);
+			pba_to_lba[i] = UNUSABLE;
+			continue;
+		}
+
+		if ((data[6] >> 4) != 0x01) {
+			US_DEBUGP("alauda_read_map: PBA %d has invalid address "
+			       "field %02X%02X/%02X%02X\n",
+			       blocknum, data[6], data[7], data[11], data[12]);
+			pba_to_lba[i] = UNUSABLE;
+			continue;
+		}
+
+		/* check even parity */
+		if (parity[data[6] ^ data[7]]) {
+			printk("alauda_read_map: Bad parity in LBA for block %d"
+			       " (%02X %02X)\n", i, data[6], data[7]);
+			pba_to_lba[i] = UNUSABLE;
+			continue;
+		}
+
+		lba_offset = short_pack(data[7], data[6]);
+		lba_offset = (lba_offset & 0x07FF) >> 1;
+		lba_real = lba_offset + zone_base_lba;
+
+		/*
+		 * Every 1024 physical blocks ("zone"), the LBA numbers
+		 * go back to zero, but are within a higher block of LBA's.
+		 * Also, there is a maximum of 1000 LBA's per zone.
+		 * In other words, in PBA 1024-2047 you will find LBA 0-999
+		 * which are really LBA 1000-1999. This allows for 24 bad
+		 * or special physical blocks per zone.
+		 */
+
+		if (lba_offset >= uzonesize) {
+			printk("alauda_read_map: Bad low LBA %d for block %d\n",
+			       lba_real, blocknum);
+			continue;
+		}
+
+		if (lba_to_pba[lba_offset] != UNDEF) {
+			printk("alauda_read_map: LBA %d seen for PBA %d and %d\n",
+			       lba_real, lba_to_pba[lba_offset], blocknum);
+			continue;
+		}
+
+		pba_to_lba[i] = lba_real;
+		lba_to_pba[lba_offset] = blocknum;
+		continue;
+	}
+
+	MEDIA_INFO(us).lba_to_pba[zone] = lba_to_pba;
+	MEDIA_INFO(us).pba_to_lba[zone] = pba_to_lba;
+	result = 0;
+	goto out;
+
+error:
+	kfree(lba_to_pba);
+	kfree(pba_to_lba);
+out:
+	return result;
+}
+
+/*
+ * Checks to see whether we have already mapped a certain zone
+ * If we haven't, the map is generated
+ */
+static void alauda_ensure_map_for_zone(struct us_data *us, unsigned int zone)
+{
+	if (MEDIA_INFO(us).lba_to_pba[zone] == NULL
+		|| MEDIA_INFO(us).pba_to_lba[zone] == NULL)
+		alauda_read_map(us, zone);
+}
+
+/*
+ * Erases an entire block
+ */
+static int alauda_erase_block(struct us_data *us, u16 pba)
+{
+	int rc;
+	unsigned char command[] = {
+		ALAUDA_BULK_CMD, ALAUDA_BULK_ERASE_BLOCK, PBA_HI(pba),
+		PBA_ZONE(pba), 0, PBA_LO(pba), 0x02, 0, MEDIA_PORT(us)
+	};
+	unsigned char buf[2];
+
+	US_DEBUGP("alauda_erase_block: Erasing PBA %d\n", pba);
+
+	rc = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
+		command, 9, NULL);
+	if (rc != USB_STOR_XFER_GOOD)
+		return rc;
+
+	rc = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
+		buf, 2, NULL);
+	if (rc != USB_STOR_XFER_GOOD)
+		return rc;
+
+	US_DEBUGP("alauda_erase_block: Erase result: %02X %02X\n",
+		buf[0], buf[1]);
+	return rc;
+}
+
+/*
+ * Reads data from a certain offset page inside a PBA, including interleaved
+ * redundancy data. Returns (pagesize+64)*pages bytes in data.
+ */
+static int alauda_read_block_raw(struct us_data *us, u16 pba,
+		unsigned int page, unsigned int pages, unsigned char *data)
+{
+	int rc;
+	unsigned char command[] = {
+		ALAUDA_BULK_CMD, ALAUDA_BULK_READ_BLOCK, PBA_HI(pba),
+		PBA_ZONE(pba), 0, PBA_LO(pba) + page, pages, 0, MEDIA_PORT(us)
+	};
+
+	US_DEBUGP("alauda_read_block: pba %d page %d count %d\n",
+		pba, page, pages);
+
+	rc = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
+		command, 9, NULL);
+	if (rc != USB_STOR_XFER_GOOD)
+		return rc;
+
+	return usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
+		data, (MEDIA_INFO(us).pagesize + 64) * pages, NULL);
+}
+
+/*
+ * Reads data from a certain offset page inside a PBA, excluding redundancy
+ * data. Returns pagesize*pages bytes in data. Note that data must be big enough
+ * to hold (pagesize+64)*pages bytes of data, but you can ignore those 'extra'
+ * trailing bytes outside this function.
+ */
+static int alauda_read_block(struct us_data *us, u16 pba,
+		unsigned int page, unsigned int pages, unsigned char *data)
+{
+	int i, rc;
+	unsigned int pagesize = MEDIA_INFO(us).pagesize;
+
+	rc = alauda_read_block_raw(us, pba, page, pages, data);
+	if (rc != USB_STOR_XFER_GOOD)
+		return rc;
+
+	/* Cut out the redundancy data */
+	for (i = 0; i < pages; i++) {
+		int dest_offset = i * pagesize;
+		int src_offset = i * (pagesize + 64);
+		memmove(data + dest_offset, data + src_offset, pagesize);
+	}
+
+	return rc;
+}
+
+/*
+ * Writes an entire block of data and checks status after write.
+ * Redundancy data must be already included in data. Data should be
+ * (pagesize+64)*blocksize bytes in length.
+ */
+static int alauda_write_block(struct us_data *us, u16 pba, unsigned char *data)
+{
+	int rc;
+	struct alauda_info *info = (struct alauda_info *) us->extra;
+	unsigned char command[] = {
+		ALAUDA_BULK_CMD, ALAUDA_BULK_WRITE_BLOCK, PBA_HI(pba),
+		PBA_ZONE(pba), 0, PBA_LO(pba), 32, 0, MEDIA_PORT(us)
+	};
+
+	US_DEBUGP("alauda_write_block: pba %d\n", pba);
+
+	rc = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
+		command, 9, NULL);
+	if (rc != USB_STOR_XFER_GOOD)
+		return rc;
+
+	rc = usb_stor_bulk_transfer_buf(us, info->wr_ep, data,
+		(MEDIA_INFO(us).pagesize + 64) * MEDIA_INFO(us).blocksize,
+		NULL);
+	if (rc != USB_STOR_XFER_GOOD)
+		return rc;
+
+	return alauda_check_status2(us);
+}
+
+/*
+ * Write some data to a specific LBA.
+ */
+static int alauda_write_lba(struct us_data *us, u16 lba,
+		 unsigned int page, unsigned int pages,
+		 unsigned char *ptr, unsigned char *blockbuffer)
+{
+	u16 pba, lbap, new_pba;
+	unsigned char *bptr, *cptr, *xptr;
+	unsigned char ecc[3];
+	int i, result;
+	unsigned int uzonesize = MEDIA_INFO(us).uzonesize;
+	unsigned int zonesize = MEDIA_INFO(us).zonesize;
+	unsigned int pagesize = MEDIA_INFO(us).pagesize;
+	unsigned int blocksize = MEDIA_INFO(us).blocksize;
+	unsigned int lba_offset = lba % uzonesize;
+	unsigned int new_pba_offset;
+	unsigned int zone = lba / uzonesize;
+
+	alauda_ensure_map_for_zone(us, zone);
+
+	pba = MEDIA_INFO(us).lba_to_pba[zone][lba_offset];
+	if (pba == 1) {
+		/* Maybe it is impossible to write to PBA 1.
+		   Fake success, but don't do anything. */
+		printk("alauda_write_lba: avoid writing to pba 1\n");
+		return USB_STOR_TRANSPORT_GOOD;
+	}
+
+	new_pba = alauda_find_unused_pba(&MEDIA_INFO(us), zone);
+	if (!new_pba) {
+		printk("alauda_write_lba: Out of unused blocks\n");
+		return USB_STOR_TRANSPORT_ERROR;
+	}
+
+	/* read old contents */
+	if (pba != UNDEF) {
+		result = alauda_read_block_raw(us, pba, 0,
+			blocksize, blockbuffer);
+		if (result != USB_STOR_XFER_GOOD)
+			return result;
+	} else {
+		memset(blockbuffer, 0, blocksize * (pagesize + 64));
+	}
+
+	lbap = (lba_offset << 1) | 0x1000;
+	if (parity[MSB_of(lbap) ^ LSB_of(lbap)])
+		lbap ^= 1;
+
+	/* check old contents and fill lba */
+	for (i = 0; i < blocksize; i++) {
+		bptr = blockbuffer + (i * (pagesize + 64));
+		cptr = bptr + pagesize;
+		nand_compute_ecc(bptr, ecc);
+		if (!nand_compare_ecc(cptr+13, ecc)) {
+			US_DEBUGP("Warning: bad ecc in page %d- of pba %d\n",
+				  i, pba);
+			nand_store_ecc(cptr+13, ecc);
+		}
+		nand_compute_ecc(bptr + (pagesize / 2), ecc);
+		if (!nand_compare_ecc(cptr+8, ecc)) {
+			US_DEBUGP("Warning: bad ecc in page %d+ of pba %d\n",
+				  i, pba);
+			nand_store_ecc(cptr+8, ecc);
+		}
+		cptr[6] = cptr[11] = MSB_of(lbap);
+		cptr[7] = cptr[12] = LSB_of(lbap);
+	}
+
+	/* copy in new stuff and compute ECC */
+	xptr = ptr;
+	for (i = page; i < page+pages; i++) {
+		bptr = blockbuffer + (i * (pagesize + 64));
+		cptr = bptr + pagesize;
+		memcpy(bptr, xptr, pagesize);
+		xptr += pagesize;
+		nand_compute_ecc(bptr, ecc);
+		nand_store_ecc(cptr+13, ecc);
+		nand_compute_ecc(bptr + (pagesize / 2), ecc);
+		nand_store_ecc(cptr+8, ecc);
+	}
+
+	result = alauda_write_block(us, new_pba, blockbuffer);
+	if (result != USB_STOR_XFER_GOOD)
+		return result;
+
+	new_pba_offset = new_pba - (zone * zonesize);
+	MEDIA_INFO(us).pba_to_lba[zone][new_pba_offset] = lba;
+	MEDIA_INFO(us).lba_to_pba[zone][lba_offset] = new_pba;
+	US_DEBUGP("alauda_write_lba: Remapped LBA %d to PBA %d\n",
+		lba, new_pba);
+
+	if (pba != UNDEF) {
+		unsigned int pba_offset = pba - (zone * zonesize);
+		result = alauda_erase_block(us, pba);
+		if (result != USB_STOR_XFER_GOOD)
+			return result;
+		MEDIA_INFO(us).pba_to_lba[zone][pba_offset] = UNDEF;
+	}
+
+	return USB_STOR_TRANSPORT_GOOD;
+}
+
+/*
+ * Read data from a specific sector address
+ */
+static int alauda_read_data(struct us_data *us, unsigned long address,
+		unsigned int sectors)
+{
+	unsigned char *buffer;
+	u16 lba, max_lba;
+	unsigned int page, len, index, offset;
+	unsigned int blockshift = MEDIA_INFO(us).blockshift;
+	unsigned int pageshift = MEDIA_INFO(us).pageshift;
+	unsigned int blocksize = MEDIA_INFO(us).blocksize;
+	unsigned int pagesize = MEDIA_INFO(us).pagesize;
+	unsigned int uzonesize = MEDIA_INFO(us).uzonesize;
+	int result;
+
+	/*
+	 * Since we only read in one block at a time, we have to create
+	 * a bounce buffer and move the data a piece at a time between the
+	 * bounce buffer and the actual transfer buffer.
+	 * We make this buffer big enough to hold temporary redundancy data,
+	 * which we use when reading the data blocks.
+	 */
+
+	len = min(sectors, blocksize) * (pagesize + 64);
+	buffer = kmalloc(len, GFP_NOIO);
+	if (buffer == NULL) {
+		printk("alauda_read_data: Out of memory\n");
+		return USB_STOR_TRANSPORT_ERROR;
+	}
+
+	/* Figure out the initial LBA and page */
+	lba = address >> blockshift;
+	page = (address & MEDIA_INFO(us).blockmask);
+	max_lba = MEDIA_INFO(us).capacity >> (blockshift + pageshift);
+
+	result = USB_STOR_TRANSPORT_GOOD;
+	index = offset = 0;
+
+	while (sectors > 0) {
+		unsigned int zone = lba / uzonesize; /* integer division */
+		unsigned int lba_offset = lba - (zone * uzonesize);
+		unsigned int pages;
+		u16 pba;
+		alauda_ensure_map_for_zone(us, zone);
+
+		/* Not overflowing capacity? */
+		if (lba >= max_lba) {
+			US_DEBUGP("Error: Requested lba %u exceeds "
+				  "maximum %u\n", lba, max_lba);
+			result = USB_STOR_TRANSPORT_ERROR;
+			break;
+		}
+
+		/* Find number of pages we can read in this block */
+		pages = min(sectors, blocksize - page);
+		len = pages << pageshift;
+
+		/* Find where this lba lives on disk */
+		pba = MEDIA_INFO(us).lba_to_pba[zone][lba_offset];
+
+		if (pba == UNDEF) {	/* this lba was never written */
+			US_DEBUGP("Read %d zero pages (LBA %d) page %d\n",
+				  pages, lba, page);
+
+			/* This is not really an error. It just means
+			   that the block has never been written.
+			   Instead of returning USB_STOR_TRANSPORT_ERROR
+			   it is better to return all zero data. */
+
+			memset(buffer, 0, len);
+		} else {
+			US_DEBUGP("Read %d pages, from PBA %d"
+				  " (LBA %d) page %d\n",
+				  pages, pba, lba, page);
+
+			result = alauda_read_block(us, pba, page, pages, buffer);
+			if (result != USB_STOR_TRANSPORT_GOOD)
+				break;
+		}
+
+		/* Store the data in the transfer buffer */
+		usb_stor_access_xfer_buf(buffer, len, us->srb,
+				&index, &offset, TO_XFER_BUF);
+
+		page = 0;
+		lba++;
+		sectors -= pages;
+	}
+
+	kfree(buffer);
+	return result;
+}
+
+/*
+ * Write data to a specific sector address
+ */
+static int alauda_write_data(struct us_data *us, unsigned long address,
+		unsigned int sectors)
+{
+	unsigned char *buffer, *blockbuffer;
+	unsigned int page, len, index, offset;
+	unsigned int blockshift = MEDIA_INFO(us).blockshift;
+	unsigned int pageshift = MEDIA_INFO(us).pageshift;
+	unsigned int blocksize = MEDIA_INFO(us).blocksize;
+	unsigned int pagesize = MEDIA_INFO(us).pagesize;
+	u16 lba, max_lba;
+	int result;
+
+	/*
+	 * Since we don't write the user data directly to the device,
+	 * we have to create a bounce buffer and move the data a piece
+	 * at a time between the bounce buffer and the actual transfer buffer.
+	 */
+
+	len = min(sectors, blocksize) * pagesize;
+	buffer = kmalloc(len, GFP_NOIO);
+	if (buffer == NULL) {
+		printk("alauda_write_data: Out of memory\n");
+		return USB_STOR_TRANSPORT_ERROR;
+	}
+
+	/*
+	 * We also need a temporary block buffer, where we read in the old data,
+	 * overwrite parts with the new data, and manipulate the redundancy data
+	 */
+	blockbuffer = kmalloc((pagesize + 64) * blocksize, GFP_NOIO);
+	if (blockbuffer == NULL) {
+		printk("alauda_write_data: Out of memory\n");
+		kfree(buffer);
+		return USB_STOR_TRANSPORT_ERROR;
+	}
+
+	/* Figure out the initial LBA and page */
+	lba = address >> blockshift;
+	page = (address & MEDIA_INFO(us).blockmask);
+	max_lba = MEDIA_INFO(us).capacity >> (pageshift + blockshift);
+
+	result = USB_STOR_TRANSPORT_GOOD;
+	index = offset = 0;
+
+	while (sectors > 0) {
+		/* Write as many sectors as possible in this block */
+		unsigned int pages = min(sectors, blocksize - page);
+		len = pages << pageshift;
+
+		/* Not overflowing capacity? */
+		if (lba >= max_lba) {
+			US_DEBUGP("alauda_write_data: Requested lba %u exceeds "
+				  "maximum %u\n", lba, max_lba);
+			result = USB_STOR_TRANSPORT_ERROR;
+			break;
+		}
+
+		/* Get the data from the transfer buffer */
+		usb_stor_access_xfer_buf(buffer, len, us->srb,
+				&index, &offset, FROM_XFER_BUF);
+
+		result = alauda_write_lba(us, lba, page, pages, buffer,
+			blockbuffer);
+		if (result != USB_STOR_TRANSPORT_GOOD)
+			break;
+
+		page = 0;
+		lba++;
+		sectors -= pages;
+	}
+
+	kfree(buffer);
+	kfree(blockbuffer);
+	return result;
+}
+
+/*
+ * Our interface with the rest of the world
+ */
+
+static void alauda_info_destructor(void *extra)
+{
+	struct alauda_info *info = (struct alauda_info *) extra;
+	int port;
+
+	if (!info)
+		return;
+
+	for (port = 0; port < 2; port++) {
+		struct alauda_media_info *media_info = &info->port[port];
+
+		alauda_free_maps(media_info);
+		kfree(media_info->lba_to_pba);
+		kfree(media_info->pba_to_lba);
+	}
+}
+
+/*
+ * Initialize alauda_info struct and find the data-write endpoint
+ */
+int init_alauda(struct us_data *us)
+{
+	struct alauda_info *info;
+	struct usb_host_interface *altsetting = us->pusb_intf->cur_altsetting;
+	nand_init_ecc();
+
+	us->extra = kzalloc(sizeof(struct alauda_info), GFP_NOIO);
+	if (!us->extra) {
+		US_DEBUGP("init_alauda: Gah! Can't allocate storage for"
+			"alauda info struct!\n");
+		return USB_STOR_TRANSPORT_ERROR;
+	}
+	info = (struct alauda_info *) us->extra;
+	us->extra_destructor = alauda_info_destructor;
+
+	info->wr_ep = usb_sndbulkpipe(us->pusb_dev,
+		altsetting->endpoint[0].desc.bEndpointAddress
+		& USB_ENDPOINT_NUMBER_MASK);
+
+	return USB_STOR_TRANSPORT_GOOD;
+}
+
+int alauda_transport(struct scsi_cmnd *srb, struct us_data *us)
+{
+	int rc;
+	struct alauda_info *info = (struct alauda_info *) us->extra;
+	unsigned char *ptr = us->iobuf;
+	static unsigned char inquiry_response[36] = {
+		0x00, 0x80, 0x00, 0x01, 0x1F, 0x00, 0x00, 0x00
+	};
+
+	if (srb->cmnd[0] == INQUIRY) {
+		US_DEBUGP("alauda_transport: INQUIRY. "
+			"Returning bogus response.\n");
+		memcpy(ptr, inquiry_response, sizeof(inquiry_response));
+		fill_inquiry_response(us, ptr, 36);
+		return USB_STOR_TRANSPORT_GOOD;
+	}
+
+	if (srb->cmnd[0] == TEST_UNIT_READY) {
+		US_DEBUGP("alauda_transport: TEST_UNIT_READY.\n");
+		return alauda_check_media(us);
+	}
+
+	if (srb->cmnd[0] == READ_CAPACITY) {
+		unsigned int num_zones;
+		unsigned long capacity;
+
+		rc = alauda_check_media(us);
+		if (rc != USB_STOR_TRANSPORT_GOOD)
+			return rc;
+
+		num_zones = MEDIA_INFO(us).capacity >> (MEDIA_INFO(us).zoneshift
+			+ MEDIA_INFO(us).blockshift + MEDIA_INFO(us).pageshift);
+
+		capacity = num_zones * MEDIA_INFO(us).uzonesize
+			* MEDIA_INFO(us).blocksize;
+
+		/* Report capacity and page size */
+		((__be32 *) ptr)[0] = cpu_to_be32(capacity - 1);
+		((__be32 *) ptr)[1] = cpu_to_be32(512);
+
+		usb_stor_set_xfer_buf(ptr, 8, srb);
+		return USB_STOR_TRANSPORT_GOOD;
+	}
+
+	if (srb->cmnd[0] == READ_10) {
+		unsigned int page, pages;
+
+		rc = alauda_check_media(us);
+		if (rc != USB_STOR_TRANSPORT_GOOD)
+			return rc;
+
+		page = short_pack(srb->cmnd[3], srb->cmnd[2]);
+		page <<= 16;
+		page |= short_pack(srb->cmnd[5], srb->cmnd[4]);
+		pages = short_pack(srb->cmnd[8], srb->cmnd[7]);
+
+		US_DEBUGP("alauda_transport: READ_10: page %d pagect %d\n",
+			  page, pages);
+
+		return alauda_read_data(us, page, pages);
+	}
+
+	if (srb->cmnd[0] == WRITE_10) {
+		unsigned int page, pages;
+
+		rc = alauda_check_media(us);
+		if (rc != USB_STOR_TRANSPORT_GOOD)
+			return rc;
+
+		page = short_pack(srb->cmnd[3], srb->cmnd[2]);
+		page <<= 16;
+		page |= short_pack(srb->cmnd[5], srb->cmnd[4]);
+		pages = short_pack(srb->cmnd[8], srb->cmnd[7]);
+
+		US_DEBUGP("alauda_transport: WRITE_10: page %d pagect %d\n",
+			  page, pages);
+
+		return alauda_write_data(us, page, pages);
+	}
+
+	if (srb->cmnd[0] == REQUEST_SENSE) {
+		US_DEBUGP("alauda_transport: REQUEST_SENSE.\n");
+
+		memset(ptr, 0, 18);
+		ptr[0] = 0xF0;
+		ptr[2] = info->sense_key;
+		ptr[7] = 11;
+		ptr[12] = info->sense_asc;
+		ptr[13] = info->sense_ascq;
+		usb_stor_set_xfer_buf(ptr, 18, srb);
+
+		return USB_STOR_TRANSPORT_GOOD;
+	}
+
+	if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) {
+		/* sure.  whatever.  not like we can stop the user from popping
+		   the media out of the device (no locking doors, etc) */
+		return USB_STOR_TRANSPORT_GOOD;
+	}
+
+	US_DEBUGP("alauda_transport: Gah! Unknown command: %d (0x%x)\n",
+		srb->cmnd[0], srb->cmnd[0]);
+	info->sense_key = 0x05;
+	info->sense_asc = 0x20;
+	info->sense_ascq = 0x00;
+	return USB_STOR_TRANSPORT_FAILED;
+}
+
diff --git a/drivers/usb/storage/alauda.h b/drivers/usb/storage/alauda.h
new file mode 100644
index 000000000000..a700f87d0803
--- /dev/null
+++ b/drivers/usb/storage/alauda.h
@@ -0,0 +1,100 @@
+/*
+ * Driver for Alauda-based card readers
+ *
+ * Current development and maintenance by:
+ *    (c) 2005 Daniel Drake <dsd@gentoo.org>
+ *
+ * See alauda.c for more explanation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _USB_ALAUDA_H
+#define _USB_ALAUDA_H
+
+/*
+ * Status bytes
+ */
+#define ALAUDA_STATUS_ERROR		0x01
+#define ALAUDA_STATUS_READY		0x40
+
+/*
+ * Control opcodes (for request field)
+ */
+#define ALAUDA_GET_XD_MEDIA_STATUS	0x08
+#define ALAUDA_GET_SM_MEDIA_STATUS	0x98
+#define ALAUDA_ACK_XD_MEDIA_CHANGE	0x0a
+#define ALAUDA_ACK_SM_MEDIA_CHANGE	0x9a
+#define ALAUDA_GET_XD_MEDIA_SIG		0x86
+#define ALAUDA_GET_SM_MEDIA_SIG		0x96
+
+/*
+ * Bulk command identity (byte 0)
+ */
+#define ALAUDA_BULK_CMD			0x40
+
+/*
+ * Bulk opcodes (byte 1)
+ */
+#define ALAUDA_BULK_GET_REDU_DATA	0x85
+#define ALAUDA_BULK_READ_BLOCK		0x94
+#define ALAUDA_BULK_ERASE_BLOCK		0xa3
+#define ALAUDA_BULK_WRITE_BLOCK		0xb4
+#define ALAUDA_BULK_GET_STATUS2		0xb7
+#define ALAUDA_BULK_RESET_MEDIA		0xe0
+
+/*
+ * Port to operate on (byte 8)
+ */
+#define ALAUDA_PORT_XD			0x00
+#define ALAUDA_PORT_SM			0x01
+
+/*
+ * LBA and PBA are unsigned ints. Special values.
+ */
+#define UNDEF    0xffff
+#define SPARE    0xfffe
+#define UNUSABLE 0xfffd
+
+int init_alauda(struct us_data *us);
+int alauda_transport(struct scsi_cmnd *srb, struct us_data *us);
+
+struct alauda_media_info {
+	unsigned long capacity;		/* total media size in bytes */
+	unsigned int pagesize;		/* page size in bytes */
+	unsigned int blocksize;		/* number of pages per block */
+	unsigned int uzonesize;		/* number of usable blocks per zone */
+	unsigned int zonesize;		/* number of blocks per zone */
+	unsigned int blockmask;		/* mask to get page from address */
+
+	unsigned char pageshift;
+	unsigned char blockshift;
+	unsigned char zoneshift;
+
+	u16 **lba_to_pba;		/* logical to physical block map */
+	u16 **pba_to_lba;		/* physical to logical block map */
+};
+
+struct alauda_info {
+	struct alauda_media_info port[2];
+	int wr_ep;			/* endpoint to write data out of */
+
+	unsigned char sense_key;
+	unsigned long sense_asc;	/* additional sense code */
+	unsigned long sense_ascq;	/* additional sense code qualifier */
+};
+
+#endif
+
diff --git a/drivers/usb/storage/debug.c b/drivers/usb/storage/debug.c
index 5a9321705a74..01e430654a13 100644
--- a/drivers/usb/storage/debug.c
+++ b/drivers/usb/storage/debug.c
@@ -132,6 +132,7 @@ void usb_stor_show_command(struct scsi_cmnd *srb)
 	case 0x5C: what = "READ BUFFER CAPACITY"; break;
 	case 0x5D: what = "SEND CUE SHEET"; break;
 	case GPCMD_BLANK: what = "BLANK"; break;
+	case REPORT_LUNS: what = "REPORT LUNS"; break;
 	case MOVE_MEDIUM: what = "MOVE_MEDIUM or PLAY AUDIO (12)"; break;
 	case READ_12: what = "READ_12"; break;
 	case WRITE_12: what = "WRITE_12"; break;
diff --git a/drivers/usb/storage/initializers.h b/drivers/usb/storage/initializers.h
index 7372386f33d5..4c1b2bd2e2e4 100644
--- a/drivers/usb/storage/initializers.h
+++ b/drivers/usb/storage/initializers.h
@@ -45,10 +45,6 @@
  * mode */
 int usb_stor_euscsi_init(struct us_data *us);
 
-#ifdef CONFIG_USB_STORAGE_SDDR09
-int sddr09_init(struct us_data *us);
-#endif
-
 /* This function is required to activate all four slots on the UCR-61S2B
  * flash reader */
 int usb_stor_ucr61s2b_init(struct us_data *us);
diff --git a/drivers/usb/storage/libusual.c b/drivers/usb/storage/libusual.c
new file mode 100644
index 000000000000..b28151d1b609
--- /dev/null
+++ b/drivers/usb/storage/libusual.c
@@ -0,0 +1,266 @@
+/*
+ * libusual
+ *
+ * The libusual contains the table of devices common for ub and usb-storage.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/usb_usual.h>
+#include <linux/vmalloc.h>
+
+/*
+ */
+#define USU_MOD_FL_THREAD   1	/* Thread is running */
+#define USU_MOD_FL_PRESENT  2	/* The module is loaded */
+
+struct mod_status {
+	unsigned long fls;
+};
+
+static struct mod_status stat[3];
+static DEFINE_SPINLOCK(usu_lock);
+
+/*
+ */
+#define USB_US_DEFAULT_BIAS	USB_US_TYPE_STOR
+static atomic_t usu_bias = ATOMIC_INIT(USB_US_DEFAULT_BIAS);
+
+#define BIAS_NAME_SIZE  (sizeof("usb-storage"))
+static const char *bias_names[3] = { "none", "usb-storage", "ub" };
+
+static DECLARE_MUTEX_LOCKED(usu_init_notify);
+static DECLARE_COMPLETION(usu_end_notify);
+static atomic_t total_threads = ATOMIC_INIT(0);
+
+static int usu_probe_thread(void *arg);
+
+/*
+ * The table.
+ */
+#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
+		    vendorName, productName,useProtocol, useTransport, \
+		    initFunction, flags) \
+{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax), \
+  .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
+
+#define USUAL_DEV(useProto, useTrans, useType) \
+{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \
+  .driver_info = ((useType)<<24) }
+
+struct usb_device_id storage_usb_ids [] = {
+#	include "unusual_devs.h"
+	{ } /* Terminating entry */
+};
+
+#undef USUAL_DEV
+#undef UNUSUAL_DEV
+
+MODULE_DEVICE_TABLE(usb, storage_usb_ids);
+EXPORT_SYMBOL_GPL(storage_usb_ids);
+
+/*
+ * @type: the module type as an integer
+ */
+void usb_usual_set_present(int type)
+{
+	struct mod_status *st;
+	unsigned long flags;
+
+	if (type <= 0 || type >= 3)
+		return;
+	st = &stat[type];
+	spin_lock_irqsave(&usu_lock, flags);
+	st->fls |= USU_MOD_FL_PRESENT;
+	spin_unlock_irqrestore(&usu_lock, flags);
+}
+EXPORT_SYMBOL_GPL(usb_usual_set_present);
+
+void usb_usual_clear_present(int type)
+{
+	struct mod_status *st;
+	unsigned long flags;
+
+	if (type <= 0 || type >= 3)
+		return;
+	st = &stat[type];
+	spin_lock_irqsave(&usu_lock, flags);
+	st->fls &= ~USU_MOD_FL_PRESENT;
+	spin_unlock_irqrestore(&usu_lock, flags);
+}
+EXPORT_SYMBOL_GPL(usb_usual_clear_present);
+
+/*
+ * Match the calling driver type against the table.
+ * Returns: 0 if the device matches.
+ */
+int usb_usual_check_type(const struct usb_device_id *id, int caller_type)
+{
+	int id_type = USB_US_TYPE(id->driver_info);
+
+	if (caller_type <= 0 || caller_type >= 3)
+		return -EINVAL;
+
+	/* Drivers grab fixed assignment devices */
+	if (id_type == caller_type)
+		return 0;
+	/* Drivers grab devices biased to them */
+	if (id_type == USB_US_TYPE_NONE && caller_type == atomic_read(&usu_bias))
+		return 0;
+	return -ENODEV;
+}
+EXPORT_SYMBOL_GPL(usb_usual_check_type);
+
+/*
+ */
+static int usu_probe(struct usb_interface *intf,
+			 const struct usb_device_id *id)
+{
+	int type;
+	int rc;
+	unsigned long flags;
+
+	type = USB_US_TYPE(id->driver_info);
+	if (type == 0)
+		type = atomic_read(&usu_bias);
+
+	spin_lock_irqsave(&usu_lock, flags);
+	if ((stat[type].fls & (USU_MOD_FL_THREAD|USU_MOD_FL_PRESENT)) != 0) {
+		spin_unlock_irqrestore(&usu_lock, flags);
+		return -ENXIO;
+	}
+	stat[type].fls |= USU_MOD_FL_THREAD;
+	spin_unlock_irqrestore(&usu_lock, flags);
+
+	rc = kernel_thread(usu_probe_thread, (void*)type, CLONE_VM);
+	if (rc < 0) {
+		printk(KERN_WARNING "libusual: "
+		    "Unable to start the thread for %s: %d\n",
+		    bias_names[type], rc);
+		spin_lock_irqsave(&usu_lock, flags);
+		stat[type].fls &= ~USU_MOD_FL_THREAD;
+		spin_unlock_irqrestore(&usu_lock, flags);
+		return rc;	/* Not being -ENXIO causes a message printed */
+	}
+	atomic_inc(&total_threads);
+
+	return -ENXIO;
+}
+
+static void usu_disconnect(struct usb_interface *intf)
+{
+	;	/* We should not be here. */
+}
+
+static struct usb_driver usu_driver = {
+	.name =		"libusual",
+	.probe =	usu_probe,
+	.disconnect =	usu_disconnect,
+	.id_table =	storage_usb_ids,
+};
+
+/*
+ * A whole new thread for a purpose of request_module seems quite stupid.
+ * The request_module forks once inside again. However, if we attempt
+ * to load a storage module from our own modprobe thread, that module
+ * references our symbols, which cannot be resolved until our module is
+ * initialized. I wish there was a way to wait for the end of initialization.
+ * The module notifier reports MODULE_STATE_COMING only.
+ * So, we wait until module->init ends as the next best thing.
+ */
+static int usu_probe_thread(void *arg)
+{
+	int type = (unsigned long) arg;
+	struct mod_status *st = &stat[type];
+	int rc;
+	unsigned long flags;
+
+	daemonize("libusual_%d", type);	/* "usb-storage" is kinda too long */
+
+	/* A completion does not work here because it's counted. */
+	down(&usu_init_notify);
+	up(&usu_init_notify);
+
+	rc = request_module(bias_names[type]);
+	spin_lock_irqsave(&usu_lock, flags);
+	if (rc == 0 && (st->fls & USU_MOD_FL_PRESENT) == 0) {
+		/*
+		 * This should not happen, but let us keep tabs on it.
+		 */
+		printk(KERN_NOTICE "libusual: "
+		    "modprobe for %s succeeded, but module is not present\n",
+		    bias_names[type]);
+	}
+	st->fls &= ~USU_MOD_FL_THREAD;
+	spin_unlock_irqrestore(&usu_lock, flags);
+
+	complete_and_exit(&usu_end_notify, 0);
+}
+
+/*
+ */
+static int __init usb_usual_init(void)
+{
+	int rc;
+
+	rc = usb_register(&usu_driver);
+	up(&usu_init_notify);
+	return rc;
+}
+
+static void __exit usb_usual_exit(void)
+{
+	/*
+	 * We do not check for any drivers present, because
+	 * they keep us pinned with symbol references.
+	 */
+
+	usb_deregister(&usu_driver);
+
+	while (atomic_read(&total_threads) > 0) {
+		wait_for_completion(&usu_end_notify);
+		atomic_dec(&total_threads);
+	}
+}
+
+/*
+ * Validate and accept the bias parameter.
+ */
+static int usu_set_bias(const char *bias_s, struct kernel_param *kp)
+{
+	int i;
+	int len;
+	int bias_n = 0;
+
+	len = strlen(bias_s);
+	if (len == 0)
+		return -EDOM;
+	if (bias_s[len-1] == '\n')
+		--len;
+
+	for (i = 1; i < 3; i++) {
+		if (strncmp(bias_s, bias_names[i], len) == 0) {
+			bias_n = i;
+			break;
+		}
+	}
+	if (bias_n == 0)
+		return -EINVAL;
+
+	atomic_set(&usu_bias, bias_n);
+	return 0;
+}
+
+static int usu_get_bias(char *buffer, struct kernel_param *kp)
+{
+	return strlen(strcpy(buffer, bias_names[atomic_read(&usu_bias)]));
+}
+
+module_init(usb_usual_init);
+module_exit(usb_usual_exit);
+
+module_param_call(bias, usu_set_bias, usu_get_bias, NULL, S_IRUGO|S_IWUSR);
+__MODULE_PARM_TYPE(bias, "string");
+MODULE_PARM_DESC(bias, "Bias to usb-storage or ub");
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c
index 89401a59f952..55ee2d36d585 100644
--- a/drivers/usb/storage/onetouch.c
+++ b/drivers/usb/storage/onetouch.c
@@ -52,6 +52,7 @@ struct usb_onetouch {
 	struct urb *irq;	/* urb for interrupt in report */
 	unsigned char *data;	/* input data */
 	dma_addr_t data_dma;
+	unsigned int is_open:1;
 };
 
 static void usb_onetouch_irq(struct urb *urb, struct pt_regs *regs)
@@ -89,6 +90,7 @@ static int usb_onetouch_open(struct input_dev *dev)
 {
 	struct usb_onetouch *onetouch = dev->private;
 
+	onetouch->is_open = 1;
 	onetouch->irq->dev = onetouch->udev;
 	if (usb_submit_urb(onetouch->irq, GFP_KERNEL)) {
 		err("usb_submit_urb failed");
@@ -103,8 +105,30 @@ static void usb_onetouch_close(struct input_dev *dev)
 	struct usb_onetouch *onetouch = dev->private;
 
 	usb_kill_urb(onetouch->irq);
+	onetouch->is_open = 0;
 }
 
+#ifdef CONFIG_PM
+static void usb_onetouch_pm_hook(struct us_data *us, int action)
+{
+	struct usb_onetouch *onetouch = (struct usb_onetouch *) us->extra;
+
+	if (onetouch->is_open) {
+		switch (action) {
+		case US_SUSPEND:
+			usb_kill_urb(onetouch->irq);
+			break;
+		case US_RESUME:
+			if (usb_submit_urb(onetouch->irq, GFP_KERNEL) != 0)
+				err("usb_submit_urb failed");
+			break;
+		default:
+			break;
+		}
+	}
+}
+#endif /* CONFIG_PM */
+
 int onetouch_connect_input(struct us_data *ss)
 {
 	struct usb_device *udev = ss->pusb_dev;
@@ -185,6 +209,9 @@ int onetouch_connect_input(struct us_data *ss)
 
 	ss->extra_destructor = onetouch_release_input;
 	ss->extra = onetouch;
+#ifdef CONFIG_PM
+	ss->suspend_resume_hook = usb_onetouch_pm_hook;
+#endif
 
 	input_register_device(onetouch->dev);
 
diff --git a/drivers/usb/storage/protocol.h b/drivers/usb/storage/protocol.h
index 02bff01ab09c..845bed4b8031 100644
--- a/drivers/usb/storage/protocol.h
+++ b/drivers/usb/storage/protocol.h
@@ -41,20 +41,6 @@
 #ifndef _PROTOCOL_H_
 #define _PROTOCOL_H_
 
-/* Sub Classes */
-
-#define US_SC_RBC	0x01		/* Typically, flash devices */
-#define US_SC_8020	0x02		/* CD-ROM */
-#define US_SC_QIC	0x03		/* QIC-157 Tapes */
-#define US_SC_UFI	0x04		/* Floppy */
-#define US_SC_8070	0x05		/* Removable media */
-#define US_SC_SCSI	0x06		/* Transparent */
-#define US_SC_ISD200    0x07		/* ISD200 ATA */
-#define US_SC_MIN	US_SC_RBC
-#define US_SC_MAX	US_SC_ISD200
-
-#define US_SC_DEVICE	0xff		/* Use device's value */
-
 /* Protocol handling routines */
 extern void usb_stor_ATAPI_command(struct scsi_cmnd*, struct us_data*);
 extern void usb_stor_qic157_command(struct scsi_cmnd*, struct us_data*);
diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c
index 0ea2f5ab66ba..fb8bacaae27c 100644
--- a/drivers/usb/storage/sddr09.c
+++ b/drivers/usb/storage/sddr09.c
@@ -133,13 +133,11 @@ static struct nand_flash_dev nand_flash_ids[] = {
 	{ 0,}
 };
 
-#define SIZE(a)	(sizeof(a)/sizeof((a)[0]))
-
 static struct nand_flash_dev *
 nand_find_id(unsigned char id) {
 	int i;
 
-	for (i = 0; i < SIZE(nand_flash_ids); i++)
+	for (i = 0; i < ARRAY_SIZE(nand_flash_ids); i++)
 		if (nand_flash_ids[i].model_id == id)
 			return &(nand_flash_ids[i]);
 	return NULL;
@@ -214,6 +212,20 @@ static void nand_store_ecc(unsigned char *data, unsigned char *ecc) {
  * The actual driver starts here.
  */
 
+struct sddr09_card_info {
+	unsigned long	capacity;	/* Size of card in bytes */
+	int		pagesize;	/* Size of page in bytes */
+	int		pageshift;	/* log2 of pagesize */
+	int		blocksize;	/* Size of block in pages */
+	int		blockshift;	/* log2 of blocksize */
+	int		blockmask;	/* 2^blockshift - 1 */
+	int		*lba_to_pba;	/* logical to physical map */
+	int		*pba_to_lba;	/* physical to logical map */
+	int		lbact;		/* number of available pages */
+	int		flags;
+#define	SDDR09_WP	1		/* write protected */
+};
+
 /*
  * On my 16MB card, control blocks have size 64 (16 real control bytes,
  * and 48 junk bytes). In reality of course the card uses 16 control bytes,
@@ -237,7 +249,7 @@ static void nand_store_ecc(unsigned char *data, unsigned char *ecc) {
 #define SPARE    0xfffffffe
 #define UNUSABLE 0xfffffffd
 
-static int erase_bad_lba_entries = 0;
+static const int erase_bad_lba_entries = 0;
 
 /* send vendor interface command (0x41) */
 /* called for requests 0, 1, 8 */
@@ -260,8 +272,11 @@ sddr09_send_command(struct us_data *us,
 
 	rc = usb_stor_ctrl_transfer(us, pipe, request, requesttype,
 				   0, 0, xfer_data, xfer_len);
-	return (rc == USB_STOR_XFER_GOOD ? USB_STOR_TRANSPORT_GOOD :
-			USB_STOR_TRANSPORT_ERROR);
+	switch (rc) {
+		case USB_STOR_XFER_GOOD:	return 0;
+		case USB_STOR_XFER_STALLED:	return -EPIPE;
+		default:			return -EIO;
+	}
 }
 
 static int
@@ -308,20 +323,12 @@ sddr09_request_sense(struct us_data *us, unsigned char *sensebuf, int buflen) {
 	command[4] = buflen;
 
 	result = sddr09_send_scsi_command(us, command, 12);
-	if (result != USB_STOR_TRANSPORT_GOOD) {
-		US_DEBUGP("request sense failed\n");
+	if (result)
 		return result;
-	}
 
 	result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
 			sensebuf, buflen, NULL);
-	if (result != USB_STOR_XFER_GOOD) {
-		US_DEBUGP("request sense bulk in failed\n");
-		return USB_STOR_TRANSPORT_ERROR;
-	} else {
-		US_DEBUGP("request sense worked\n");
-		return USB_STOR_TRANSPORT_GOOD;
-	}
+	return (result == USB_STOR_XFER_GOOD ? 0 : -EIO);
 }
 
 /*
@@ -369,7 +376,7 @@ sddr09_readX(struct us_data *us, int x, unsigned long fromaddress,
 
 	result = sddr09_send_scsi_command(us, command, 12);
 
-	if (result != USB_STOR_TRANSPORT_GOOD) {
+	if (result) {
 		US_DEBUGP("Result for send_control in sddr09_read2%d %d\n",
 			  x, result);
 		return result;
@@ -381,9 +388,9 @@ sddr09_readX(struct us_data *us, int x, unsigned long fromaddress,
 	if (result != USB_STOR_XFER_GOOD) {
 		US_DEBUGP("Result for bulk_transfer in sddr09_read2%d %d\n",
 			  x, result);
-		return USB_STOR_TRANSPORT_ERROR;
+		return -EIO;
 	}
-	return USB_STOR_TRANSPORT_GOOD;
+	return 0;
 }
 
 /*
@@ -497,7 +504,7 @@ sddr09_erase(struct us_data *us, unsigned long Eaddress) {
 
 	result = sddr09_send_scsi_command(us, command, 12);
 
-	if (result != USB_STOR_TRANSPORT_GOOD)
+	if (result)
 		US_DEBUGP("Result for send_control in sddr09_erase %d\n",
 			  result);
 
@@ -555,7 +562,7 @@ sddr09_writeX(struct us_data *us,
 
 	result = sddr09_send_scsi_command(us, command, 12);
 
-	if (result != USB_STOR_TRANSPORT_GOOD) {
+	if (result) {
 		US_DEBUGP("Result for send_control in sddr09_writeX %d\n",
 			  result);
 		return result;
@@ -567,9 +574,9 @@ sddr09_writeX(struct us_data *us,
 	if (result != USB_STOR_XFER_GOOD) {
 		US_DEBUGP("Result for bulk_transfer in sddr09_writeX %d\n",
 			  result);
-		return USB_STOR_TRANSPORT_ERROR;
+		return -EIO;
 	}
-	return USB_STOR_TRANSPORT_GOOD;
+	return 0;
 }
 
 /* erase address, write same address */
@@ -633,7 +640,7 @@ sddr09_read_sg_test_only(struct us_data *us) {
 
 	result = sddr09_send_scsi_command(us, command, 4*nsg+3);
 
-	if (result != USB_STOR_TRANSPORT_GOOD) {
+	if (result) {
 		US_DEBUGP("Result for send_control in sddr09_read_sg %d\n",
 			  result);
 		return result;
@@ -641,7 +648,7 @@ sddr09_read_sg_test_only(struct us_data *us) {
 
 	buf = (unsigned char *) kmalloc(bulklen, GFP_NOIO);
 	if (!buf)
-		return USB_STOR_TRANSPORT_ERROR;
+		return -ENOMEM;
 
 	result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
 				       buf, bulklen, NULL);
@@ -649,10 +656,10 @@ sddr09_read_sg_test_only(struct us_data *us) {
 	if (result != USB_STOR_XFER_GOOD) {
 		US_DEBUGP("Result for bulk_transfer in sddr09_read_sg %d\n",
 			  result);
-		return USB_STOR_TRANSPORT_ERROR;
+		return -EIO;
 	}
 
-	return USB_STOR_TRANSPORT_GOOD;
+	return 0;
 }
 #endif
 
@@ -681,14 +688,13 @@ sddr09_read_status(struct us_data *us, unsigned char *status) {
 	command[1] = LUNBITS;
 
 	result = sddr09_send_scsi_command(us, command, 12);
-	if (result != USB_STOR_TRANSPORT_GOOD)
+	if (result)
 		return result;
 
 	result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
 				       data, 64, NULL);
 	*status = data[0];
-	return (result == USB_STOR_XFER_GOOD ?
-			USB_STOR_TRANSPORT_GOOD : USB_STOR_TRANSPORT_ERROR);
+	return (result == USB_STOR_XFER_GOOD ? 0 : -EIO);
 }
 
 static int
@@ -703,6 +709,13 @@ sddr09_read_data(struct us_data *us,
 	unsigned int len, index, offset;
 	int result;
 
+	// Figure out the initial LBA and page
+	lba = address >> info->blockshift;
+	page = (address & info->blockmask);
+	maxlba = info->capacity >> (info->pageshift + info->blockshift);
+	if (lba >= maxlba)
+		return -EIO;
+
 	// Since we only read in one block at a time, we have to create
 	// a bounce buffer and move the data a piece at a time between the
 	// bounce buffer and the actual transfer buffer.
@@ -711,18 +724,13 @@ sddr09_read_data(struct us_data *us,
 	buffer = kmalloc(len, GFP_NOIO);
 	if (buffer == NULL) {
 		printk("sddr09_read_data: Out of memory\n");
-		return USB_STOR_TRANSPORT_ERROR;
+		return -ENOMEM;
 	}
 
-	// Figure out the initial LBA and page
-	lba = address >> info->blockshift;
-	page = (address & info->blockmask);
-	maxlba = info->capacity >> (info->pageshift + info->blockshift);
-
 	// This could be made much more efficient by checking for
 	// contiguous LBA's. Another exercise left to the student.
 
-	result = USB_STOR_TRANSPORT_GOOD;
+	result = 0;
 	index = offset = 0;
 
 	while (sectors > 0) {
@@ -735,7 +743,7 @@ sddr09_read_data(struct us_data *us,
 		if (lba >= maxlba) {
 			US_DEBUGP("Error: Requested lba %u exceeds "
 				  "maximum %u\n", lba, maxlba);
-			result = USB_STOR_TRANSPORT_ERROR;
+			result = -EIO;
 			break;
 		}
 
@@ -749,7 +757,7 @@ sddr09_read_data(struct us_data *us,
 
 			/* This is not really an error. It just means
 			   that the block has never been written.
-			   Instead of returning USB_STOR_TRANSPORT_ERROR
+			   Instead of returning an error
 			   it is better to return all zero data. */
 
 			memset(buffer, 0, len);
@@ -764,7 +772,7 @@ sddr09_read_data(struct us_data *us,
 
 			result = sddr09_read20(us, address>>1,
 					pages, info->pageshift, buffer, 0);
-			if (result != USB_STOR_TRANSPORT_GOOD)
+			if (result)
 				break;
 		}
 
@@ -830,7 +838,7 @@ sddr09_write_lba(struct us_data *us, unsigned int lba,
 		pba = sddr09_find_unused_pba(info, lba);
 		if (!pba) {
 			printk("sddr09_write_lba: Out of unused blocks\n");
-			return USB_STOR_TRANSPORT_ERROR;
+			return -ENOSPC;
 		}
 		info->pba_to_lba[pba] = lba;
 		info->lba_to_pba[lba] = pba;
@@ -841,7 +849,7 @@ sddr09_write_lba(struct us_data *us, unsigned int lba,
 		/* Maybe it is impossible to write to PBA 1.
 		   Fake success, but don't do anything. */
 		printk("sddr09: avoid writing to pba 1\n");
-		return USB_STOR_TRANSPORT_GOOD;
+		return 0;
 	}
 
 	pagelen = (1 << info->pageshift) + (1 << CONTROL_SHIFT);
@@ -850,7 +858,7 @@ sddr09_write_lba(struct us_data *us, unsigned int lba,
 	address = (pba << (info->pageshift + info->blockshift));
 	result = sddr09_read22(us, address>>1, info->blocksize,
 			       info->pageshift, blockbuffer, 0);
-	if (result != USB_STOR_TRANSPORT_GOOD)
+	if (result)
 		return result;
 
 	/* check old contents and fill lba */
@@ -897,7 +905,7 @@ sddr09_write_lba(struct us_data *us, unsigned int lba,
 	{
 		unsigned char status = 0;
 		int result2 = sddr09_read_status(us, &status);
-		if (result2 != USB_STOR_TRANSPORT_GOOD)
+		if (result2)
 			US_DEBUGP("sddr09_write_inplace: cannot read status\n");
 		else if (status != 0xc0)
 			US_DEBUGP("sddr09_write_inplace: status after write: 0x%x\n",
@@ -920,13 +928,20 @@ sddr09_write_data(struct us_data *us,
 		  unsigned int sectors) {
 
 	struct sddr09_card_info *info = (struct sddr09_card_info *) us->extra;
-	unsigned int lba, page, pages;
+	unsigned int lba, maxlba, page, pages;
 	unsigned int pagelen, blocklen;
 	unsigned char *blockbuffer;
 	unsigned char *buffer;
 	unsigned int len, index, offset;
 	int result;
 
+	// Figure out the initial LBA and page
+	lba = address >> info->blockshift;
+	page = (address & info->blockmask);
+	maxlba = info->capacity >> (info->pageshift + info->blockshift);
+	if (lba >= maxlba)
+		return -EIO;
+
 	// blockbuffer is used for reading in the old data, overwriting
 	// with the new data, and performing ECC calculations
 
@@ -938,7 +953,7 @@ sddr09_write_data(struct us_data *us,
 	blockbuffer = kmalloc(blocklen, GFP_NOIO);
 	if (!blockbuffer) {
 		printk("sddr09_write_data: Out of memory\n");
-		return USB_STOR_TRANSPORT_ERROR;
+		return -ENOMEM;
 	}
 
 	// Since we don't write the user data directly to the device,
@@ -950,14 +965,10 @@ sddr09_write_data(struct us_data *us,
 	if (buffer == NULL) {
 		printk("sddr09_write_data: Out of memory\n");
 		kfree(blockbuffer);
-		return USB_STOR_TRANSPORT_ERROR;
+		return -ENOMEM;
 	}
 
-	// Figure out the initial LBA and page
-	lba = address >> info->blockshift;
-	page = (address & info->blockmask);
-
-	result = USB_STOR_TRANSPORT_GOOD;
+	result = 0;
 	index = offset = 0;
 
 	while (sectors > 0) {
@@ -967,13 +978,21 @@ sddr09_write_data(struct us_data *us,
 		pages = min(sectors, info->blocksize - page);
 		len = (pages << info->pageshift);
 
+		/* Not overflowing capacity? */
+		if (lba >= maxlba) {
+			US_DEBUGP("Error: Requested lba %u exceeds "
+				  "maximum %u\n", lba, maxlba);
+			result = -EIO;
+			break;
+		}
+
 		// Get the data from the transfer buffer
 		usb_stor_access_xfer_buf(buffer, len, us->srb,
 				&index, &offset, FROM_XFER_BUF);
 
 		result = sddr09_write_lba(us, lba, page, pages,
 				buffer, blockbuffer);
-		if (result != USB_STOR_TRANSPORT_GOOD)
+		if (result)
 			break;
 
 		page = 0;
@@ -1022,7 +1041,7 @@ sddr09_read_deviceID(struct us_data *us, unsigned char *deviceID) {
 	command[1] = LUNBITS;
 
 	result = sddr09_send_scsi_command(us, command, 12);
-	if (result != USB_STOR_TRANSPORT_GOOD)
+	if (result)
 		return result;
 
 	result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
@@ -1031,8 +1050,7 @@ sddr09_read_deviceID(struct us_data *us, unsigned char *deviceID) {
 	for (i = 0; i < 4; i++)
 		deviceID[i] = content[i];
 
-	return (result == USB_STOR_XFER_GOOD ?
-			USB_STOR_TRANSPORT_GOOD : USB_STOR_TRANSPORT_ERROR);
+	return (result == USB_STOR_XFER_GOOD ? 0 : -EIO);
 }
 
 static int
@@ -1041,7 +1059,7 @@ sddr09_get_wp(struct us_data *us, struct sddr09_card_info *info) {
 	unsigned char status;
 
 	result = sddr09_read_status(us, &status);
-	if (result != USB_STOR_TRANSPORT_GOOD) {
+	if (result) {
 		US_DEBUGP("sddr09_get_wp: read_status fails\n");
 		return result;
 	}
@@ -1057,7 +1075,7 @@ sddr09_get_wp(struct us_data *us, struct sddr09_card_info *info) {
 	if (status & 0x1)
 		US_DEBUGP(" Error");
 	US_DEBUGP("\n");
-	return USB_STOR_TRANSPORT_GOOD;
+	return 0;
 }
 
 #if 0
@@ -1089,7 +1107,7 @@ sddr09_get_cardinfo(struct us_data *us, unsigned char flags) {
 
 	result = sddr09_read_deviceID(us, deviceID);
 
-	if (result != USB_STOR_TRANSPORT_GOOD) {
+	if (result) {
 		US_DEBUGP("Result of read_deviceID is %d\n", result);
 		printk("sddr09: could not read card info\n");
 		return NULL;
@@ -1200,7 +1218,7 @@ sddr09_read_map(struct us_data *us) {
 				us, address>>1,
 				min(alloc_blocks, numblocks - i),
 				buffer, 0);
-			if (result != USB_STOR_TRANSPORT_GOOD) {
+			if (result) {
 				result = -1;
 				goto done;
 			}
@@ -1342,29 +1360,53 @@ sddr09_card_info_destructor(void *extra) {
 	kfree(info->pba_to_lba);
 }
 
-static void
-sddr09_init_card_info(struct us_data *us) {
-	if (!us->extra) {
-		us->extra = kmalloc(sizeof(struct sddr09_card_info), GFP_NOIO);
-		if (us->extra) {
-			memset(us->extra, 0, sizeof(struct sddr09_card_info));
-			us->extra_destructor = sddr09_card_info_destructor;
-		}
+static int
+sddr09_common_init(struct us_data *us) {
+	int result;
+
+	/* set the configuration -- STALL is an acceptable response here */
+	if (us->pusb_dev->actconfig->desc.bConfigurationValue != 1) {
+		US_DEBUGP("active config #%d != 1 ??\n", us->pusb_dev
+				->actconfig->desc.bConfigurationValue);
+		return -EINVAL;
+	}
+
+	result = usb_reset_configuration(us->pusb_dev);
+	US_DEBUGP("Result of usb_reset_configuration is %d\n", result);
+	if (result == -EPIPE) {
+		US_DEBUGP("-- stall on control interface\n");
+	} else if (result != 0) {
+		/* it's not a stall, but another error -- time to bail */
+		US_DEBUGP("-- Unknown error.  Rejecting device\n");
+		return -EINVAL;
 	}
+
+	us->extra = kzalloc(sizeof(struct sddr09_card_info), GFP_NOIO);
+	if (!us->extra)
+		return -ENOMEM;
+	us->extra_destructor = sddr09_card_info_destructor;
+
+	nand_init_ecc();
+	return 0;
 }
 
+
 /*
  * This is needed at a very early stage. If this is not listed in the
  * unusual devices list but called from here then LUN 0 of the combo reader
  * is not recognized. But I do not know what precisely these calls do.
  */
 int
-sddr09_init(struct us_data *us) {
+usb_stor_sddr09_dpcm_init(struct us_data *us) {
 	int result;
 	unsigned char *data = us->iobuf;
 
+	result = sddr09_common_init(us);
+	if (result)
+		return result;
+
 	result = sddr09_send_command(us, 0x01, USB_DIR_IN, data, 2);
-	if (result != USB_STOR_TRANSPORT_GOOD) {
+	if (result) {
 		US_DEBUGP("sddr09_init: send_command fails\n");
 		return result;
 	}
@@ -1373,7 +1415,7 @@ sddr09_init(struct us_data *us) {
 	// get 07 02
 
 	result = sddr09_send_command(us, 0x08, USB_DIR_IN, data, 2);
-	if (result != USB_STOR_TRANSPORT_GOOD) {
+	if (result) {
 		US_DEBUGP("sddr09_init: 2nd send_command fails\n");
 		return result;
 	}
@@ -1382,7 +1424,7 @@ sddr09_init(struct us_data *us) {
 	// get 07 00
 
 	result = sddr09_request_sense(us, data, 18);
-	if (result == USB_STOR_TRANSPORT_GOOD && data[2] != 0) {
+	if (result == 0 && data[2] != 0) {
 		int j;
 		for (j=0; j<18; j++)
 			printk(" %02X", data[j]);
@@ -1398,7 +1440,7 @@ sddr09_init(struct us_data *us) {
 
 	// test unit ready
 
-	return USB_STOR_TRANSPORT_GOOD;		/* not result */
+	return 0;		/* not result */
 }
 
 /*
@@ -1427,13 +1469,6 @@ int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us)
 	};
 
 	info = (struct sddr09_card_info *)us->extra;
-	if (!info) {
-		nand_init_ecc();
-		sddr09_init_card_info(us);
-		info = (struct sddr09_card_info *)us->extra;
-		if (!info)
-			return USB_STOR_TRANSPORT_ERROR;
-	}
 
 	if (srb->cmnd[0] == REQUEST_SENSE && havefakesense) {
 		/* for a faked command, we have to follow with a faked sense */
@@ -1536,7 +1571,9 @@ int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us)
 		US_DEBUGP("READ_10: read page %d pagect %d\n",
 			  page, pages);
 
-		return sddr09_read_data(us, page, pages);
+		result = sddr09_read_data(us, page, pages);
+		return (result == 0 ? USB_STOR_TRANSPORT_GOOD :
+				USB_STOR_TRANSPORT_ERROR);
 	}
 
 	if (srb->cmnd[0] == WRITE_10) {
@@ -1549,7 +1586,9 @@ int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us)
 		US_DEBUGP("WRITE_10: write page %d pagect %d\n",
 			  page, pages);
 
-		return sddr09_write_data(us, page, pages);
+		result = sddr09_write_data(us, page, pages);
+		return (result == 0 ? USB_STOR_TRANSPORT_GOOD :
+				USB_STOR_TRANSPORT_ERROR);
 	}
 
 	/* catch-all for all other commands, except
@@ -1575,10 +1614,10 @@ int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us)
 	US_DEBUGP("SDDR09: Send control for command %s\n", ptr);
 
 	result = sddr09_send_scsi_command(us, srb->cmnd, 12);
-	if (result != USB_STOR_TRANSPORT_GOOD) {
+	if (result) {
 		US_DEBUGP("sddr09_transport: sddr09_send_scsi_command "
 			  "returns %d\n", result);
-		return result;
+		return USB_STOR_TRANSPORT_ERROR;
 	}
 
 	if (srb->request_bufflen == 0)
@@ -1606,3 +1645,10 @@ int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us)
 	return USB_STOR_TRANSPORT_GOOD;
 }
 
+/*
+ * Initialization routine for the sddr09 subdriver
+ */
+int
+usb_stor_sddr09_init(struct us_data *us) {
+	return sddr09_common_init(us);
+}
diff --git a/drivers/usb/storage/sddr09.h b/drivers/usb/storage/sddr09.h
index c9d78d6188b1..c03089a9ec38 100644
--- a/drivers/usb/storage/sddr09.h
+++ b/drivers/usb/storage/sddr09.h
@@ -31,18 +31,7 @@
 
 extern int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us);
 
-struct sddr09_card_info {
-	unsigned long	capacity;	/* Size of card in bytes */
-	int		pagesize;	/* Size of page in bytes */
-	int		pageshift;	/* log2 of pagesize */
-	int		blocksize;	/* Size of block in pages */
-	int		blockshift;	/* log2 of blocksize */
-	int		blockmask;	/* 2^blockshift - 1 */
-	int		*lba_to_pba;	/* logical to physical map */
-	int		*pba_to_lba;	/* physical to logical map */
-	int		lbact;		/* number of available pages */
-	int		flags;
-#define	SDDR09_WP	1		/* write protected */
-};
+extern int usb_stor_sddr09_dpcm_init(struct us_data *us);
+extern int usb_stor_sddr09_init(struct us_data *us);
 
 #endif
diff --git a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h
index 0a362cc781ad..633a715850a4 100644
--- a/drivers/usb/storage/transport.h
+++ b/drivers/usb/storage/transport.h
@@ -41,39 +41,8 @@
 #ifndef _TRANSPORT_H_
 #define _TRANSPORT_H_
 
-#include <linux/config.h>
 #include <linux/blkdev.h>
 
-/* Protocols */
-
-#define US_PR_CBI	0x00		/* Control/Bulk/Interrupt */
-#define US_PR_CB	0x01		/* Control/Bulk w/o interrupt */
-#define US_PR_BULK	0x50		/* bulk only */
-#ifdef CONFIG_USB_STORAGE_USBAT
-#define US_PR_USBAT	0x80		/* SCM-ATAPI bridge */
-#endif
-#ifdef CONFIG_USB_STORAGE_SDDR09
-#define US_PR_EUSB_SDDR09	0x81	/* SCM-SCSI bridge for SDDR-09 */
-#endif
-#ifdef CONFIG_USB_STORAGE_SDDR55
-#define US_PR_SDDR55	0x82		/* SDDR-55 (made up) */
-#endif
-#define US_PR_DPCM_USB  0xf0		/* Combination CB/SDDR09 */
-
-#ifdef CONFIG_USB_STORAGE_FREECOM
-#define US_PR_FREECOM   0xf1		/* Freecom */
-#endif
-
-#ifdef CONFIG_USB_STORAGE_DATAFAB
-#define US_PR_DATAFAB   0xf2		/* Datafab chipsets */
-#endif
-
-#ifdef CONFIG_USB_STORAGE_JUMPSHOT
-#define US_PR_JUMPSHOT  0xf3		/* Lexar Jumpshot */
-#endif
-
-#define US_PR_DEVICE	0xff		/* Use device's value */
-
 /*
  * Bulk only data structures
  */
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index f5f47a34b168..dc301e567cfc 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -79,13 +79,6 @@ UNUSUAL_DEV(  0x03f0, 0x0307, 0x0001, 0x0001,
 		US_SC_8070, US_PR_USBAT, init_usbat, 0),
 #endif
 
-/* Patch submitted by Mihnea-Costin Grigore <mihnea@zulu.ro> */
-UNUSUAL_DEV(  0x040d, 0x6205, 0x0003, 0x0003,
-		"VIA Technologies Inc.",
-		"USB 2.0 Card Reader",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
-		US_FL_IGNORE_RESIDUE ),
-
 /* Reported by Sebastian Kapfer <sebastian_kapfer@gmx.net>
  * and Olaf Hering <olh@suse.de> (different bcd's, same vendor/product)
  * for USB floppies that need the SINGLE_LUN enforcement.
@@ -96,6 +89,13 @@ UNUSUAL_DEV(  0x0409, 0x0040, 0x0000, 0x9999,
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN ),
 
+/* Patch submitted by Mihnea-Costin Grigore <mihnea@zulu.ro> */
+UNUSUAL_DEV(  0x040d, 0x6205, 0x0003, 0x0003,
+		"VIA Technologies Inc.",
+		"USB 2.0 Card Reader",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_IGNORE_RESIDUE ),
+
 /* Deduced by Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
  * Entry needed for flags: US_FL_FIX_INQUIRY because initial inquiry message
  * always fails and confuses drive.
@@ -187,6 +187,14 @@ UNUSUAL_DEV(  0x04b0, 0x0405, 0x0100, 0x0100,
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY),
 
+/* Patch for Nikon coolpix 2000
+ * Submitted by Fabien Cosse <fabien.cosse@wanadoo.fr>*/
+UNUSUAL_DEV(  0x04b0, 0x0301, 0x0010, 0x0010,
+		"NIKON",
+		"NIKON DSC E2000",
+		US_SC_DEVICE, US_PR_DEVICE,NULL,
+		US_FL_NOT_LOCKABLE ),
+
 /* BENQ DC5330
  * Reported by Manuel Fombuena <mfombuena@ya.com> and
  * Frank Copeland <fjc@thingy.apana.org.au> */
@@ -276,14 +284,14 @@ UNUSUAL_DEV(  0x04e6, 0x0002, 0x0100, 0x0100,
 UNUSUAL_DEV(  0x04e6, 0x0003, 0x0000, 0x9999, 
 		"Sandisk",
 		"ImageMate SDDR09",
-		US_SC_SCSI, US_PR_EUSB_SDDR09, NULL,
-		US_FL_SINGLE_LUN ),
+		US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init,
+		0),
 
 /* This entry is from Andries.Brouwer@cwi.nl */
 UNUSUAL_DEV(  0x04e6, 0x0005, 0x0100, 0x0208,
 		"SCM Microsystems",
 		"eUSB SmartMedia / CompactFlash Adapter",
-		US_SC_SCSI, US_PR_DPCM_USB, sddr09_init, 
+		US_SC_SCSI, US_PR_DPCM_USB, usb_stor_sddr09_dpcm_init,
 		0), 
 #endif
 
@@ -527,6 +535,13 @@ UNUSUAL_DEV(  0x057b, 0x0022, 0x0000, 0x9999,
 		"Silicon Media R/W",
 		US_SC_DEVICE, US_PR_DEVICE, NULL, 0),
 
+#ifdef CONFIG_USB_STORAGE_ALAUDA
+UNUSUAL_DEV(  0x0584, 0x0008, 0x0102, 0x0102,
+		"Fujifilm",
+		"DPC-R1 (Alauda)",
+ 		US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0 ),
+#endif
+
 /* Fabrizio Fellini <fello@libero.it> */
 UNUSUAL_DEV(  0x0595, 0x4343, 0x0000, 0x2210,
 		"Fujifilm",
@@ -673,8 +688,8 @@ UNUSUAL_DEV(  0x0644, 0x0000, 0x0100, 0x0100,
 UNUSUAL_DEV(  0x066b, 0x0105, 0x0100, 0x0100, 
 		"Olympus",
 		"Camedia MAUSB-2",
-		US_SC_SCSI, US_PR_EUSB_SDDR09, NULL,
-		US_FL_SINGLE_LUN ),
+		US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init,
+		0),
 #endif
 
 /* Reported by Darsen Lu <darsen@micro.ee.nthu.edu.tw> */
@@ -739,8 +754,8 @@ UNUSUAL_DEV(  0x0781, 0x0100, 0x0100, 0x0100,
 UNUSUAL_DEV(  0x0781, 0x0200, 0x0000, 0x9999, 
 		"Sandisk",
 		"ImageMate SDDR-09",
-		US_SC_SCSI, US_PR_EUSB_SDDR09, NULL,
-		US_FL_SINGLE_LUN ),
+		US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init,
+		0),
 #endif
 
 #ifdef CONFIG_USB_STORAGE_FREECOM
@@ -776,6 +791,13 @@ UNUSUAL_DEV(  0x07af, 0x0006, 0x0100, 0x0100,
  		US_SC_SCSI, US_PR_DPCM_USB, NULL, 0 ),
 #endif
 
+#ifdef CONFIG_USB_STORAGE_ALAUDA
+UNUSUAL_DEV(  0x07b4, 0x010a, 0x0102, 0x0102,
+		"Olympus",
+		"MAUSB-10 (Alauda)",
+ 		US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0 ),
+#endif
+
 #ifdef CONFIG_USB_STORAGE_DATAFAB
 UNUSUAL_DEV(  0x07c4, 0xa000, 0x0000, 0x0015,
 		"Datafab",
@@ -1134,3 +1156,27 @@ UNUSUAL_DEV(  0x55aa, 0xa103, 0x0000, 0x9999,
 		US_SC_SCSI, US_PR_SDDR55, NULL,
 		US_FL_SINGLE_LUN),
 #endif
+
+/* Control/Bulk transport for all SubClass values */
+USUAL_DEV(US_SC_RBC, US_PR_CB, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_8020, US_PR_CB, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_QIC, US_PR_CB, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_UFI, US_PR_CB, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_8070, US_PR_CB, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_SCSI, US_PR_CB, USB_US_TYPE_STOR),
+
+/* Control/Bulk/Interrupt transport for all SubClass values */
+USUAL_DEV(US_SC_RBC, US_PR_CBI, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_8020, US_PR_CBI, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_QIC, US_PR_CBI, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_UFI, US_PR_CBI, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_8070, US_PR_CBI, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_SCSI, US_PR_CBI, USB_US_TYPE_STOR),
+
+/* Bulk-only transport for all SubClass values */
+USUAL_DEV(US_SC_RBC, US_PR_BULK, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_8020, US_PR_BULK, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_QIC, US_PR_BULK, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_UFI, US_PR_BULK, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_8070, US_PR_BULK, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_SCSI, US_PR_BULK, 0),
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 3847ebed2aa4..dbcf23980ff1 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -94,6 +94,9 @@
 #ifdef CONFIG_USB_STORAGE_ONETOUCH
 #include "onetouch.h"
 #endif
+#ifdef CONFIG_USB_STORAGE_ALAUDA
+#include "alauda.h"
+#endif
 
 /* Some informational data */
 MODULE_AUTHOR("Matthew Dharm <mdharm-usb@one-eyed-alien.net>");
@@ -112,49 +115,33 @@ static atomic_t total_threads = ATOMIC_INIT(0);
 static DECLARE_COMPLETION(threads_gone);
 
 
-/* The entries in this table, except for final ones here
- * (USB_MASS_STORAGE_CLASS and the empty entry), correspond,
- * line for line with the entries of us_unsuaul_dev_list[].
+/*
+ * The entries in this table correspond, line for line,
+ * with the entries of us_unusual_dev_list[].
  */
+#ifndef CONFIG_USB_LIBUSUAL
 
 #define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
 		    vendorName, productName,useProtocol, useTransport, \
 		    initFunction, flags) \
-{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax) }
+{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax), \
+  .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
+
+#define USUAL_DEV(useProto, useTrans, useType) \
+{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \
+  .driver_info = (USB_US_TYPE_STOR<<24) }
 
 static struct usb_device_id storage_usb_ids [] = {
 
 #	include "unusual_devs.h"
 #undef UNUSUAL_DEV
-	/* Control/Bulk transport for all SubClass values */
-	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_RBC, US_PR_CB) },
-	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8020, US_PR_CB) },
-	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_QIC, US_PR_CB) },
-	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_UFI, US_PR_CB) },
-	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8070, US_PR_CB) },
-	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_CB) },
-
-	/* Control/Bulk/Interrupt transport for all SubClass values */
-	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_RBC, US_PR_CBI) },
-	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8020, US_PR_CBI) },
-	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_QIC, US_PR_CBI) },
-	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_UFI, US_PR_CBI) },
-	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8070, US_PR_CBI) },
-	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_CBI) },
-
-	/* Bulk-only transport for all SubClass values */
-	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_RBC, US_PR_BULK) },
-	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8020, US_PR_BULK) },
-	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_QIC, US_PR_BULK) },
-	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_UFI, US_PR_BULK) },
-	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8070, US_PR_BULK) },
-	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_BULK) },
-
+#undef USUAL_DEV
 	/* Terminating entry */
 	{ }
 };
 
 MODULE_DEVICE_TABLE (usb, storage_usb_ids);
+#endif /* CONFIG_USB_LIBUSUAL */
 
 /* This is the list of devices we recognize, along with their flag data */
 
@@ -167,7 +154,6 @@ MODULE_DEVICE_TABLE (usb, storage_usb_ids);
  * are free to use as many characters as you like.
  */
 
-#undef UNUSUAL_DEV
 #define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \
 		    vendor_name, product_name, use_protocol, use_transport, \
 		    init_function, Flags) \
@@ -177,53 +163,18 @@ MODULE_DEVICE_TABLE (usb, storage_usb_ids);
 	.useProtocol = use_protocol,	\
 	.useTransport = use_transport,	\
 	.initFunction = init_function,	\
-	.flags = Flags, \
+}
+
+#define USUAL_DEV(use_protocol, use_transport, use_type) \
+{ \
+	.useProtocol = use_protocol,	\
+	.useTransport = use_transport,	\
 }
 
 static struct us_unusual_dev us_unusual_dev_list[] = {
 #	include "unusual_devs.h" 
 #	undef UNUSUAL_DEV
-	/* Control/Bulk transport for all SubClass values */
-	{ .useProtocol = US_SC_RBC,
-	  .useTransport = US_PR_CB},
-	{ .useProtocol = US_SC_8020,
-	  .useTransport = US_PR_CB},
-	{ .useProtocol = US_SC_QIC,
-	  .useTransport = US_PR_CB},
-	{ .useProtocol = US_SC_UFI,
-	  .useTransport = US_PR_CB},
-	{ .useProtocol = US_SC_8070,
-	  .useTransport = US_PR_CB},
-	{ .useProtocol = US_SC_SCSI,
-	  .useTransport = US_PR_CB},
-
-	/* Control/Bulk/Interrupt transport for all SubClass values */
-	{ .useProtocol = US_SC_RBC,
-	  .useTransport = US_PR_CBI},
-	{ .useProtocol = US_SC_8020,
-	  .useTransport = US_PR_CBI},
-	{ .useProtocol = US_SC_QIC,
-	  .useTransport = US_PR_CBI},
-	{ .useProtocol = US_SC_UFI,
-	  .useTransport = US_PR_CBI},
-	{ .useProtocol = US_SC_8070,
-	  .useTransport = US_PR_CBI},
-	{ .useProtocol = US_SC_SCSI,
-	  .useTransport = US_PR_CBI},
-
-	/* Bulk-only transport for all SubClass values */
-	{ .useProtocol = US_SC_RBC,
-	  .useTransport = US_PR_BULK},
-	{ .useProtocol = US_SC_8020,
-	  .useTransport = US_PR_BULK},
-	{ .useProtocol = US_SC_QIC,
-	  .useTransport = US_PR_BULK},
-	{ .useProtocol = US_SC_UFI,
-	  .useTransport = US_PR_BULK},
-	{ .useProtocol = US_SC_8070,
-	  .useTransport = US_PR_BULK},
-	{ .useProtocol = US_SC_SCSI,
-	  .useTransport = US_PR_BULK},
+#	undef USUAL_DEV
 
 	/* Terminating entry */
 	{ NULL }
@@ -240,6 +191,8 @@ static int storage_suspend(struct usb_interface *iface, pm_message_t message)
 	down(&us->dev_semaphore);
 
 	US_DEBUGP("%s\n", __FUNCTION__);
+	if (us->suspend_resume_hook)
+		(us->suspend_resume_hook)(us, US_SUSPEND);
 	iface->dev.power.power_state.event = message.event;
 
 	/* When runtime PM is working, we'll set a flag to indicate
@@ -256,6 +209,8 @@ static int storage_resume(struct usb_interface *iface)
 	down(&us->dev_semaphore);
 
 	US_DEBUGP("%s\n", __FUNCTION__);
+	if (us->suspend_resume_hook)
+		(us->suspend_resume_hook)(us, US_RESUME);
 	iface->dev.power.power_state.event = PM_EVENT_ON;
 
 	up(&us->dev_semaphore);
@@ -484,14 +439,20 @@ static int associate_dev(struct us_data *us, struct usb_interface *intf)
 	return 0;
 }
 
+/* Find an unusual_dev descriptor (always succeeds in the current code) */
+static struct us_unusual_dev *find_unusual(const struct usb_device_id *id)
+{
+	const int id_index = id - storage_usb_ids;
+	return &us_unusual_dev_list[id_index];
+}
+
 /* Get the unusual_devs entries and the string descriptors */
-static void get_device_info(struct us_data *us, int id_index)
+static void get_device_info(struct us_data *us, const struct usb_device_id *id)
 {
 	struct usb_device *dev = us->pusb_dev;
 	struct usb_interface_descriptor *idesc =
 		&us->pusb_intf->cur_altsetting->desc;
-	struct us_unusual_dev *unusual_dev = &us_unusual_dev_list[id_index];
-	struct usb_device_id *id = &storage_usb_ids[id_index];
+	struct us_unusual_dev *unusual_dev = find_unusual(id);
 
 	/* Store the entries */
 	us->unusual_dev = unusual_dev;
@@ -501,7 +462,7 @@ static void get_device_info(struct us_data *us, int id_index)
 	us->protocol = (unusual_dev->useTransport == US_PR_DEVICE) ?
 			idesc->bInterfaceProtocol :
 			unusual_dev->useTransport;
-	us->flags = unusual_dev->flags;
+	us->flags = USB_US_ORIG_FLAGS(id->driver_info);
 
 	/*
 	 * This flag is only needed when we're in high-speed, so let's
@@ -516,7 +477,7 @@ static void get_device_info(struct us_data *us, int id_index)
 	 * from the unusual_devs.h table.
 	 */
 	if (id->idVendor || id->idProduct) {
-		static char *msgs[3] = {
+		static const char *msgs[3] = {
 			"an unneeded SubClass entry",
 			"an unneeded Protocol entry",
 			"unneeded SubClass and Protocol entries"};
@@ -529,7 +490,7 @@ static void get_device_info(struct us_data *us, int id_index)
 		if (unusual_dev->useTransport != US_PR_DEVICE &&
 			us->protocol == idesc->bInterfaceProtocol)
 			msg += 2;
-		if (msg >= 0 && !(unusual_dev->flags & US_FL_NEED_OVERRIDE))
+		if (msg >= 0 && !(us->flags & US_FL_NEED_OVERRIDE))
 			printk(KERN_NOTICE USB_STORAGE "This device "
 				"(%04x,%04x,%04x S %02x P %02x)"
 				" has %s in unusual_devs.h\n"
@@ -686,6 +647,15 @@ static int get_protocol(struct us_data *us)
 		break;
 #endif
 
+#ifdef CONFIG_USB_STORAGE_ALAUDA
+	case US_PR_ALAUDA:
+		us->transport_name  = "Alauda Control/Bulk";
+		us->transport = alauda_transport;
+		us->transport_reset = usb_stor_Bulk_reset;
+		us->max_lun = 1;
+		break;
+#endif
+
 	default:
 		return -EIO;
 	}
@@ -921,10 +891,12 @@ static int storage_probe(struct usb_interface *intf,
 {
 	struct Scsi_Host *host;
 	struct us_data *us;
-	const int id_index = id - storage_usb_ids; 
 	int result;
 	struct task_struct *th;
 
+	if (usb_usual_check_type(id, USB_US_TYPE_STOR))
+		return -ENXIO;
+
 	US_DEBUGP("USB Mass Storage device detected\n");
 
 	/*
@@ -957,29 +929,7 @@ static int storage_probe(struct usb_interface *intf,
 	 * of the match from the usb_device_id table, so we can find the
 	 * corresponding entry in the private table.
 	 */
-	get_device_info(us, id_index);
-
-#ifdef CONFIG_USB_STORAGE_SDDR09
-	if (us->protocol == US_PR_EUSB_SDDR09 ||
-			us->protocol == US_PR_DPCM_USB) {
-		/* set the configuration -- STALL is an acceptable response here */
-		if (us->pusb_dev->actconfig->desc.bConfigurationValue != 1) {
-			US_DEBUGP("active config #%d != 1 ??\n", us->pusb_dev
-				->actconfig->desc.bConfigurationValue);
-			goto BadDevice;
-		}
-		result = usb_reset_configuration(us->pusb_dev);
-
-		US_DEBUGP("Result of usb_reset_configuration is %d\n", result);
-		if (result == -EPIPE) {
-			US_DEBUGP("-- stall on control interface\n");
-		} else if (result != 0) {
-			/* it's not a stall, but another error -- time to bail */
-			US_DEBUGP("-- Unknown error.  Rejecting device\n");
-			goto BadDevice;
-		}
-	}
-#endif
+	get_device_info(us, id);
 
 	/* Get the transport, protocol, and pipe settings */
 	result = get_transport(us);
@@ -1044,7 +994,6 @@ static void storage_disconnect(struct usb_interface *intf)
  ***********************************************************************/
 
 static struct usb_driver usb_storage_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"usb-storage",
 	.probe =	storage_probe,
 	.disconnect =	storage_disconnect,
@@ -1062,9 +1011,10 @@ static int __init usb_stor_init(void)
 
 	/* register the driver, return usb_register return code if error */
 	retval = usb_register(&usb_storage_driver);
-	if (retval == 0)
+	if (retval == 0) {
 		printk(KERN_INFO "USB Mass Storage support registered.\n");
-
+		usb_usual_set_present(USB_US_TYPE_STOR);
+	}
 	return retval;
 }
 
@@ -1088,6 +1038,8 @@ static void __exit usb_stor_exit(void)
 		wait_for_completion(&threads_gone);
 		atomic_dec(&total_threads);
 	}
+
+	usb_usual_clear_present(USB_US_TYPE_STOR);
 }
 
 module_init(usb_stor_init);
diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
index 98b09711a739..7259fd1f6b0d 100644
--- a/drivers/usb/storage/usb.h
+++ b/drivers/usb/storage/usb.h
@@ -45,6 +45,7 @@
 #define _USB_H_
 
 #include <linux/usb.h>
+#include <linux/usb_usual.h>
 #include <linux/blkdev.h>
 #include <linux/smp_lock.h>
 #include <linux/completion.h>
@@ -63,38 +64,8 @@ struct us_unusual_dev {
 	__u8  useProtocol;
 	__u8  useTransport;
 	int (*initFunction)(struct us_data *);
-	unsigned int flags;
 };
 
-/*
- * Static flag definitions.  We use this roundabout technique so that the
- * proc_info() routine can automatically display a message for each flag.
- */
-#define US_DO_ALL_FLAGS						\
-	US_FLAG(SINGLE_LUN,	0x00000001)			\
-		/* allow access to only LUN 0 */		\
-	US_FLAG(NEED_OVERRIDE,	0x00000002)			\
-		/* unusual_devs entry is necessary */		\
-	US_FLAG(SCM_MULT_TARG,	0x00000004)			\
-		/* supports multiple targets */			\
-	US_FLAG(FIX_INQUIRY,	0x00000008)			\
-		/* INQUIRY response needs faking */		\
-	US_FLAG(FIX_CAPACITY,	0x00000010)			\
-		/* READ CAPACITY response too big */		\
-	US_FLAG(IGNORE_RESIDUE,	0x00000020)			\
-		/* reported residue is wrong */			\
-	US_FLAG(BULK32,		0x00000040)			\
-		/* Uses 32-byte CBW length */			\
-	US_FLAG(NOT_LOCKABLE,	0x00000080)			\
-		/* PREVENT/ALLOW not supported */		\
-	US_FLAG(GO_SLOW,	0x00000100)			\
-		/* Need delay after Command phase */		\
-	US_FLAG(NO_WP_DETECT,	0x00000200)			\
-		/* Don't check for write-protect */		\
-
-#define US_FLAG(name, value)	US_FL_##name = value ,
-enum { US_DO_ALL_FLAGS };
-#undef US_FLAG
 
 /* Dynamic flag definitions: used in set_bit() etc. */
 #define US_FLIDX_URB_ACTIVE	18  /* 0x00040000  current_urb is in use  */
@@ -122,7 +93,11 @@ enum { US_DO_ALL_FLAGS };
 typedef int (*trans_cmnd)(struct scsi_cmnd *, struct us_data*);
 typedef int (*trans_reset)(struct us_data*);
 typedef void (*proto_cmnd)(struct scsi_cmnd*, struct us_data*);
-typedef void (*extra_data_destructor)(void *);	 /* extra data destructor   */
+typedef void (*extra_data_destructor)(void *);	/* extra data destructor */
+typedef void (*pm_hook)(struct us_data *, int);	/* power management hook */
+
+#define US_SUSPEND	0
+#define US_RESUME	1
 
 /* we allocate one of these for every device that we remember */
 struct us_data {
@@ -178,6 +153,9 @@ struct us_data {
 	/* subdriver information */
 	void			*extra;		 /* Any extra data          */
 	extra_data_destructor	extra_destructor;/* extra data destructor   */
+#ifdef CONFIG_PM
+	pm_hook			suspend_resume_hook;
+#endif
 };
 
 /* Convert between us_data and the corresponding Scsi_Host */
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
index 6c3a53f8f26c..5d02f16b7d0e 100644
--- a/drivers/usb/usb-skeleton.c
+++ b/drivers/usb/usb-skeleton.c
@@ -39,10 +39,15 @@ MODULE_DEVICE_TABLE (usb, skel_table);
 /* Get a minor range for your devices from the usb maintainer */
 #define USB_SKEL_MINOR_BASE	192
 
+/* our private defines. if this grows any larger, use your own .h file */
+#define MAX_TRANSFER		( PAGE_SIZE - 512 )
+#define WRITES_IN_FLIGHT	8
+
 /* Structure to hold all of our device specific stuff */
 struct usb_skel {
 	struct usb_device *	udev;			/* the usb device for this device */
 	struct usb_interface *	interface;		/* the interface for this device */
+	struct semaphore	limit_sem;		/* limiting the number of writes in progress */
 	unsigned char *		bulk_in_buffer;		/* the buffer to receive data */
 	size_t			bulk_in_size;		/* the size of the receive buffer */
 	__u8			bulk_in_endpointAddr;	/* the address of the bulk in endpoint */
@@ -152,6 +157,7 @@ static void skel_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
 	/* free up our allocated buffer */
 	usb_buffer_free(urb->dev, urb->transfer_buffer_length, 
 			urb->transfer_buffer, urb->transfer_dma);
+	up(&dev->limit_sem);
 }
 
 static ssize_t skel_write(struct file *file, const char *user_buffer, size_t count, loff_t *ppos)
@@ -160,6 +166,7 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou
 	int retval = 0;
 	struct urb *urb = NULL;
 	char *buf = NULL;
+	size_t writesize = min(count, (size_t)MAX_TRANSFER);
 
 	dev = (struct usb_skel *)file->private_data;
 
@@ -167,6 +174,12 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou
 	if (count == 0)
 		goto exit;
 
+	/* limit the number of URBs in flight to stop a user from using up all RAM */
+	if (down_interruptible(&dev->limit_sem)) {
+		retval = -ERESTARTSYS;
+		goto exit;
+	}
+
 	/* create a urb, and a buffer for it, and copy the data to the urb */
 	urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!urb) {
@@ -174,13 +187,13 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou
 		goto error;
 	}
 
-	buf = usb_buffer_alloc(dev->udev, count, GFP_KERNEL, &urb->transfer_dma);
+	buf = usb_buffer_alloc(dev->udev, writesize, GFP_KERNEL, &urb->transfer_dma);
 	if (!buf) {
 		retval = -ENOMEM;
 		goto error;
 	}
 
-	if (copy_from_user(buf, user_buffer, count)) {
+	if (copy_from_user(buf, user_buffer, writesize)) {
 		retval = -EFAULT;
 		goto error;
 	}
@@ -188,7 +201,7 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou
 	/* initialize the urb properly */
 	usb_fill_bulk_urb(urb, dev->udev,
 			  usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),
-			  buf, count, skel_write_bulk_callback, dev);
+			  buf, writesize, skel_write_bulk_callback, dev);
 	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
 	/* send the data out the bulk port */
@@ -202,11 +215,12 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou
 	usb_free_urb(urb);
 
 exit:
-	return count;
+	return writesize;
 
 error:
-	usb_buffer_free(dev->udev, count, buf, urb->transfer_dma);
+	usb_buffer_free(dev->udev, writesize, buf, urb->transfer_dma);
 	usb_free_urb(urb);
+	up(&dev->limit_sem);
 	return retval;
 }
 
@@ -238,13 +252,13 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
 	int retval = -ENOMEM;
 
 	/* allocate memory for our device state and initialize it */
-	dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 	if (dev == NULL) {
 		err("Out of memory");
 		goto error;
 	}
-	memset(dev, 0x00, sizeof(*dev));
 	kref_init(&dev->kref);
+	sema_init(&dev->limit_sem, WRITES_IN_FLIGHT);
 
 	dev->udev = usb_get_dev(interface_to_usbdev(interface));
 	dev->interface = interface;
@@ -330,7 +344,6 @@ static void skel_disconnect(struct usb_interface *interface)
 }
 
 static struct usb_driver skel_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"skeleton",
 	.probe =	skel_probe,
 	.disconnect =	skel_disconnect,
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index 08edbfcfca58..3fefdb0cbf07 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -403,7 +403,7 @@ static struct {
 	{ PCI_CHIP_MACH64GM, "3D RAGE XL (Mach64 GM, AGP)", 230, 83, 63, ATI_CHIP_264XL },
 	{ PCI_CHIP_MACH64GN, "3D RAGE XL (Mach64 GN, AGP)", 230, 83, 63, ATI_CHIP_264XL },
 	{ PCI_CHIP_MACH64GO, "3D RAGE XL (Mach64 GO, PCI-66/BGA)", 230, 83, 63, ATI_CHIP_264XL },
-	{ PCI_CHIP_MACH64GR, "3D RAGE XL (Mach64 GR, PCI-33MHz)", 230, 83, 63, ATI_CHIP_264XL },
+	{ PCI_CHIP_MACH64GR, "3D RAGE XL (Mach64 GR, PCI-33MHz)", 235, 83, 63, ATI_CHIP_264XL | M64F_SDRAM_MAGIC_PLL },
 	{ PCI_CHIP_MACH64GL, "3D RAGE XL (Mach64 GL, PCI)", 230, 83, 63, ATI_CHIP_264XL },
 	{ PCI_CHIP_MACH64GS, "3D RAGE XL (Mach64 GS, PCI)", 230, 83, 63, ATI_CHIP_264XL },
 
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 4f01ccc02aa4..156db84cb363 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -594,7 +594,7 @@ static int __devinit radeon_probe_pll_params(struct radeonfb_info *rinfo)
 }
 
 /*
- * Retreive PLL infos by different means (BIOS, Open Firmware, register probing...)
+ * Retrieve PLL infos by different means (BIOS, Open Firmware, register probing...)
  */
 static void __devinit radeon_get_pllinfo(struct radeonfb_info *rinfo)
 {
@@ -660,17 +660,17 @@ static void __devinit radeon_get_pllinfo(struct radeonfb_info *rinfo)
 
 #ifdef CONFIG_PPC_OF
 	/*
-	 * Retreive PLL infos from Open Firmware first
+	 * Retrieve PLL infos from Open Firmware first
 	 */
        	if (!force_measure_pll && radeon_read_xtal_OF(rinfo) == 0) {
-       		printk(KERN_INFO "radeonfb: Retreived PLL infos from Open Firmware\n");
+       		printk(KERN_INFO "radeonfb: Retrieved PLL infos from Open Firmware\n");
 		goto found;
 	}
 #endif /* CONFIG_PPC_OF */
 
 	/*
 	 * Check out if we have an X86 which gave us some PLL informations
-	 * and if yes, retreive them
+	 * and if yes, retrieve them
 	 */
 	if (!force_measure_pll && rinfo->bios_seg) {
 		u16 pll_info_block = BIOS_IN16(rinfo->fp_bios_start + 0x30);
@@ -682,7 +682,7 @@ static void __devinit radeon_get_pllinfo(struct radeonfb_info *rinfo)
 		rinfo->pll.ppll_min	= BIOS_IN32(pll_info_block + 0x12);
 		rinfo->pll.ppll_max	= BIOS_IN32(pll_info_block + 0x16);
 
-		printk(KERN_INFO "radeonfb: Retreived PLL infos from BIOS\n");
+		printk(KERN_INFO "radeonfb: Retrieved PLL infos from BIOS\n");
 		goto found;
 	}
 
@@ -691,7 +691,7 @@ static void __devinit radeon_get_pllinfo(struct radeonfb_info *rinfo)
 	 * probe them
 	 */
 	if (radeon_probe_pll_params(rinfo) == 0) {
-		printk(KERN_INFO "radeonfb: Retreived PLL infos from registers\n");
+		printk(KERN_INFO "radeonfb: Retrieved PLL infos from registers\n");
 		goto found;
 	}
 
@@ -702,7 +702,7 @@ static void __devinit radeon_get_pllinfo(struct radeonfb_info *rinfo)
 
 found:
 	/*
-	 * Some methods fail to retreive SCLK and MCLK values, we apply default
+	 * Some methods fail to retrieve SCLK and MCLK values, we apply default
 	 * settings in this case (200Mhz). If that really happne often, we could
 	 * fetch from registers instead...
 	 */
@@ -2393,7 +2393,7 @@ static int radeonfb_pci_register (struct pci_dev *pdev,
 	       rinfo->mapped_vram/1024);
 
 	/*
-	 * Map the BIOS ROM if any and retreive PLL parameters from
+	 * Map the BIOS ROM if any and retrieve PLL parameters from
 	 * the BIOS. We skip that on mobility chips as the real panel
 	 * values we need aren't in the ROM but in the BIOS image in
 	 * memory. This is definitely not the best meacnism though,
diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c
index ad60bbb16cdf..a1f2c5e8fc88 100644
--- a/drivers/video/matrox/matroxfb_maven.c
+++ b/drivers/video/matrox/matroxfb_maven.c
@@ -1288,18 +1288,13 @@ static int maven_detach_client(struct i2c_client* client) {
 	return 0;
 }
 
-static int maven_command(struct i2c_client* client, unsigned int cmd, void* arg) {
-	return -ENOIOCTLCMD;	/* or -EINVAL, depends on who will call this */
-}
-
 static struct i2c_driver maven_driver={
-	.owner		= THIS_MODULE,
-	.name		= "maven",
+	.driver = {
+		.name	= "maven",
+	},
 	.id		= I2C_DRIVERID_MGATVO,
-	.flags		= I2C_DF_NOTIFY,
 	.attach_adapter	= maven_attach_adapter,
 	.detach_client	= maven_detach_client,
-	.command	= maven_command,
 };
 
 /* ************************** */
diff --git a/drivers/w1/dscore.c b/drivers/w1/dscore.c
index 15fb250451e5..b9146306df49 100644
--- a/drivers/w1/dscore.c
+++ b/drivers/w1/dscore.c
@@ -52,7 +52,6 @@ static int ds_send_control_cmd(struct ds_device *, u16, u16);
 
 
 static struct usb_driver ds_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"DS9490R",
 	.probe =	ds_probe,
 	.disconnect =	ds_disconnect,
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c
index 14016b1cd948..024206c4a0e4 100644
--- a/drivers/w1/w1.c
+++ b/drivers/w1/w1.c
@@ -142,12 +142,12 @@ static struct bin_attribute w1_slave_attr_bin_id = {
 /* Default family */
 static struct w1_family w1_default_family;
 
-static int w1_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size);
+static int w1_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size);
 
 static struct bus_type w1_bus_type = {
 	.name = "w1",
 	.match = w1_master_match,
-	.hotplug = w1_hotplug,
+	.uevent = w1_uevent,
 };
 
 struct device_driver w1_master_driver = {
@@ -361,7 +361,7 @@ void w1_destroy_master_attributes(struct w1_master *master)
 }
 
 #ifdef CONFIG_HOTPLUG
-static int w1_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
+static int w1_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
 {
 	struct w1_master *md = NULL;
 	struct w1_slave *sl = NULL;
@@ -377,7 +377,7 @@ static int w1_hotplug(struct device *dev, char **envp, int num_envp, char *buffe
 		event_owner = "slave";
 		name = sl->name;
 	} else {
-		dev_dbg(dev, "Unknown hotplug event.\n");
+		dev_dbg(dev, "Unknown event.\n");
 		return -EINVAL;
 	}
 
@@ -386,18 +386,18 @@ static int w1_hotplug(struct device *dev, char **envp, int num_envp, char *buffe
 	if (dev->driver != &w1_slave_driver || !sl)
 		return 0;
 
-	err = add_hotplug_env_var(envp, num_envp, &cur_index, buffer, buffer_size, &cur_len, "W1_FID=%02X", sl->reg_num.family);
+	err = add_uevent_var(envp, num_envp, &cur_index, buffer, buffer_size, &cur_len, "W1_FID=%02X", sl->reg_num.family);
 	if (err)
 		return err;
 
-	err = add_hotplug_env_var(envp, num_envp, &cur_index, buffer, buffer_size, &cur_len, "W1_SLAVE_ID=%024LX", (u64)sl->reg_num.id);
+	err = add_uevent_var(envp, num_envp, &cur_index, buffer, buffer_size, &cur_len, "W1_SLAVE_ID=%024LX", (u64)sl->reg_num.id);
 	if (err)
 		return err;
 
 	return 0;
 };
 #else
-static int w1_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
+static int w1_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
 {
 	return 0;
 }