aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2006-01-06 16:34:21 -0500
committerLen Brown <len.brown@intel.com>2006-01-06 16:34:21 -0500
commit25da0974601fc8096461f3d3f7ca3aab8e79adfb (patch)
treef9b3c1bfbc63fdb6a94e82177b8c3ae891125422 /drivers
parent036d25f79ddfbc9878da24ef8e468a6d22caa605 (diff)
parentd99cf9d679a520d67f81d805b7cb91c68e1847f0 (diff)
Auto-update from upstream
Diffstat (limited to 'drivers')
-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/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/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.c39
-rw-r--r--drivers/macintosh/therm_pm72.c7
-rw-r--r--drivers/macintosh/windfarm_lm75_sensor.c7
-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.c1
-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/video/cpia_pp.c30
-rw-r--r--drivers/media/video/cpia_usb.c1
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c1
-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.c7
-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/w1/dscore.c1
-rw-r--r--drivers/w1/w1.c14
617 files changed, 45607 insertions, 19571 deletions
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c
index 27ec12c1fab..b69a8cad82b 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 0c561c571f2..1278aca96fe 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 31218e1d2a1..0745d20afb8 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 934149c1512..f0eff3dac58 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 fa601b085eb..29f6af554e7 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 db65fd0babe..df7fdabd073 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 8615b42b517..fd8059920db 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 a95844790f7..281d26784d2 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 3b419c9a1e7..2b905016664 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 59dacb6552c..5b3d5e9ddcb 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 bc3ca6a656b..58801d718cc 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 8827dafba94..0f81731bdfa 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 adbc3148c03..96370ec1d67 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 70eaa5c7ac0..21097a39a05 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 7b1cd93892b..139cbba7618 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 c3441b3f086..d2815b7a915 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 cf1822a6361..9bddb687487 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 f7e765a1d31..a5b857c5c4b 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 96c664af8d0..a452b13620a 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 9e268ddedfb..33d6f237b2e 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 17ff4056125..c0d2854dd09 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 68c60a5bcda..ffd6abd6d5a 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 1ded3b43345..9251f4131b5 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 bfb23d543ff..a05fe5843e6 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 2d518aa2720..063f0304a16 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 8e7fb355177..3e7a067cc08 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 067e27893e4..8947c8837da 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 f36c563d72c..9888bc15175 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 394796315ad..9446960ac74 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 d2a0add19cc..e522d19ad88 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 529a28a3209..7b4bff4cfa2 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 dec5980a1cd..0449bc45ae5 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 057cb2b6e6d..92382e82328 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 ac96de15d83..378e88d2075 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 2b6b1d772ed..73dfdcebfbb 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 84e68cdd451..5ebd06b1b4c 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 66e53dd450f..40a67c86420 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 6f673d2de0b..49769f59ea1 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 e9b87a78622..00342a677c9 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 1f56b4cf0f5..561430ed94a 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/n_hdlc.c b/drivers/char/n_hdlc.c
index c3660d8781a..a133a62f3d5 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 61681c9f3f7..649677b5dc3 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 4c698d908ff..46eb371bf17 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 2c326ea5342..cf45b100eff 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 7999da25fe4..bdfdfd28594 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 344001b45af..a6544790af6 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 b5be8b11104..3800835ca8f 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 092e9b13375..1533f56baa4 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 815902c2c85..a9163d02983 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 2ed5c4363b5..39543a2bed0 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 17741111246..e69fd8dd1f1 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/ide/ide-cd.c b/drivers/ide/ide-cd.c
index b4d7a3efb90..d31117eb95a 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 449522f0540..4b441720b6b 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 9e293c8063d..fba3fffc2d6 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 ecfafcdafea..b5dc6df8e67 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 7d7944ed415..fab9b2b0250 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 8af179b531c..4b524f6b3ec 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 ef79805218e..4c2af902090 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 00000000000..33da10a2532
--- /dev/null
+++ b/drivers/ieee1394/.gitignore
@@ -0,0 +1 @@
+oui.c
diff --git a/drivers/ieee1394/Kconfig b/drivers/ieee1394/Kconfig
index 25103a0ef9b..39142e2f804 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 e8b4d48d376..6f53611fe25 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 61ddd5d37ef..15773544234 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 28c5f4b726e..cecd5871f2d 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 b79ddb43e74..9fb2769d9ab 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 cbbbe14b884..196db743927 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 c9e92d85c89..30fa0d43a43 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 997e1bf6297..734b121a055 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 aeeaeb670d0..ba09741fc82 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 ae9b02cc013..07d188ca849 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 f92b566363d..15670398634 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 b634a9bb365..936d776de00 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 32a1e016c85..25ef5a86f5f 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 0b31429d0a6..b35466023f0 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 0aa876360f9..3fe2f6c4a25 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 615541b8b90..f26680ebef7 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 0ea37b1bccb..082c7fd239f 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 3a2f0c02fd0..0b26616e16c 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 4cf9b8f3e33..b6b96fa04d6 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 cc66c1cae25..7df0962144e 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 6b1ab875333..e2edc41e1b6 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 24411e666b2..b0523563991 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 f7e18ccc5c0..18d7eda3885 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 cd425be7484..900ea1d25e7 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 23911da5015..608479b2df1 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 08648b1a387..1f1743c5c9a 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 475d98fa9e2..780009c7eaa 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 ef3ee035bbc..ed0c2ead8bc 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 9f2352bd834..a1e660e3531 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 bdd2a7fc268..ef5824c8846 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 64b4a308098..bc2fce60f9f 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 fbb69ef6a77..8e530cc970e 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 27391c32f3e..2a2b03ff096 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 5f5a5ae740d..969da40c424 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 6fc6868de0b..062fb8f0739 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 f8457ef4882..ca5b4a3b683 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 dc334aab433..6f5213a18a8 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 8e192a3a349..99cb0f3d59a 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 0ddef1bf778..4e5c14c7240 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 c34c96d1890..228e1852a83 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 f38696622eb..5e1f5e9653c 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]);
@@ -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 190878eef99..435427daed7 100644
--- a/drivers/macintosh/therm_pm72.c
+++ b/drivers/macintosh/therm_pm72.c
@@ -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/windfarm_lm75_sensor.c b/drivers/macintosh/windfarm_lm75_sensor.c
index a0a41ad0f2b..c62ed68a313 100644
--- a/drivers/macintosh/windfarm_lm75_sensor.c
+++ b/drivers/macintosh/windfarm_lm75_sensor.c
@@ -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 00000000000..a7afec6b19c
--- /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 252d55df964..76a189ceb52 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 cf663105668..a601a427885 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 1a77f326570..f9035bfd1a9 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 07d44e19536..561bda5011e 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 a76349cb10a..efe4adf7853 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 6b0fc167092..6cfa8d435d5 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 ab54f99b7c3..4b9dd8fb1e5 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 a6d3baa46f6..a6f2dc66c3d 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 930b9fc2795..0e481512f91 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 e38c3fc1a1d..4eaf075da21 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 0248f8e7eac..a7a5ab55433 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 eb703648597..ca99979c868 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 946efef3a8f..777585458c8 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 8175a2a222d..1b76fb29fb7 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 145cdc5ad00..e6aa309a66d 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 fece3277c2a..abbca150202 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 229d7b20429..a06ff91f27e 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 713dc9c2c73..9e658e519a2 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 fafc4bc045f..54f4a9847e3 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 0000d162d19..8c823d686a6 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 0a78ba3737a..a6c91db40ad 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 336fc284fa5..b996fb59b7e 100644
--- a/drivers/media/dvb/cinergyT2/cinergyT2.c
+++ b/drivers/media/dvb/cinergyT2/cinergyT2.c
@@ -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 8c7beffb045..ce44aa6bbb8 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 3fe383f4bb4..d05fab01ccc 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 aa271a2496d..52ac3e5adf5 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 6a0912eab39..55802fba3c2 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 f98e306a575..450417a9e64 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 b595476332c..6e2bac87344 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 1841a66427b..fac48fc7a4a 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 6fd67657c26..14f1911c79b 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 de13c04e8e6..afa00fdb5ec 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 75765e3a569..3835235b68d 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/video/cpia_pp.c b/drivers/media/video/cpia_pp.c
index ddf184f95d8..6861d408f1b 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 9774e94d1e7..1439cb75287 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/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index 06d76879bde..3a56120397a 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/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index 4262a22adc2..537836068c4 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 bac8eb4186d..6c48d1f54ac 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 602138f8544..959d2c5951b 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 a628be9bbba..ba61e182885 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 e0a8bb8ba7d..17e9757e728 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 b7b9846ff3f..93a16fa3c4b 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 971fda4b8b5..d3cba12f4bd 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 5c0e307d1d5..ce332a6085e 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 43a942a29c2..fef67710388 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 151b228e1cb..ac06f10c54e 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 10432f66520..3bba7aa82e5 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 9eefedb1621..90628562851 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 8eb50cdb8ae..ee183053fa2 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 0fb9c4e2ad4..64130227574 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 9c339a2505b..9bb9859f6df 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 f283b5bafdd..5b1febed313 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 3c3a7abebb1..89daf67b764 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 561d63304d7..6502b817df5 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 d559a175836..2a0c42b8cda 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 9f1744c3933..f9e5a23697a 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 4eb53258842..49216744693 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 ee7075fa1ec..c5b656cdea7 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 abcf19116d7..8e380c14bf6 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 3f4a66ca955..ec701667abf 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 af24216a062..f0f8916da7a 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 30bee11c48b..d2102a27d30 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 ebd7313d7fc..e2fa29b612c 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 4cffd34442a..b74a7cb5bae 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 cf50384b469..5cdae2bc055 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 d2f34d5a808..f3f5825469d 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 673a30af566..5ee2cef5b03 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 f8fce396119..854ddfb90da 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 e4091cd8d65..28f2a2fd1b5 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 94cec3cf2a1..2582d98ef5c 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 00000000000..32d13da43a0
--- /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 1433e91db0f..015c7f1d1bc 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 53b41d99b00..2c5b849b7ba 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 434b2558685..6d0d24a6364 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 3f653a93e1b..e02e9ba2e18 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 8eae8ba27e8..c88f1a3c1b1 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 a267c5235fc..136fc031e4a 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 76ce12809a1..7caa35748ce 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 e0ae248b431..438a931fd55 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 0f030b73cbb..146f9513aea 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 5065ba82cb7..94a91da84fb 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 cfa3cd7c91a..765e810620f 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 e85eb216fb5..d527cf2f9c1 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 00000000000..10d34cb1919
--- /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 c22c0517883..fa176ffb4ad 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 3961a754e92..31867e4b891 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 00000000000..2fec2415651
--- /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 00000000000..fd38351ceaa
--- /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 00000000000..3595e107df2
--- /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 00000000000..e93a1ef5b8a
--- /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 00000000000..d82651a97ba
--- /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 00000000000..48a3a891d3a
--- /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 00000000000..3ac1af2771d
--- /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 00000000000..42a73e357af
--- /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 00000000000..e8aee2f81aa
--- /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 00000000000..d090d1884fb
--- /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 00000000000..a433e24b0a5
--- /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 00000000000..09f03f493be
--- /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 00000000000..bd686cb6305
--- /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 00000000000..86aa08ea0c3
--- /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 00000000000..5c7ab756405
--- /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 00000000000..fe92bb056ac
--- /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 f857ae94d26..b0c3b6ab626 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 71fd41122c9..48774efeec7 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 d83fdd8c194..1c3c9c666f7 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 8bb4e85689e..01ddfc8cce3 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 b9355d9498a..2827a48ea37 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 356f5090922..28fe2fb4d6c 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 b6c140eb979..b9c7e39576f 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 980d7e5d66c..4a232254a49 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 818c185d643..d85b758f3ef 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 c7cca842e5e..0122415dfee 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 ce143f08638..049c34b3706 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 c782a632980..fa39b944bc4 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 1bd22cd40c7..87ee3271b17 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 a842ecc60a3..9369f811075 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 0c1e114527f..9315046b3f5 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 669dd52c412..89c46787676 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 419aad7f10e..852a6a899d0 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 1d4d88680db..3d95fa20cd8 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 de3c06735d1..4233ea55670 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 7653d6e33aa..afd900d5d73 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 2dc5728e3ef..778d9e618eb 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 bdc1a5eaaae..daa9a8d154f 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 b71769ae460..4265ed91a9c 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 ae734393475..9a76ac180b1 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 5cece25c034..00000000000
--- 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 00d683063c0..b538e303805 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 ee123c15f54..2efdacc290e 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 00000000000..f5d697c0c03
--- /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 00000000000..95518921001
--- /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 2fc9893d69e..eb86b059809 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 942fae0f213..c2506b56a18 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 00000000000..dae3ea6bb18
--- /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 f3b1df9e2cd..00000000000
--- 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 00e55165b76..24f7967aab6 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 7a92b1cbd6a..ee866fd6957 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 e328547599d..a496460ce22 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 5e53c5258a3..e4729ddf29f 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 17d1fd90f83..d6f4a5a3e55 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 fc62235bfc2..353ccb93134 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 2643976a667..8bc0b528548 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 3d2ea61033b..3d2ea61033b 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 77d2a21d4cd..44cd3fcd157 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 7c65b10bb16..f6c51441fa8 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 5e7c7e944c9..cdfe5020775 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 1c98db0652c..e65620a4d79 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 92793b958e3..bf6271ee387 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 dc1128a0097..b664708481c 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 70fd6fd8feb..319180ca7e7 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 b1bbc8e8e91..fee4be1ce81 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 c822cad3333..7e2039f52c4 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 724a715089c..f2d59756815 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 978fdc60678..48e10b0c7e7 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 725a14119f2..b8241561da4 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 075c7eb5c85..9ee67321b63 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 ce1e2aad8b1..d6c77658231 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 24e6aacddb7..158d9256325 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 c6493ad7c0c..18e85ccdae6 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 4b48b31ec23..b62aee8de3c 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 9cb3ab156b0..ea62bed6bc8 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 e1743be3190..1c97e7dd130 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 a9046d4b8af..7146b69b812 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 6527b36c9a6..294849d2459 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 3a4f49f4eff..f28ebdd3958 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 309eb557f9a..1f4ad0e7836 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 87302c548c2..971a3528164 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 2dc3e611a9a..120fa8da639 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 a30aa74304a..613f2f1fbfd 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 55867bc7f19..7b37eba35bf 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 7f8219f3fd9..0252582b91c 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 561706ba449..b39435bbfae 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 f3fdc748659..7979c85df3d 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 b98cac7bda9..9c14599d067 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 4d56bc9926d..35a92d1e494 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 078579ae635..071cf485e1a 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 356a6fb416a..70d5f0748d5 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 6d9f71cfcb3..0e07d953511 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 20642f0e7bf..f2789afb22b 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 5209d8c7764..5d957dfe23d 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 56c58831e80..b5fdeec20b1 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 0668384ebc8..51460936983 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 00960a379b9..5301ac60358 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 9e7ccd8a432..ea7d9ca160b 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 4a3150a7854..7a7744662d5 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 e3126386437..73bad1d5cb2 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 539b5cd1a59..d5b4ff74462 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 38a028c725d..24c547ef512 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 db91259dc50..1b277d2c1c9 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 ec6ab65f087..4145eb83b9b 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 bd7c966ea2d..0ecbe4edbec 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 d3ccce706ab..15fb758a9e5 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 261668618b2..c4256aa32bc 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 6b7583f497d..a1f0b0ba2bf 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 f49674f0794..b154b3f52cb 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 c99a2fe92fb..9803c9352d7 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 6e7d7b06421..6f50cc9323d 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 7008d32433b..f779f674dfa 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 ab8754e566b..ba80fdea7eb 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 df31484d73a..a4f80bd735f 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 811060e10c0..96eb4825858 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 28cb4613b7f..8ec75dc08e2 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 9fab04f3056..2fb05c4a528 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 789595b3fa0..044b7537199 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 4fde4118899..2e727f49ad1 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 d428c909b8a..bf3a67c3cc5 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 5a6cef2dfa1..80f7f31310e 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 83f75774df6..56fa6916889 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 1efc9f21229..5ced2725d6c 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 5473c23fcb5..5acc0ace3d7 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 a1c52a68219..daf21e03b21 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 fb42cafbe57..95e25c1df92 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 e7bd7f37f08..e849289d4f3 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 fa3c23b80e3..7270808c02d 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 be20da49d14..44e4b4bb1c5 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 185bc73c3ec..7376bc87206 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 c50a9da420a..0ca987344e0 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 b978f7fe832..0b03714e696 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 555119cacc2..e565193650c 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 2004a6c4938..251ebd7a7d3 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 811c9d15063..fa3e4c0a253 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 a3aa056d724..11587ebb728 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 c1c89f4fd4e..23d12b65e5f 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 0e68fb511dc..04ceba343db 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 85a3026e690..143b6c25a4e 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 0adac8a6733..052832d03d3 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 12a24d4331a..db09c209098 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 45480a2bc4c..95a9462f9a9 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 eb39218b925..30a836ffc31 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 328e31cc685..fa385e761fe 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 00000000000..54328fec5ad
--- /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 e319e78b5ea..f87c785f203 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 0a3bb5a10dd..3a18443fdfa 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 c215e088973..d7f7494a0cb 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 4010f2bb85a..135ae04e6e7 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 a7efc394515..54885475492 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 6b63d21612e..e70af7f3994 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 0075894c71d..77dacb46573 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 df7647c3c10..ea817739256 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 f8f55cc468b..97f927c01a8 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 00000000000..566cc3d185b
--- /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 4191fd9d4d1..3bf46660351 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 87c2db1bd4f..66da840c931 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 00000000000..b385af31435
--- /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 e7ad269041a..4ce7438608e 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 362d78483d0..a8c83bb0363 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 9cb5dd48383..7894b8ea84b 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 20dd85a7781..3c606cf8c8c 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 cba9655d0f1..9f0ddbe6dc7 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 9df23b654ce..cb2ee25f213 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 83467a05dc8..d113290b5fc 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 00000000000..b8ee24d5748
--- /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 6aab9dacdee..1c8f872e2dd 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 d866213f42b..fd389e9f946 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 13f23043c8a..06d7601cdf5 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 b7b20c689c2..09ed05727bc 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 333d69dd84e..557788ec4ee 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 2ae31ceb32a..57295bcea3e 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 ccbbae2bf47..0920220f331 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 09bc81557b6..30a335349ce 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 5b9c2c5a7f0..66783c860a1 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 4cb1f3ed910..3c688ef5466 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 fa2cb3582cf..27acf78cf8d 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 6bec673c925..b639332131f 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 3d8009f5534..10bcf42cb65 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 d23ae68fae0..855f2dfd18a 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 d0a0fdbd0fc..f55b9b3f7b3 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 2282c04fee4..cfbceb50471 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 8ebaa694d18..e03ce48b7b4 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 3062b39fbdb..38ffa8d6e62 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 89e8222bc7c..5625a8c2a8f 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 d527d05a607..f1e708946e6 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 084e7628ce1..ed6c81660e0 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 bcc29ec126d..20f1a0713db 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 259eeb161b8..a1f751e7940 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 86c41981188..1ea565e0561 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 07498118359..b7a603a4532 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 507a6af56f4..fbead786031 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 c63275e66e2..9ee8218404c 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 e2c08c5d83f..7b785ade8b0 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 4f0466fbd5f..fa681a934ff 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 578143e93a6..4a6feb1e5e3 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 7363e12663a..17419e30ffc 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 4b5d420d2f4..d18a4bc2498 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 644b91bdb02..882fb1a0b57 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 243470936fa..32350707b94 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 05c7b83cef0..6a7bef2e611 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 7c530649983..0c9edb7051f 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 db8f5cd85ff..788c58d805f 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 050ea13ff80..9e3ab3fd535 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 f8b94308271..b66b140a745 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 bb091a45a88..dce7e687fd4 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 98b64b2aa8e..3a4dd6f5b81 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 f557f17ca00..e8df0c9ec1e 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 c1c1c687bcb..5205c4e7d6f 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 b169687d08f..40c0de12588 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 00000000000..6c7165f47e2
--- /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 00000000000..5977795854f
--- /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 48e460eef05..2efca52dff5 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 7b3efd53129..79d8a914f9d 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 fedcb0d3fc7..bec81adcf4f 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 c46d2469b85..7d973bd9022 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 c58c9d97b04..24304300d7b 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 5b1c12041a4..5ec5f44602a 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 9321cdf4568..cd54244058b 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 4954896dfdb..c0cf52cb975 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 2691625f9bc..3d1ea09a06a 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 a8987f5ff5c..de05e2883f9 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 36091868560..b017f85e6d6 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 e0d6f194f54..923130185a9 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 32e12620b16..2df8c5632ac 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 6e7f7c83a75..668373590aa 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 ac7b0d819eb..bc87c16c80d 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 b2422a0f25c..9635ca70097 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 c76215692da..6d5b0a794cf 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 fcfa486965b..2e2c3b7acb0 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 e69477d1889..f01ec0a7c50 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 c0ae9e965f6..a2333d2c7af 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 dc249cb970e..ba93d6e66d4 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 d632d9e1493..f04e7e11f57 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 4e6709f448e..05ebb9cef96 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 46349293de0..ea7f3a43357 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 2a1a99a2ef5..685b997306c 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 38a53b5f9e9..46da6fe10ad 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 03fcbab3003..32d4d8d7b9f 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 b55c2a8a547..221e96e2620 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 fb4012b5c18..a4d9be7c687 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 78274dc91f5..9dde8df2f5c 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 dd592f6a252..c4aade8f534 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 790acac160b..411209048d7 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 c041bfd56e1..25cced91c8a 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 2d9437d7242..3659dd7b9d7 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 fd36cf9858c..9916a2a2255 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 43f6810a404..66ec35beab5 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 cdd92d82f4b..7b39f4a35e9 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 7ea7151f5d1..851f2706f22 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 7fc0b97173e..1fffd2b3c65 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 d3d52f14d7c..cc92d0c70cd 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 1564ca203a3..8260f040d39 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 3a264a40821..2456090bb24 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 a34d403ccc6..92bf9b14a7a 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 994b7566bca..15d69298ab6 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 1538bede527..bdfbbb083b6 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 20ae2b17df5..00000000000
--- 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 139cd0e12e6..00000000000
--- 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 b8727d9bf69..1288d6203e9 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 7ce0c7e66d3..96969cb960a 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 57c0c6e3fbe..d3a7b0c3d38 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 a50c2bc506f..3639c3f8d35 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 f429862e097..550ddfa71a4 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 85099718c68..4c4a776ab1c 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 9d59dc62e6d..af0a41e7870 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 d0cbbb7f038..b2833614865 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 00000000000..7d2a679989e
--- /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 2e6593e6c1b..9baa6296fc9 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 7fe7fb484d1..5c76e3aaaa5 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 50858273f8d..3ad9ee8b84a 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 1b475141297..248279e44c9 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 963a5dfd209..fd2aaccdcba 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 5f8af35e763..f13f004d311 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 357e75335f1..dba4cc02607 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 86d5c380892..28329ddf187 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 419c9943a7c..ad742cec94f 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 83e815d3cd5..2684e15b813 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 b1d6e9af732..2b68998fe4b 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 00000000000..076462c8ba2
--- /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 da24c31ee00..0018bbc4de3 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 c8a1b350e2c..591b5aad1a1 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 f78bd124d29..650d5ee5871 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 bf23f897802..29d5f45a845 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 fe74f99ca5f..319de03944e 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 e80ef946782..13d1d367f7f 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 1c4a68499dc..4647e1ebc68 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 c655d46c8ae..9734cb76dd6 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 ea09aaa3cab..0cea9782d7d 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 b35ac6d334f..65e084a2c87 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 58321d3f314..e3020f4b17b 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 29f52a44b92..9dd3d14c64f 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 82caf336e9b..69b0b9be7a6 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 13f73a836e4..08ca0f849da 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 bf03ec0d8ee..9b13bf2fa98 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 0eaabeb37ac..641268d7e6f 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 82f64986bc2..584b8dc6511 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 c6fec96785f..a1b7c3813d3 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 bf1d9abc07a..a4b12404ae0 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 72e3b12a192..4b2226d77b3 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 9d65ec30799..acde8868da2 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 e46528c825b..3ef2c0cdf1d 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 a7722a6a5a5..517360b77d8 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 e73faf831b2..466384d7c79 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 151154df37f..5832953086f 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 79efaf7d86a..dfe121d3588 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 e576db57a92..8b4b887a7d4 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 7e46887d9e1..b6076004a43 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 1d973bcf56a..049871145d6 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 950543aa5ac..458f2acdeb0 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 1e53934907c..509dd0a04c5 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 07cb17db42f..d512d9f488f 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 a32558b4048..df29b8078b5 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 0e2505c073d..a6693b0d1c4 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 15840db092a..1949b54f41f 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 9a2a47db949..f7bdc506e61 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 00000000000..ab1a1ae24be
--- /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 26ca5b890a6..b44d398de07 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 a3e44ef1df4..5f52979af1c 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 1220a5004a5..192a03b2897 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 440377c7a0d..4dff8473553 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 4a50acb39d2..7618ae5c104 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 fd48e74e78e..f6d5cead542 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 a32cfe51b77..b4a051b549d 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 52cc18cd247..f018953a548 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 b7476233ef5..fdf0f788062 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 7420c6b8428..3b3c7b4120a 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 226b6f90a90..2f3edc26cb5 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 230f6b1b314..af526135d21 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 dc099bbe12b..48df4cfd5a4 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 43112f040b6..e278489a80c 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 f526aebea50..1bfc105ad4d 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 27b23c55bbc..18d8eaf408d 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 7503f5b96f5..6a5700e9d42 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 ba41fc7b95c..a42c2229412 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 9fe2c2710d1..e2ede583518 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 036c485d1d1..3a0e8ce67eb 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 53099190952..359c4b2df73 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 5524fd70210..09ca6128ac2 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 f69e443cd1b..b2ae29af594 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 b2e66e3b90a..8d1a1c357d5 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 0fd0fa9fec2..774038b352c 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 44594061260..b0551cdb280 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 24efb21969c..4bd113325ef 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 0bc0b1247a6..1c73155c8d7 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 67612c81cb9..04d69339c05 100644
--- a/drivers/usb/media/w9968cf.c
+++ b/drivers/usb/media/w9968cf.c
@@ -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 b293db3c28c..449b2501acf 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 b33044d56a1..6671317b495 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 c8155209bf4..3824df33094 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 189986af2ac..52fea2e08db 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 1dc3e0f7301..d8cde101798 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 7e93ac96490..981d8a5fbfd 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 2703e205bc8..1336745b8f5 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 067a8148692..605a3c87e05 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 a30d4a6ee82..b3418d2bcc6 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 9590dbac5d9..384fa376980 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 41ef2b60675..3260d595441 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 85f3725334b..cc3dae3f34e 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 3c93921cb6b..877b081a3a6 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 605a2afe34e..84fa1728f05 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 1cabe7ed91f..4081990b7d1 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 17d0190ef64..611612146ae 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 542120ef1fd..54118169504 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 37ef365a247..be5f5e142dd 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 c008c981862..63f1f3ba8e0 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 f05cfb83c82..ec801e8bb1b 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 2455e9a8567..faf1e86be68 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 b5776518020..def3bb8e229 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 b3799b1a2b0..78e6a43b108 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 683e3df5d60..156a2f1cb39 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 89856aa0e3b..4fe863389cb 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 c0ecbab6f6b..49991ac1bf3 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 787dd3591d6..8ca52be2397 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 680d13957af..9c5ab251370 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 2f52261c7cc..f3a8e2807c3 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 1f29d883732..dbf1f063098 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 18022a74a3d..343f6f22822 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 84bc0ee4f06..4144777ea18 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 c9787001cf2..da46b351e18 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 e581e4ae848..6d18d4eaba3 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 af9290ed257..af18355e94c 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 dc74644a603..8fc414bd5b2 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 0b0546dcc7b..79a766e9ca2 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 06e04b442ff..eb863b3f2d7 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 773ea3eca08..00d45f8600d 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 35820bda7ae..452efce7271 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 53a47c31cd0..4ddac620fc0 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 8eadfb70560..e9719da2aca 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 dc4c498bd1e..faedbeb6ba4 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 5112d7aac05..123fa8a904e 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 c7c3a3c305f..e3463de99de 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 832b6d6734c..2edf9cabad2 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 d5d06648810..06d07cea0b7 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 7744b8148bc..2dd191f5fe7 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 19f329e9bdc..a5901042144 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 5cfc13b5e56..7472ed6bf62 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 cd4f48bd83b..b0441c35f98 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 a8951c0fd02..4e2f7dfb58b 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 9456dd9dd13..d9c21e27513 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 ca5dbadb9b7..b6d6cab9c85 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 3caf97072ac..762d8ff9a1e 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 7716000045b..3fd2405304f 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 41a45a5025b..f0372105619 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 c22bdc0c4df..f0215f850d2 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 205dbf7201d..abb830cb77b 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 0c4881d18cd..8bc8337c99c 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 238a5a871ed..d7d27c3385b 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 a473c1c3455..49b1fbe61f2 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 18c3183be76..a7c3c4734d8 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 c41d64dbb0f..92be101feba 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 44ab8f9978f..8cbba22508a 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 00000000000..4d3cbb12b71
--- /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 00000000000..a700f87d080
--- /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 5a9321705a7..01e430654a1 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 7372386f33d..4c1b2bd2e2e 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 00000000000..b28151d1b60
--- /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 89401a59f95..55ee2d36d58 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 02bff01ab09..845bed4b803 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 0ea2f5ab66b..fb8bacaae27 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 c9d78d6188b..c03089a9ec3 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 0a362cc781a..633a715850a 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 f5f47a34b16..dc301e567cf 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 3847ebed2aa..dbcf23980ff 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 98b09711a73..7259fd1f6b0 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 6c3a53f8f26..5d02f16b7d0 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 08edbfcfca5..3fefdb0cbf0 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 4f01ccc02aa..156db84cb36 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/w1/dscore.c b/drivers/w1/dscore.c
index 15fb250451e..b9146306df4 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 14016b1cd94..024206c4a0e 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;
}